1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/svdobj.hxx>
21 #include <config_features.h>
23 #include <sal/config.h>
24 #include <sal/log.hxx>
25 #include <rtl/ustrbuf.hxx>
27 #include <com/sun/star/lang/XComponent.hpp>
28 #include <com/sun/star/text/RelOrientation.hpp>
30 #include <basegfx/matrix/b2dhommatrix.hxx>
31 #include <basegfx/matrix/b2dhommatrixtools.hxx>
32 #include <basegfx/polygon/b2dpolygon.hxx>
33 #include <basegfx/polygon/b2dpolygontools.hxx>
34 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
35 #include <basegfx/polygon/b2dpolypolygontools.hxx>
36 #include <basegfx/range/b2drange.hxx>
37 #include <drawinglayer/processor2d/contourextractor2d.hxx>
38 #include <drawinglayer/processor2d/linegeometryextractor2d.hxx>
39 #include <editeng/editeng.hxx>
40 #include <editeng/outlobj.hxx>
41 #include <o3tl/deleter.hxx>
43 #include <svl/grabbagitem.hxx>
44 #include <tools/bigint.hxx>
45 #include <tools/diagnose_ex.h>
46 #include <tools/helpers.hxx>
47 #include <unotools/configmgr.hxx>
48 #include <vcl/canvastools.hxx>
49 #include <vcl/ptrstyle.hxx>
52 #include <svx/shapepropertynotifier.hxx>
53 #include <svx/svdotable.hxx>
55 #include <svx/sdr/contact/displayinfo.hxx>
56 #include <sdr/contact/objectcontactofobjlistpainter.hxx>
57 #include <svx/sdr/contact/viewcontactofsdrobj.hxx>
58 #include <sdr/properties/emptyproperties.hxx>
59 #include <svx/sdrhittesthelper.hxx>
60 #include <svx/sdrobjectuser.hxx>
61 #include <svx/sdrobjectfilter.hxx>
62 #include <svx/svddrag.hxx>
63 #include <svx/svdetc.hxx>
64 #include <svx/svdhdl.hxx>
65 #include <svx/svditer.hxx>
66 #include <svx/svdmodel.hxx>
67 #include <svx/svdoashp.hxx>
68 #include <svx/svdocapt.hxx>
69 #include <svx/svdocirc.hxx>
70 #include <svx/svdoedge.hxx>
71 #include <svx/svdograf.hxx>
72 #include <svx/svdogrp.hxx>
73 #include <svx/svdomeas.hxx>
74 #include <svx/svdomedia.hxx>
75 #include <svx/svdoole2.hxx>
76 #include <svx/svdopage.hxx>
77 #include <svx/svdopath.hxx>
78 #include <svx/svdorect.hxx>
79 #include <svx/svdotext.hxx>
80 #include <svx/svdouno.hxx>
81 #include <svx/svdovirt.hxx>
82 #include <svx/svdpage.hxx>
83 #include <svx/svdpool.hxx>
84 #include <svx/strings.hrc>
85 #include <svx/dialmgr.hxx>
86 #include <svx/svdtrans.hxx>
87 #include <svx/svdundo.hxx>
88 #include <svx/svdview.hxx>
89 #include <sxlayitm.hxx>
90 #include <sxlogitm.hxx>
91 #include <sxmovitm.hxx>
92 #include <sxoneitm.hxx>
93 #include <sxopitm.hxx>
94 #include <sxreoitm.hxx>
95 #include <sxrooitm.hxx>
96 #include <sxsaitm.hxx>
97 #include <sxsoitm.hxx>
98 #include <sxtraitm.hxx>
99 #include <svx/unopage.hxx>
100 #include <svx/unoshape.hxx>
101 #include <svx/xfillit0.hxx>
102 #include <svx/xflclit.hxx>
103 #include <svx/xfltrit.hxx>
104 #include <svx/xlineit0.hxx>
105 #include <svx/xlnclit.hxx>
106 #include <svx/xlnedwit.hxx>
107 #include <svx/xlnstwit.hxx>
108 #include <svx/xlntrit.hxx>
109 #include <svx/xlnwtit.hxx>
110 #include <svx/svdglue.hxx>
111 #include <svx/svdsob.hxx>
112 #include <svdobjplusdata.hxx>
113 #include <svdobjuserdatalist.hxx>
115 #include <unordered_set>
118 #include <libxml/xmlwriter.h>
121 using namespace ::com::sun::star
;
124 SdrObjUserCall::~SdrObjUserCall()
128 void SdrObjUserCall::Changed(const SdrObject
& /*rObj*/, SdrUserCallType
/*eType*/, const tools::Rectangle
& /*rOldBoundRect*/)
132 SdrObjMacroHitRec::SdrObjMacroHitRec() :
138 SdrObjUserData::SdrObjUserData(SdrInventor nInv
, sal_uInt16 nId
) :
142 SdrObjUserData::SdrObjUserData(const SdrObjUserData
& rData
) :
143 nInventor(rData
.nInventor
),
144 nIdentifier(rData
.nIdentifier
) {}
146 SdrObjUserData::~SdrObjUserData() {}
148 SdrObjGeoData::SdrObjGeoData():
158 SdrObjGeoData::~SdrObjGeoData()
162 SdrObjTransformInfoRec::SdrObjTransformInfoRec() :
164 bResizeFreeAllowed(true),
165 bResizePropAllowed(true),
166 bRotateFreeAllowed(true),
167 bRotate90Allowed(true),
168 bMirrorFreeAllowed(true),
169 bMirror45Allowed(true),
170 bMirror90Allowed(true),
171 bTransparenceAllowed(true),
173 bEdgeRadiusAllowed(true),
174 bNoOrthoDesired(true),
176 bCanConvToPath(true),
177 bCanConvToPoly(true),
178 bCanConvToContour(false),
179 bCanConvToPathLineToArea(true),
180 bCanConvToPolyLineToArea(true) {}
182 struct SdrObject::Impl
184 sdr::ObjectUserVector maObjectUsers
;
185 std::shared_ptr
<DiagramDataInterface
> mpDiagramData
;
186 std::optional
<double> mnRelativeWidth
;
187 std::optional
<double> mnRelativeHeight
;
188 sal_Int16 meRelativeWidthRelation
;
189 sal_Int16 meRelativeHeightRelation
;
192 meRelativeWidthRelation(text::RelOrientation::PAGE_FRAME
),
193 meRelativeHeightRelation(text::RelOrientation::PAGE_FRAME
) {}
197 // BaseProperties section
199 std::unique_ptr
<sdr::properties::BaseProperties
> SdrObject::CreateObjectSpecificProperties()
201 return std::make_unique
<sdr::properties::EmptyProperties
>(*this);
204 sdr::properties::BaseProperties
& SdrObject::GetProperties() const
208 // CAUTION(!) Do *not* call this during SdrObject construction,
209 // that will lead to wrong type-casts (dependent on constructor-level)
210 // and thus eventually create the wrong sdr::properties (!). Is there
211 // a way to check if on the stack is a SdrObject-constructor (?)
212 const_cast< SdrObject
* >(this)->mpProperties
=
213 const_cast< SdrObject
* >(this)->CreateObjectSpecificProperties();
216 return *mpProperties
;
220 // ObjectUser section
222 void SdrObject::AddObjectUser(sdr::ObjectUser
& rNewUser
)
224 mpImpl
->maObjectUsers
.push_back(&rNewUser
);
227 void SdrObject::RemoveObjectUser(sdr::ObjectUser
& rOldUser
)
229 const sdr::ObjectUserVector::iterator aFindResult
=
230 std::find(mpImpl
->maObjectUsers
.begin(), mpImpl
->maObjectUsers
.end(), &rOldUser
);
231 if (aFindResult
!= mpImpl
->maObjectUsers
.end())
233 mpImpl
->maObjectUsers
.erase(aFindResult
);
238 // DrawContact section
240 std::unique_ptr
<sdr::contact::ViewContact
> SdrObject::CreateObjectSpecificViewContact()
242 return std::make_unique
<sdr::contact::ViewContactOfSdrObj
>(*this);
245 sdr::contact::ViewContact
& SdrObject::GetViewContact() const
249 const_cast< SdrObject
* >(this)->mpViewContact
=
250 const_cast< SdrObject
* >(this)->CreateObjectSpecificViewContact();
253 return *mpViewContact
;
256 // DrawContact support: Methods for handling Object changes
257 void SdrObject::ActionChanged() const
259 // Do necessary ViewContact actions
260 GetViewContact().ActionChanged();
263 SdrPage
* SdrObject::getSdrPageFromSdrObject() const
265 if(getParentSdrObjListFromSdrObject())
267 return getParentSdrObjListFromSdrObject()->getSdrPageFromSdrObjList();
273 SdrModel
& SdrObject::getSdrModelFromSdrObject() const
275 return mrSdrModelFromSdrObject
;
278 void SdrObject::setParentOfSdrObject(SdrObjList
* pNewObjList
)
280 if(getParentSdrObjListFromSdrObject() == pNewObjList
)
283 // remember current page
284 SdrPage
* pOldPage(getSdrPageFromSdrObject());
287 mpParentOfSdrObject
= pNewObjList
;
290 SdrPage
* pNewPage(getSdrPageFromSdrObject());
292 // broadcast page change over objects if needed
293 if(pOldPage
!= pNewPage
)
295 handlePageChange(pOldPage
, pNewPage
);
299 SdrObjList
* SdrObject::getParentSdrObjListFromSdrObject() const
301 return mpParentOfSdrObject
;
304 SdrObjList
* SdrObject::getChildrenOfSdrObject() const
306 // default has no children
310 void SdrObject::SetBoundRectDirty()
312 aOutRect
= tools::Rectangle();
316 // SdrObjectLifetimeWatchDog:
317 void impAddIncarnatedSdrObjectToSdrModel(const SdrObject
& rSdrObject
, SdrModel
& rSdrModel
)
319 rSdrModel
.maAllIncarnatedObjects
.insert(&rSdrObject
);
321 void impRemoveIncarnatedSdrObjectToSdrModel(const SdrObject
& rSdrObject
, SdrModel
& rSdrModel
)
323 if(!rSdrModel
.maAllIncarnatedObjects
.erase(&rSdrObject
))
325 SAL_WARN("svx","SdrObject::~SdrObject: Destructed incarnation of SdrObject not member of this SdrModel (!)");
330 SdrObject::SdrObject(SdrModel
& rSdrModel
)
331 : mpFillGeometryDefiningShape(nullptr)
332 ,mrSdrModelFromSdrObject(rSdrModel
)
335 ,mpParentOfSdrObject(nullptr)
337 ,mnNavigationPosition(SAL_MAX_UINT32
)
339 ,mpSvxShape( nullptr )
341 ,mbDoNotInsertIntoPageAutomatically(false)
344 bSnapRectDirty
=true;
348 bEmptyPresObj
=false;
349 bNotVisibleAsMaster
=false;
354 mbLineIsOutsideGeometry
= false;
357 mbSupportTextIndentingOnLineWidthChange
= false;
364 // SdrObjectLifetimeWatchDog:
365 impAddIncarnatedSdrObjectToSdrModel(*this, getSdrModelFromSdrObject());
369 SdrObject::~SdrObject()
371 // Tell all the registered ObjectUsers that the page is in destruction.
372 // And clear the vector. This means that user do not need to call RemoveObjectUser()
373 // when they get called from ObjectInDestruction().
374 sdr::ObjectUserVector aList
;
375 aList
.swap(mpImpl
->maObjectUsers
);
376 for(sdr::ObjectUser
* pObjectUser
: aList
)
378 DBG_ASSERT(pObjectUser
, "SdrObject::~SdrObject: corrupt ObjectUser list (!)");
379 pObjectUser
->ObjectInDestruction(*this);
383 SendUserCall(SdrUserCallType::Delete
, GetLastBoundRect());
384 o3tl::reset_preserve_ptr_during(pPlusData
);
386 pGrabBagItem
.reset();
387 mpProperties
.reset();
388 mpViewContact
.reset();
391 // SdrObjectLifetimeWatchDog:
392 impRemoveIncarnatedSdrObjectToSdrModel(*this, getSdrModelFromSdrObject());
396 void SdrObject::Free( SdrObject
*& _rpObject
)
398 SdrObject
* pObject
= _rpObject
; _rpObject
= nullptr;
400 if(nullptr == pObject
)
406 SvxShape
* pShape(pObject
->getSvxShape());
410 if(pShape
->HasSdrObjectOwnership())
412 // only the SvxShape is allowed to delete me, and will reset
413 // the ownership before doing so
418 // not only delete pObject, but also need to dispose uno shape
421 pShape
->InvalidateSdrObject();
422 uno::Reference
< lang::XComponent
> xShapeComp( pObject
->getWeakUnoShape(), uno::UNO_QUERY_THROW
);
423 xShapeComp
->dispose();
425 catch( const uno::Exception
& )
427 DBG_UNHANDLED_EXCEPTION("svx");
435 void SdrObject::SetRectsDirty(bool bNotMyself
, bool bRecursive
)
443 if (bRecursive
&& nullptr != getParentSdrObjListFromSdrObject())
445 getParentSdrObjListFromSdrObject()->SetSdrObjListRectsDirty();
449 void SdrObject::handlePageChange(SdrPage
* pOldPage
, SdrPage
* pNewPage
)
451 // The creation of the UNO shape in SdrObject::getUnoShape is influenced
452 // by pPage, so when the page changes we need to discard the cached UNO
453 // shape so that a new one will be created.
454 // If the page is changing to another page with the same model, we
455 // assume they create compatible UNO shape objects so we shouldn't have
457 // TTTT: This causes quite some problems in SvxDrawPage::add when used
458 // e.g. from Writer - the SdrObject may be cloned to target model, and
459 // the xShape was added to it by purpose (see there). Thus it will be
460 // good to think about if this is really needed - it *seems* to be intended
461 // for a xShape being a on-demand-creatable resource - with the argument that
462 // the SdrPage/UnoPage used influences the SvxShape creation. This uses
463 // resources and would be nice to get rid of anyways.
464 if(nullptr == pOldPage
|| nullptr == pNewPage
)
466 SvxShape
* const pShape(getSvxShape());
468 if (pShape
&& !pShape
->HasSdrObjectOwnership())
470 setUnoShape(nullptr);
475 // init global static itempool
476 SdrItemPool
* SdrObject::mpGlobalItemPool
= nullptr;
478 SdrItemPool
& SdrObject::GetGlobalDrawObjectItemPool()
480 if(!mpGlobalItemPool
)
482 mpGlobalItemPool
= new SdrItemPool();
483 SfxItemPool
* pGlobalOutlPool
= EditEngine::CreatePool();
484 mpGlobalItemPool
->SetSecondaryPool(pGlobalOutlPool
);
485 mpGlobalItemPool
->SetDefaultMetric(SdrEngineDefaults::GetMapUnit());
486 mpGlobalItemPool
->FreezeIdRanges();
489 return *mpGlobalItemPool
;
492 void SdrObject::SetRelativeWidth( double nValue
)
494 mpImpl
->mnRelativeWidth
= nValue
;
497 void SdrObject::SetRelativeWidthRelation( sal_Int16 eValue
)
499 mpImpl
->meRelativeWidthRelation
= eValue
;
502 void SdrObject::SetRelativeHeight( double nValue
)
504 mpImpl
->mnRelativeHeight
= nValue
;
507 void SdrObject::SetRelativeHeightRelation( sal_Int16 eValue
)
509 mpImpl
->meRelativeHeightRelation
= eValue
;
512 const double* SdrObject::GetRelativeWidth( ) const
514 if (!mpImpl
->mnRelativeWidth
)
517 return &*mpImpl
->mnRelativeWidth
;
520 sal_Int16
SdrObject::GetRelativeWidthRelation() const
522 return mpImpl
->meRelativeWidthRelation
;
525 const double* SdrObject::GetRelativeHeight( ) const
527 if (!mpImpl
->mnRelativeHeight
)
530 return &*mpImpl
->mnRelativeHeight
;
533 sal_Int16
SdrObject::GetRelativeHeightRelation() const
535 return mpImpl
->meRelativeHeightRelation
;
538 void SdrObject::SetDiagramData(std::shared_ptr
<DiagramDataInterface
> pDiagramData
)
540 mpImpl
->mpDiagramData
= pDiagramData
;
543 std::shared_ptr
<DiagramDataInterface
> SdrObject::GetDiagramData() const
545 return mpImpl
->mpDiagramData
;
548 SfxItemPool
& SdrObject::GetObjectItemPool() const
550 return getSdrModelFromSdrObject().GetItemPool();
553 SdrInventor
SdrObject::GetObjInventor() const
555 return SdrInventor::Default
;
558 SdrObjKind
SdrObject::GetObjIdentifier() const
563 void SdrObject::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
565 rInfo
.bRotateFreeAllowed
=false;
566 rInfo
.bMirrorFreeAllowed
=false;
567 rInfo
.bTransparenceAllowed
= false;
568 rInfo
.bShearAllowed
=false;
569 rInfo
.bEdgeRadiusAllowed
=false;
570 rInfo
.bCanConvToPath
=false;
571 rInfo
.bCanConvToPoly
=false;
572 rInfo
.bCanConvToContour
= false;
573 rInfo
.bCanConvToPathLineToArea
=false;
574 rInfo
.bCanConvToPolyLineToArea
=false;
577 SdrLayerID
SdrObject::GetLayer() const
582 void SdrObject::getMergedHierarchySdrLayerIDSet(SdrLayerIDSet
& rSet
) const
584 rSet
.Set(GetLayer());
585 SdrObjList
* pOL
=GetSubList();
587 const size_t nObjCount
= pOL
->GetObjCount();
588 for (size_t nObjNum
= 0; nObjNum
<nObjCount
; ++nObjNum
) {
589 pOL
->GetObj(nObjNum
)->getMergedHierarchySdrLayerIDSet(rSet
);
594 void SdrObject::NbcSetLayer(SdrLayerID nLayer
)
599 void SdrObject::SetLayer(SdrLayerID nLayer
)
603 BroadcastObjectChange();
606 void SdrObject::AddListener(SfxListener
& rListener
)
609 if (pPlusData
->pBroadcast
==nullptr) pPlusData
->pBroadcast
.reset(new SfxBroadcaster
);
611 // SdrEdgeObj may be connected to same SdrObject on both ends so allow it
613 SdrEdgeObj
const*const pEdge(dynamic_cast<SdrEdgeObj
const*>(&rListener
));
614 rListener
.StartListening(*pPlusData
->pBroadcast
, pEdge
? DuplicateHandling::Allow
: DuplicateHandling::Unexpected
);
617 void SdrObject::RemoveListener(SfxListener
& rListener
)
619 if (pPlusData
!=nullptr && pPlusData
->pBroadcast
!=nullptr) {
620 rListener
.EndListening(*pPlusData
->pBroadcast
);
621 if (!pPlusData
->pBroadcast
->HasListeners()) {
622 pPlusData
->pBroadcast
.reset();
627 const SfxBroadcaster
* SdrObject::GetBroadcaster() const
629 return pPlusData
!=nullptr ? pPlusData
->pBroadcast
.get() : nullptr;
632 void SdrObject::AddReference(SdrVirtObj
& rVrtObj
)
634 AddListener(rVrtObj
);
637 void SdrObject::DelReference(SdrVirtObj
& rVrtObj
)
639 RemoveListener(rVrtObj
);
642 bool SdrObject::IsGroupObject() const
644 return GetSubList()!=nullptr;
647 SdrObjList
* SdrObject::GetSubList() const
652 SdrObject
* SdrObject::getParentSdrObjectFromSdrObject() const
654 SdrObjList
* pParent(getParentSdrObjListFromSdrObject());
656 if(nullptr == pParent
)
661 return pParent
->getSdrObjectFromSdrObjList();
664 void SdrObject::SetName(const OUString
& rStr
)
666 if (!rStr
.isEmpty() && !pPlusData
)
671 if(!(pPlusData
&& pPlusData
->aObjName
!= rStr
))
674 // Undo/Redo for setting object's name (#i73249#)
676 if ( getSdrModelFromSdrObject().IsUndoEnabled() )
679 std::unique_ptr
<SdrUndoAction
> pUndoAction
=
680 SdrUndoFactory::CreateUndoObjectStrAttr(
682 SdrUndoObjStrAttr::ObjStrAttrType::Name
,
685 getSdrModelFromSdrObject().BegUndo( pUndoAction
->GetComment() );
686 getSdrModelFromSdrObject().AddUndo( std::move(pUndoAction
) );
688 pPlusData
->aObjName
= rStr
;
689 // Undo/Redo for setting object's name (#i73249#)
692 getSdrModelFromSdrObject().EndUndo();
695 BroadcastObjectChange();
698 OUString
SdrObject::GetName() const
702 return pPlusData
->aObjName
;
708 void SdrObject::SetTitle(const OUString
& rStr
)
710 if (!rStr
.isEmpty() && !pPlusData
)
715 if(!(pPlusData
&& pPlusData
->aObjTitle
!= rStr
))
718 // Undo/Redo for setting object's title (#i73249#)
720 if ( getSdrModelFromSdrObject().IsUndoEnabled() )
723 std::unique_ptr
<SdrUndoAction
> pUndoAction
=
724 SdrUndoFactory::CreateUndoObjectStrAttr(
726 SdrUndoObjStrAttr::ObjStrAttrType::Title
,
729 getSdrModelFromSdrObject().BegUndo( pUndoAction
->GetComment() );
730 getSdrModelFromSdrObject().AddUndo( std::move(pUndoAction
) );
732 pPlusData
->aObjTitle
= rStr
;
733 // Undo/Redo for setting object's title (#i73249#)
736 getSdrModelFromSdrObject().EndUndo();
739 BroadcastObjectChange();
742 OUString
SdrObject::GetTitle() const
746 return pPlusData
->aObjTitle
;
752 void SdrObject::SetDescription(const OUString
& rStr
)
754 if (!rStr
.isEmpty() && !pPlusData
)
759 if(!(pPlusData
&& pPlusData
->aObjDescription
!= rStr
))
762 // Undo/Redo for setting object's description (#i73249#)
764 if ( getSdrModelFromSdrObject().IsUndoEnabled() )
767 std::unique_ptr
<SdrUndoAction
> pUndoAction
=
768 SdrUndoFactory::CreateUndoObjectStrAttr(
770 SdrUndoObjStrAttr::ObjStrAttrType::Description
,
773 getSdrModelFromSdrObject().BegUndo( pUndoAction
->GetComment() );
774 getSdrModelFromSdrObject().AddUndo( std::move(pUndoAction
) );
776 pPlusData
->aObjDescription
= rStr
;
777 // Undo/Redo for setting object's description (#i73249#)
780 getSdrModelFromSdrObject().EndUndo();
783 BroadcastObjectChange();
786 OUString
SdrObject::GetDescription() const
790 return pPlusData
->aObjDescription
;
796 sal_uInt32
SdrObject::GetOrdNum() const
798 if (nullptr != getParentSdrObjListFromSdrObject())
800 if (getParentSdrObjListFromSdrObject()->IsObjOrdNumsDirty())
802 getParentSdrObjListFromSdrObject()->RecalcObjOrdNums();
804 } else const_cast<SdrObject
*>(this)->nOrdNum
=0;
809 void SdrObject::SetOrdNum(sal_uInt32 nNum
)
814 void SdrObject::GetGrabBagItem(css::uno::Any
& rVal
) const
816 if (pGrabBagItem
!= nullptr)
817 pGrabBagItem
->QueryValue(rVal
);
819 rVal
<<= uno::Sequence
<beans::PropertyValue
>();
822 void SdrObject::SetGrabBagItem(const css::uno::Any
& rVal
)
824 if (pGrabBagItem
== nullptr)
825 pGrabBagItem
.reset(new SfxGrabBagItem
);
827 pGrabBagItem
->PutValue(rVal
, 0);
830 BroadcastObjectChange();
833 sal_uInt32
SdrObject::GetNavigationPosition() const
835 if (nullptr != getParentSdrObjListFromSdrObject() && getParentSdrObjListFromSdrObject()->RecalcNavigationPositions())
837 return mnNavigationPosition
;
844 void SdrObject::SetNavigationPosition (const sal_uInt32 nNewPosition
)
846 mnNavigationPosition
= nNewPosition
;
850 // To make clearer that this method may trigger RecalcBoundRect and thus may be
851 // expensive and sometimes problematic (inside a bigger object change you will get
852 // non-useful BoundRects sometimes) I rename that method from GetBoundRect() to
853 // GetCurrentBoundRect().
854 const tools::Rectangle
& SdrObject::GetCurrentBoundRect() const
856 if(aOutRect
.IsEmpty())
858 const_cast< SdrObject
* >(this)->RecalcBoundRect();
864 // To have a possibility to get the last calculated BoundRect e.g for producing
865 // the first rectangle for repaints (old and new need to be used) without forcing
866 // a RecalcBoundRect (which may be problematical and expensive sometimes) I add here
867 // a new method for accessing the last BoundRect.
868 const tools::Rectangle
& SdrObject::GetLastBoundRect() const
873 void SdrObject::RecalcBoundRect()
875 // #i101680# suppress BoundRect calculations on import(s)
876 if ((getSdrModelFromSdrObject().isLocked()) || utl::ConfigManager::IsFuzzing())
879 // central new method which will calculate the BoundRect using primitive geometry
880 if(!aOutRect
.IsEmpty())
883 // Use view-independent data - we do not want any connections
884 // to e.g. GridOffset in SdrObject-level
885 const drawinglayer::primitive2d::Primitive2DContainer
& xPrimitives(GetViewContact().getViewIndependentPrimitive2DContainer());
887 if(xPrimitives
.empty())
890 // use neutral ViewInformation and get the range of the primitives
891 const drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
892 const basegfx::B2DRange
aRange(xPrimitives
.getB2DRange(aViewInformation2D
));
894 if(!aRange
.isEmpty())
896 aOutRect
= tools::Rectangle(
897 static_cast<tools::Long
>(floor(aRange
.getMinX())),
898 static_cast<tools::Long
>(floor(aRange
.getMinY())),
899 static_cast<tools::Long
>(ceil(aRange
.getMaxX())),
900 static_cast<tools::Long
>(ceil(aRange
.getMaxY())));
905 void SdrObject::BroadcastObjectChange() const
907 if ((getSdrModelFromSdrObject().isLocked()) || utl::ConfigManager::IsFuzzing())
910 bool bPlusDataBroadcast(pPlusData
&& pPlusData
->pBroadcast
);
911 bool bObjectChange(IsInserted());
913 if(!(bPlusDataBroadcast
|| bObjectChange
))
916 SdrHint
aHint(SdrHintKind::ObjectChange
, *this);
918 if(bPlusDataBroadcast
)
920 pPlusData
->pBroadcast
->Broadcast(aHint
);
925 getSdrModelFromSdrObject().Broadcast(aHint
);
929 void SdrObject::SetChanged()
931 // For testing purposes, use the new ViewContact for change
935 // TTTT Need to check meaning/usage of IsInserted in one
936 // of the next changes. It should not mean to have a SdrModel
937 // set (this is guaranteed now), but should be connected to
938 // being added to a SdrPage (?)
939 // TTTT tdf#120066 Indeed - This triggers e.g. by CustomShape
940 // geometry-presenting SdrObjects that are in a SdrObjGroup,
941 // but the SdrObjGroup is *by purpose* not inserted.
942 // Need to check deeper and maybe identify all ::IsInserted()
943 // calls by rename and let the compiler work...
944 if(nullptr != getSdrPageFromSdrObject())
946 getSdrModelFromSdrObject().SetChanged();
950 // tooling for painting a single object to an OutputDevice.
951 void SdrObject::SingleObjectPainter(OutputDevice
& rOut
) const
953 sdr::contact::SdrObjectVector aObjectVector
;
954 aObjectVector
.push_back(const_cast< SdrObject
* >(this));
956 sdr::contact::ObjectContactOfObjListPainter
aPainter(rOut
, aObjectVector
, getSdrPageFromSdrObject());
957 sdr::contact::DisplayInfo aDisplayInfo
;
959 aPainter
.ProcessDisplay(aDisplayInfo
);
962 bool SdrObject::LineGeometryUsageIsNecessary() const
964 drawing::LineStyle eXLS
= GetMergedItem(XATTR_LINESTYLE
).GetValue();
965 return (eXLS
!= drawing::LineStyle_NONE
);
968 bool SdrObject::HasLimitedRotation() const
970 // RotGrfFlyFrame: Default is false, support full rotation
974 SdrObject
* SdrObject::CloneSdrObject(SdrModel
& rTargetModel
) const
976 return CloneHelper
< SdrObject
>(rTargetModel
);
979 SdrObject
& SdrObject::operator=(const SdrObject
& rObj
)
984 mpProperties
.reset();
985 mpViewContact
.reset();
987 // The CloneSdrObject() method uses the local copy constructor from the individual
988 // sdr::properties::BaseProperties class. Since the target class maybe for another
989 // draw object, an SdrObject needs to be provided, as in the normal constructor.
990 mpProperties
= rObj
.GetProperties().Clone(*this);
992 aOutRect
=rObj
.aOutRect
;
993 mnLayerID
= rObj
.mnLayerID
;
994 aAnchor
=rObj
.aAnchor
;
995 bVirtObj
=rObj
.bVirtObj
;
996 bSizProt
=rObj
.bSizProt
;
997 bMovProt
=rObj
.bMovProt
;
998 bNoPrint
=rObj
.bNoPrint
;
999 mbVisible
=rObj
.mbVisible
;
1000 bMarkProt
=rObj
.bMarkProt
;
1001 bEmptyPresObj
=rObj
.bEmptyPresObj
;
1002 bNotVisibleAsMaster
=rObj
.bNotVisibleAsMaster
;
1003 bSnapRectDirty
=true;
1005 if (rObj
.pPlusData
!=nullptr) {
1006 pPlusData
.reset(rObj
.pPlusData
->Clone(this));
1008 if (pPlusData
!=nullptr && pPlusData
->pBroadcast
!=nullptr) {
1009 pPlusData
->pBroadcast
.reset(); // broadcaster isn't copied
1012 pGrabBagItem
.reset();
1013 if (rObj
.pGrabBagItem
!=nullptr)
1014 pGrabBagItem
.reset(rObj
.pGrabBagItem
->Clone());
1018 OUString
SdrObject::TakeObjNameSingul() const
1020 OUStringBuffer
sName(SvxResId(STR_ObjNameSingulNONE
));
1022 OUString
aName(GetName());
1023 if (!aName
.isEmpty())
1027 sName
.append(aName
);
1030 return sName
.makeStringAndClear();
1033 OUString
SdrObject::TakeObjNamePlural() const
1035 return SvxResId(STR_ObjNamePluralNONE
);
1038 OUString
SdrObject::ImpGetDescriptionStr(const char* pStrCacheID
) const
1040 OUString aStr
= SvxResId(pStrCacheID
);
1041 sal_Int32 nPos
= aStr
.indexOf("%1");
1044 // Replace '%1' with the object name.
1045 OUString
aObjName(TakeObjNameSingul());
1046 aStr
= aStr
.replaceAt(nPos
, 2, aObjName
);
1049 nPos
= aStr
.indexOf("%2");
1051 // Replace '%2' with the passed value.
1052 aStr
= aStr
.replaceAt(nPos
, 2, "0");
1056 void SdrObject::ImpForcePlusData()
1059 pPlusData
.reset( new SdrObjPlusData
);
1062 OUString
SdrObject::GetMetrStr(tools::Long nVal
) const
1064 return getSdrModelFromSdrObject().GetMetricString(nVal
);
1067 basegfx::B2DPolyPolygon
SdrObject::TakeXorPoly() const
1069 basegfx::B2DPolyPolygon aRetval
;
1070 const tools::Rectangle
aR(GetCurrentBoundRect());
1071 aRetval
.append(basegfx::utils::createPolygonFromRect(vcl::unotools::b2DRectangleFromRectangle(aR
)));
1076 basegfx::B2DPolyPolygon
SdrObject::TakeContour() const
1078 basegfx::B2DPolyPolygon aRetval
;
1080 // create cloned object without text, but with drawing::LineStyle_SOLID,
1081 // COL_BLACK as line color and drawing::FillStyle_NONE
1082 SdrObject
* pClone(CloneSdrObject(getSdrModelFromSdrObject()));
1086 const SdrTextObj
* pTextObj
= dynamic_cast< const SdrTextObj
* >(this);
1090 // no text and no text animation
1091 pClone
->SetMergedItem(SdrTextAniKindItem(SdrTextAniKind::NONE
));
1092 pClone
->SetOutlinerParaObject(nullptr);
1095 const SdrEdgeObj
* pEdgeObj
= dynamic_cast< const SdrEdgeObj
* >(this);
1099 // create connections if connector, will be cleaned up when
1100 // deleting the connector again
1101 SdrObject
* pLeft
= pEdgeObj
->GetConnectedNode(true);
1102 SdrObject
* pRight
= pEdgeObj
->GetConnectedNode(false);
1106 pClone
->ConnectToNode(true, pLeft
);
1111 pClone
->ConnectToNode(false, pRight
);
1115 SfxItemSet
aNewSet(GetObjectItemPool());
1117 // #i101980# ignore LineWidth; that's what the old implementation
1118 // did. With line width, the result may be huge due to fat/thick
1119 // line decompositions
1120 aNewSet
.Put(XLineWidthItem(0));
1122 // solid black lines and no fill
1123 aNewSet
.Put(XLineStyleItem(drawing::LineStyle_SOLID
));
1124 aNewSet
.Put(XLineColorItem(OUString(), COL_BLACK
));
1125 aNewSet
.Put(XFillStyleItem(drawing::FillStyle_NONE
));
1126 pClone
->SetMergedItemSet(aNewSet
);
1128 // get sequence from clone
1129 const sdr::contact::ViewContact
& rVC(pClone
->GetViewContact());
1130 const drawinglayer::primitive2d::Primitive2DContainer
& xSequence(rVC
.getViewIndependentPrimitive2DContainer());
1132 if(!xSequence
.empty())
1134 // use neutral ViewInformation
1135 const drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
1137 // create extractor, process and get result (with hairlines as opened polygons)
1138 drawinglayer::processor2d::ContourExtractor2D
aExtractor(aViewInformation2D
, false);
1139 aExtractor
.process(xSequence
);
1140 const basegfx::B2DPolyPolygonVector
& rResult(aExtractor
.getExtractedContour());
1141 const sal_uInt32
nSize(rResult
.size());
1143 // when count is one, it is implied that the object has only its normal
1144 // contour anyways and TakeContour() is to return an empty PolyPolygon
1145 // (see old implementation for historical reasons)
1148 // the topology for contour is correctly a vector of PolyPolygons; for
1149 // historical reasons cut it back to a single tools::PolyPolygon here
1150 for(sal_uInt32
a(0); a
< nSize
; a
++)
1152 aRetval
.append(rResult
[a
]);
1157 // Always use SdrObject::Free to delete SdrObjects (!)
1158 SdrObject::Free(pClone
);
1164 sal_uInt32
SdrObject::GetHdlCount() const
1169 void SdrObject::AddToHdlList(SdrHdlList
& rHdlList
) const
1171 const tools::Rectangle
& rR
=GetSnapRect();
1172 for (sal_uInt32 nHdlNum
=0; nHdlNum
<8; ++nHdlNum
)
1174 std::unique_ptr
<SdrHdl
> pH
;
1176 case 0: pH
.reset(new SdrHdl(rR
.TopLeft(), SdrHdlKind::UpperLeft
)); break;
1177 case 1: pH
.reset(new SdrHdl(rR
.TopCenter(), SdrHdlKind::Upper
)); break;
1178 case 2: pH
.reset(new SdrHdl(rR
.TopRight(), SdrHdlKind::UpperRight
)); break;
1179 case 3: pH
.reset(new SdrHdl(rR
.LeftCenter(), SdrHdlKind::Left
)); break;
1180 case 4: pH
.reset(new SdrHdl(rR
.RightCenter(), SdrHdlKind::Right
)); break;
1181 case 5: pH
.reset(new SdrHdl(rR
.BottomLeft(), SdrHdlKind::LowerLeft
)); break;
1182 case 6: pH
.reset(new SdrHdl(rR
.BottomCenter(),SdrHdlKind::Lower
)); break;
1183 case 7: pH
.reset(new SdrHdl(rR
.BottomRight(), SdrHdlKind::LowerRight
)); break;
1185 rHdlList
.AddHdl(std::move(pH
));
1189 void SdrObject::AddToPlusHdlList(SdrHdlList
&, SdrHdl
&) const
1193 void SdrObject::addCropHandles(SdrHdlList
& /*rTarget*/) const
1195 // Default implementation, does nothing. Overloaded in
1196 // SdrGrafObj and SwVirtFlyDrawObj
1199 tools::Rectangle
SdrObject::ImpDragCalcRect(const SdrDragStat
& rDrag
) const
1201 tools::Rectangle
aTmpRect(GetSnapRect());
1202 tools::Rectangle
aRect(aTmpRect
);
1203 const SdrHdl
* pHdl
=rDrag
.GetHdl();
1204 SdrHdlKind eHdl
=pHdl
==nullptr ? SdrHdlKind::Move
: pHdl
->GetKind();
1205 bool bEcke
=(eHdl
==SdrHdlKind::UpperLeft
|| eHdl
==SdrHdlKind::UpperRight
|| eHdl
==SdrHdlKind::LowerLeft
|| eHdl
==SdrHdlKind::LowerRight
);
1206 bool bOrtho
=rDrag
.GetView()!=nullptr && rDrag
.GetView()->IsOrtho();
1207 bool bBigOrtho
=bEcke
&& bOrtho
&& rDrag
.GetView()->IsBigOrtho();
1208 Point
aPos(rDrag
.GetNow());
1209 bool bLft
=(eHdl
==SdrHdlKind::UpperLeft
|| eHdl
==SdrHdlKind::Left
|| eHdl
==SdrHdlKind::LowerLeft
);
1210 bool bRgt
=(eHdl
==SdrHdlKind::UpperRight
|| eHdl
==SdrHdlKind::Right
|| eHdl
==SdrHdlKind::LowerRight
);
1211 bool bTop
=(eHdl
==SdrHdlKind::UpperRight
|| eHdl
==SdrHdlKind::Upper
|| eHdl
==SdrHdlKind::UpperLeft
);
1212 bool bBtm
=(eHdl
==SdrHdlKind::LowerRight
|| eHdl
==SdrHdlKind::Lower
|| eHdl
==SdrHdlKind::LowerLeft
);
1213 if (bLft
) aTmpRect
.SetLeft(aPos
.X() );
1214 if (bRgt
) aTmpRect
.SetRight(aPos
.X() );
1215 if (bTop
) aTmpRect
.SetTop(aPos
.Y() );
1216 if (bBtm
) aTmpRect
.SetBottom(aPos
.Y() );
1217 if (bOrtho
) { // Ortho
1218 tools::Long nWdt0
=aRect
.Right() -aRect
.Left();
1219 tools::Long nHgt0
=aRect
.Bottom()-aRect
.Top();
1220 tools::Long nXMul
=aTmpRect
.Right() -aTmpRect
.Left();
1221 tools::Long nYMul
=aTmpRect
.Bottom()-aTmpRect
.Top();
1222 tools::Long nXDiv
=nWdt0
;
1223 tools::Long nYDiv
=nHgt0
;
1224 bool bXNeg
=(nXMul
<0)!=(nXDiv
<0);
1225 bool bYNeg
=(nYMul
<0)!=(nYDiv
<0);
1226 nXMul
=std::abs(nXMul
);
1227 nYMul
=std::abs(nYMul
);
1228 nXDiv
=std::abs(nXDiv
);
1229 nYDiv
=std::abs(nYDiv
);
1230 Fraction
aXFact(nXMul
,nXDiv
); // fractions for canceling
1231 Fraction
aYFact(nYMul
,nYDiv
); // and for comparing
1232 nXMul
=aXFact
.GetNumerator();
1233 nYMul
=aYFact
.GetNumerator();
1234 nXDiv
=aXFact
.GetDenominator();
1235 nYDiv
=aYFact
.GetDenominator();
1236 if (bEcke
) { // corner point handles
1237 bool bUseX
=(aXFact
<aYFact
) != bBigOrtho
;
1239 tools::Long nNeed
=tools::Long(BigInt(nHgt0
)*BigInt(nXMul
)/BigInt(nXDiv
));
1240 if (bYNeg
) nNeed
=-nNeed
;
1241 if (bTop
) aTmpRect
.SetTop(aTmpRect
.Bottom()-nNeed
);
1242 if (bBtm
) aTmpRect
.SetBottom(aTmpRect
.Top()+nNeed
);
1244 tools::Long nNeed
=tools::Long(BigInt(nWdt0
)*BigInt(nYMul
)/BigInt(nYDiv
));
1245 if (bXNeg
) nNeed
=-nNeed
;
1246 if (bLft
) aTmpRect
.SetLeft(aTmpRect
.Right()-nNeed
);
1247 if (bRgt
) aTmpRect
.SetRight(aTmpRect
.Left()+nNeed
);
1249 } else { // apex handles
1250 if ((bLft
|| bRgt
) && nXDiv
!=0) {
1251 tools::Long nHgt0b
=aRect
.Bottom()-aRect
.Top();
1252 tools::Long nNeed
=tools::Long(BigInt(nHgt0b
)*BigInt(nXMul
)/BigInt(nXDiv
));
1253 aTmpRect
.AdjustTop( -((nNeed
-nHgt0b
)/2) );
1254 aTmpRect
.SetBottom(aTmpRect
.Top()+nNeed
);
1256 if ((bTop
|| bBtm
) && nYDiv
!=0) {
1257 tools::Long nWdt0b
=aRect
.Right()-aRect
.Left();
1258 tools::Long nNeed
=tools::Long(BigInt(nWdt0b
)*BigInt(nYMul
)/BigInt(nYDiv
));
1259 aTmpRect
.AdjustLeft( -((nNeed
-nWdt0b
)/2) );
1260 aTmpRect
.SetRight(aTmpRect
.Left()+nNeed
);
1269 bool SdrObject::hasSpecialDrag() const
1274 bool SdrObject::supportsFullDrag() const
1279 SdrObjectUniquePtr
SdrObject::getFullDragClone() const
1281 // default uses simple clone
1282 return SdrObjectUniquePtr(CloneSdrObject(getSdrModelFromSdrObject()));
1285 bool SdrObject::beginSpecialDrag(SdrDragStat
& rDrag
) const
1287 const SdrHdl
* pHdl
= rDrag
.GetHdl();
1289 SdrHdlKind eHdl
= (pHdl
== nullptr) ? SdrHdlKind::Move
: pHdl
->GetKind();
1291 return eHdl
==SdrHdlKind::UpperLeft
|| eHdl
==SdrHdlKind::Upper
|| eHdl
==SdrHdlKind::UpperRight
||
1292 eHdl
==SdrHdlKind::Left
|| eHdl
==SdrHdlKind::Right
|| eHdl
==SdrHdlKind::LowerLeft
||
1293 eHdl
==SdrHdlKind::Lower
|| eHdl
==SdrHdlKind::LowerRight
;
1296 bool SdrObject::applySpecialDrag(SdrDragStat
& rDrag
)
1298 tools::Rectangle
aNewRect(ImpDragCalcRect(rDrag
));
1300 if(aNewRect
!= GetSnapRect())
1302 NbcSetSnapRect(aNewRect
);
1308 OUString
SdrObject::getSpecialDragComment(const SdrDragStat
& /*rDrag*/) const
1313 basegfx::B2DPolyPolygon
SdrObject::getSpecialDragPoly(const SdrDragStat
& /*rDrag*/) const
1315 // default has nothing to add
1316 return basegfx::B2DPolyPolygon();
1321 bool SdrObject::BegCreate(SdrDragStat
& rStat
)
1323 rStat
.SetOrtho4Possible();
1324 tools::Rectangle
aRect1(rStat
.GetStart(), rStat
.GetNow());
1326 rStat
.SetActionRect(aRect1
);
1331 bool SdrObject::MovCreate(SdrDragStat
& rStat
)
1333 rStat
.TakeCreateRect(aOutRect
);
1334 rStat
.SetActionRect(aOutRect
);
1340 bool SdrObject::EndCreate(SdrDragStat
& rStat
, SdrCreateCmd eCmd
)
1342 rStat
.TakeCreateRect(aOutRect
);
1345 return (eCmd
==SdrCreateCmd::ForceEnd
|| rStat
.GetPointCount()>=2);
1348 void SdrObject::BrkCreate(SdrDragStat
& /*rStat*/)
1352 bool SdrObject::BckCreate(SdrDragStat
& /*rStat*/)
1357 basegfx::B2DPolyPolygon
SdrObject::TakeCreatePoly(const SdrDragStat
& rDrag
) const
1359 tools::Rectangle aRect1
;
1360 rDrag
.TakeCreateRect(aRect1
);
1363 basegfx::B2DPolyPolygon aRetval
;
1364 aRetval
.append(basegfx::utils::createPolygonFromRect(vcl::unotools::b2DRectangleFromRectangle(aRect1
)));
1368 PointerStyle
SdrObject::GetCreatePointer() const
1370 return PointerStyle::Cross
;
1374 void SdrObject::NbcMove(const Size
& rSiz
)
1376 aOutRect
.Move(rSiz
);
1380 void SdrObject::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
1382 bool bXMirr
=(xFact
.GetNumerator()<0) != (xFact
.GetDenominator()<0);
1383 bool bYMirr
=(yFact
.GetNumerator()<0) != (yFact
.GetDenominator()<0);
1384 if (bXMirr
|| bYMirr
) {
1385 Point
aRef1(GetSnapRect().Center());
1389 NbcMirrorGluePoints(aRef1
,aRef2
);
1394 NbcMirrorGluePoints(aRef1
,aRef2
);
1397 ResizeRect(aOutRect
,rRef
,xFact
,yFact
);
1401 void SdrObject::NbcRotate(const Point
& rRef
, tools::Long nAngle
, double sn
, double cs
)
1403 SetGlueReallyAbsolute(true);
1404 aOutRect
.Move(-rRef
.X(),-rRef
.Y());
1405 tools::Rectangle
R(aOutRect
);
1406 if (sn
==1.0 && cs
==0.0) { // 90deg
1407 aOutRect
.SetLeft(-R
.Bottom() );
1408 aOutRect
.SetRight(-R
.Top() );
1409 aOutRect
.SetTop(R
.Left() );
1410 aOutRect
.SetBottom(R
.Right() );
1411 } else if (sn
==0.0 && cs
==-1.0) { // 180deg
1412 aOutRect
.SetLeft(-R
.Right() );
1413 aOutRect
.SetRight(-R
.Left() );
1414 aOutRect
.SetTop(-R
.Bottom() );
1415 aOutRect
.SetBottom(-R
.Top() );
1416 } else if (sn
==-1.0 && cs
==0.0) { // 270deg
1417 aOutRect
.SetLeft(R
.Top() );
1418 aOutRect
.SetRight(R
.Bottom() );
1419 aOutRect
.SetTop(-R
.Right() );
1420 aOutRect
.SetBottom(-R
.Left() );
1422 aOutRect
.Move(rRef
.X(),rRef
.Y());
1423 aOutRect
.Justify(); // just in case
1425 NbcRotateGluePoints(rRef
,nAngle
,sn
,cs
);
1426 SetGlueReallyAbsolute(false);
1429 void SdrObject::NbcMirror(const Point
& rRef1
, const Point
& rRef2
)
1431 SetGlueReallyAbsolute(true);
1432 aOutRect
.Move(-rRef1
.X(),-rRef1
.Y());
1433 tools::Rectangle
R(aOutRect
);
1434 tools::Long dx
=rRef2
.X()-rRef1
.X();
1435 tools::Long dy
=rRef2
.Y()-rRef1
.Y();
1436 if (dx
==0) { // vertical axis
1437 aOutRect
.SetLeft(-R
.Right() );
1438 aOutRect
.SetRight(-R
.Left() );
1439 } else if (dy
==0) { // horizontal axis
1440 aOutRect
.SetTop(-R
.Bottom() );
1441 aOutRect
.SetBottom(-R
.Top() );
1442 } else if (dx
==dy
) { // 45deg axis
1443 aOutRect
.SetLeft(R
.Top() );
1444 aOutRect
.SetRight(R
.Bottom() );
1445 aOutRect
.SetTop(R
.Left() );
1446 aOutRect
.SetBottom(R
.Right() );
1447 } else if (dx
==-dy
) { // 45deg axis
1448 aOutRect
.SetLeft(-R
.Bottom() );
1449 aOutRect
.SetRight(-R
.Top() );
1450 aOutRect
.SetTop(-R
.Right() );
1451 aOutRect
.SetBottom(-R
.Left() );
1453 aOutRect
.Move(rRef1
.X(),rRef1
.Y());
1454 aOutRect
.Justify(); // just in case
1456 NbcMirrorGluePoints(rRef1
,rRef2
);
1457 SetGlueReallyAbsolute(false);
1460 void SdrObject::NbcShear(const Point
& rRef
, tools::Long
/*nAngle*/, double tn
, bool bVShear
)
1462 SetGlueReallyAbsolute(true);
1463 NbcShearGluePoints(rRef
,tn
,bVShear
);
1464 SetGlueReallyAbsolute(false);
1467 void SdrObject::Move(const Size
& rSiz
)
1469 if (rSiz
.Width()!=0 || rSiz
.Height()!=0) {
1470 tools::Rectangle aBoundRect0
; if (pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1473 BroadcastObjectChange();
1474 SendUserCall(SdrUserCallType::MoveOnly
,aBoundRect0
);
1478 void SdrObject::NbcCrop(const basegfx::B2DPoint
& /*aRef*/, double /*fxFact*/, double /*fyFact*/)
1480 // Default: does nothing. Real behaviour in SwVirtFlyDrawObj and SdrDragCrop::EndSdrDrag.
1481 // Where SwVirtFlyDrawObj is the only real user of it to do something local
1484 void SdrObject::Resize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
, bool bUnsetRelative
)
1486 if (xFact
.GetNumerator() == xFact
.GetDenominator() && yFact
.GetNumerator() == yFact
.GetDenominator())
1491 mpImpl
->mnRelativeWidth
.reset();
1492 mpImpl
->meRelativeWidthRelation
= text::RelOrientation::PAGE_FRAME
;
1493 mpImpl
->meRelativeHeightRelation
= text::RelOrientation::PAGE_FRAME
;
1494 mpImpl
->mnRelativeHeight
.reset();
1496 tools::Rectangle aBoundRect0
; if (pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1497 NbcResize(rRef
,xFact
,yFact
);
1499 BroadcastObjectChange();
1500 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1503 void SdrObject::Crop(const basegfx::B2DPoint
& rRef
, double fxFact
, double fyFact
)
1505 tools::Rectangle aBoundRect0
; if (pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1506 NbcCrop(rRef
, fxFact
, fyFact
);
1508 BroadcastObjectChange();
1509 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1512 void SdrObject::Rotate(const Point
& rRef
, tools::Long nAngle
, double sn
, double cs
)
1515 tools::Rectangle aBoundRect0
; if (pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1516 NbcRotate(rRef
,nAngle
,sn
,cs
);
1518 BroadcastObjectChange();
1519 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1523 void SdrObject::Mirror(const Point
& rRef1
, const Point
& rRef2
)
1525 tools::Rectangle aBoundRect0
; if (pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1526 NbcMirror(rRef1
,rRef2
);
1528 BroadcastObjectChange();
1529 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1532 void SdrObject::Shear(const Point
& rRef
, tools::Long nAngle
, double tn
, bool bVShear
)
1535 tools::Rectangle aBoundRect0
; if (pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1536 NbcShear(rRef
,nAngle
,tn
,bVShear
);
1538 BroadcastObjectChange();
1539 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1543 void SdrObject::NbcSetRelativePos(const Point
& rPnt
)
1545 Point
aRelPos0(GetSnapRect().TopLeft()-aAnchor
);
1546 Size
aSiz(rPnt
.X()-aRelPos0
.X(),rPnt
.Y()-aRelPos0
.Y());
1547 NbcMove(aSiz
); // This also calls SetRectsDirty()
1550 void SdrObject::SetRelativePos(const Point
& rPnt
)
1552 if (rPnt
!=GetRelativePos()) {
1553 tools::Rectangle aBoundRect0
; if (pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1554 NbcSetRelativePos(rPnt
);
1556 BroadcastObjectChange();
1557 SendUserCall(SdrUserCallType::MoveOnly
,aBoundRect0
);
1561 Point
SdrObject::GetRelativePos() const
1563 return GetSnapRect().TopLeft()-aAnchor
;
1566 void SdrObject::ImpSetAnchorPos(const Point
& rPnt
)
1571 void SdrObject::NbcSetAnchorPos(const Point
& rPnt
)
1573 Size
aSiz(rPnt
.X()-aAnchor
.X(),rPnt
.Y()-aAnchor
.Y());
1575 NbcMove(aSiz
); // This also calls SetRectsDirty()
1578 void SdrObject::SetAnchorPos(const Point
& rPnt
)
1580 if (rPnt
!=aAnchor
) {
1581 tools::Rectangle aBoundRect0
; if (pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1582 NbcSetAnchorPos(rPnt
);
1584 BroadcastObjectChange();
1585 SendUserCall(SdrUserCallType::MoveOnly
,aBoundRect0
);
1589 const Point
& SdrObject::GetAnchorPos() const
1594 void SdrObject::RecalcSnapRect()
1598 const tools::Rectangle
& SdrObject::GetSnapRect() const
1603 void SdrObject::NbcSetSnapRect(const tools::Rectangle
& rRect
)
1608 const tools::Rectangle
& SdrObject::GetLogicRect() const
1610 return GetSnapRect();
1613 void SdrObject::NbcSetLogicRect(const tools::Rectangle
& rRect
)
1615 NbcSetSnapRect(rRect
);
1618 void SdrObject::AdjustToMaxRect( const tools::Rectangle
& rMaxRect
, bool /* bShrinkOnly = false */ )
1620 SetLogicRect( rMaxRect
);
1623 void SdrObject::SetSnapRect(const tools::Rectangle
& rRect
)
1625 tools::Rectangle aBoundRect0
; if (pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1626 NbcSetSnapRect(rRect
);
1628 BroadcastObjectChange();
1629 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1632 void SdrObject::SetLogicRect(const tools::Rectangle
& rRect
)
1634 tools::Rectangle aBoundRect0
; if (pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1635 NbcSetLogicRect(rRect
);
1637 BroadcastObjectChange();
1638 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1641 tools::Long
SdrObject::GetRotateAngle() const
1646 tools::Long
SdrObject::GetShearAngle(bool /*bVertical*/) const
1651 sal_uInt32
SdrObject::GetSnapPointCount() const
1653 return GetPointCount();
1656 Point
SdrObject::GetSnapPoint(sal_uInt32 i
) const
1661 bool SdrObject::IsPolyObj() const
1666 sal_uInt32
SdrObject::GetPointCount() const
1671 Point
SdrObject::GetPoint(sal_uInt32
/*i*/) const
1676 void SdrObject::SetPoint(const Point
& rPnt
, sal_uInt32 i
)
1678 tools::Rectangle aBoundRect0
; if (pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1679 NbcSetPoint(rPnt
, i
);
1681 BroadcastObjectChange();
1682 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1685 void SdrObject::NbcSetPoint(const Point
& /*rPnt*/, sal_uInt32
/*i*/)
1689 bool SdrObject::HasTextEdit() const
1694 bool SdrObject::Equals(const SdrObject
& rOtherObj
) const
1696 return (aAnchor
.X() == rOtherObj
.aAnchor
.X() && aAnchor
.Y() == rOtherObj
.aAnchor
.Y() &&
1697 nOrdNum
== rOtherObj
.nOrdNum
&& mnNavigationPosition
== rOtherObj
.mnNavigationPosition
&&
1698 mbSupportTextIndentingOnLineWidthChange
== rOtherObj
.mbSupportTextIndentingOnLineWidthChange
&&
1699 mbLineIsOutsideGeometry
== rOtherObj
.mbLineIsOutsideGeometry
&& bMarkProt
== rOtherObj
.bMarkProt
&&
1700 bIs3DObj
== rOtherObj
.bIs3DObj
&& bIsEdge
== rOtherObj
.bIsEdge
&& bClosedObj
== rOtherObj
.bClosedObj
&&
1701 bNotVisibleAsMaster
== rOtherObj
.bNotVisibleAsMaster
&& bEmptyPresObj
== rOtherObj
.bEmptyPresObj
&&
1702 mbVisible
== rOtherObj
.mbVisible
&& bNoPrint
== rOtherObj
.bNoPrint
&& bSizProt
== rOtherObj
.bSizProt
&&
1703 bMovProt
== rOtherObj
.bMovProt
&& bVirtObj
== rOtherObj
.bVirtObj
&&
1704 mnLayerID
== rOtherObj
.mnLayerID
&& GetMergedItemSet().Equals(rOtherObj
.GetMergedItemSet(), false) );
1707 void SdrObject::dumpAsXml(xmlTextWriterPtr pWriter
) const
1709 xmlTextWriterStartElement(pWriter
, BAD_CAST("SdrObject"));
1710 xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
1711 xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
1712 xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("name"), "%s", BAD_CAST(GetName().toUtf8().getStr()));
1713 xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("title"), "%s", BAD_CAST(GetTitle().toUtf8().getStr()));
1714 xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("description"), "%s", BAD_CAST(GetDescription().toUtf8().getStr()));
1715 xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("nOrdNum"), "%" SAL_PRIuUINT32
, GetOrdNumDirect());
1716 xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("aOutRect"), BAD_CAST(aOutRect
.toString().getStr()));
1720 pGrabBagItem
->dumpAsXml(pWriter
);
1725 mpProperties
->dumpAsXml(pWriter
);
1728 if (const OutlinerParaObject
* pOutliner
= GetOutlinerParaObject())
1729 pOutliner
->dumpAsXml(pWriter
);
1731 xmlTextWriterEndElement(pWriter
);
1734 void SdrObject::SetOutlinerParaObject(std::unique_ptr
<OutlinerParaObject
> pTextObject
)
1736 tools::Rectangle aBoundRect0
; if (pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1737 NbcSetOutlinerParaObject(std::move(pTextObject
));
1739 BroadcastObjectChange();
1740 if (GetCurrentBoundRect()!=aBoundRect0
) {
1741 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1744 if (getSdrModelFromSdrObject().IsUndoEnabled())
1746 // Don't do this during import.
1747 SdrObject
* pTopGroupObj
= nullptr;
1748 if (getParentSdrObjectFromSdrObject())
1750 pTopGroupObj
= getParentSdrObjectFromSdrObject();
1751 while (pTopGroupObj
->getParentSdrObjectFromSdrObject())
1753 pTopGroupObj
= pTopGroupObj
->getParentSdrObjectFromSdrObject();
1758 // A shape was modified, which is in a group shape. Empty the group shape's grab-bag,
1759 // which potentially contains the old text of the shapes in case of diagrams.
1760 pTopGroupObj
->SetGrabBagItem(uno::makeAny(uno::Sequence
<beans::PropertyValue
>()));
1765 void SdrObject::NbcSetOutlinerParaObject(std::unique_ptr
<OutlinerParaObject
> /*pTextObject*/)
1769 OutlinerParaObject
* SdrObject::GetOutlinerParaObject() const
1774 void SdrObject::NbcReformatText()
1778 void SdrObject::BurnInStyleSheetAttributes()
1780 GetProperties().ForceStyleToHardAttributes();
1783 bool SdrObject::HasMacro() const
1788 SdrObject
* SdrObject::CheckMacroHit(const SdrObjMacroHitRec
& rRec
) const
1792 return SdrObjectPrimitiveHit(*this, rRec
.aPos
, rRec
.nTol
, *rRec
.pPageView
, rRec
.pVisiLayer
, false);
1798 PointerStyle
SdrObject::GetMacroPointer(const SdrObjMacroHitRec
&) const
1800 return PointerStyle::RefHand
;
1803 void SdrObject::PaintMacro(OutputDevice
& rOut
, const tools::Rectangle
& , const SdrObjMacroHitRec
& ) const
1805 const RasterOp
eRop(rOut
.GetRasterOp());
1806 const basegfx::B2DPolyPolygon
aPolyPolygon(TakeXorPoly());
1808 rOut
.SetLineColor(COL_BLACK
);
1809 rOut
.SetFillColor();
1810 rOut
.SetRasterOp(RasterOp::Invert
);
1812 for(auto const& rPolygon
: aPolyPolygon
)
1814 rOut
.DrawPolyLine(rPolygon
);
1817 rOut
.SetRasterOp(eRop
);
1820 bool SdrObject::DoMacro(const SdrObjMacroHitRec
&)
1825 bool SdrObject::IsMacroHit(const SdrObjMacroHitRec
& rRec
) const
1827 return CheckMacroHit(rRec
) != nullptr;
1831 SdrObjGeoData
* SdrObject::NewGeoData() const
1833 return new SdrObjGeoData
;
1836 void SdrObject::SaveGeoData(SdrObjGeoData
& rGeo
) const
1838 rGeo
.aBoundRect
=GetCurrentBoundRect();
1839 rGeo
.aAnchor
=aAnchor
;
1840 rGeo
.bMovProt
=bMovProt
;
1841 rGeo
.bSizProt
=bSizProt
;
1842 rGeo
.bNoPrint
=bNoPrint
;
1843 rGeo
.mbVisible
=mbVisible
;
1844 rGeo
.bClosedObj
=bClosedObj
;
1845 rGeo
.mnLayerID
= mnLayerID
;
1847 // user-defined glue points
1848 if (pPlusData
!=nullptr && pPlusData
->pGluePoints
!=nullptr) {
1849 if (rGeo
.pGPL
!=nullptr) {
1850 *rGeo
.pGPL
=*pPlusData
->pGluePoints
;
1852 rGeo
.pGPL
.reset( new SdrGluePointList(*pPlusData
->pGluePoints
) );
1859 void SdrObject::RestGeoData(const SdrObjGeoData
& rGeo
)
1862 aOutRect
=rGeo
.aBoundRect
;
1863 aAnchor
=rGeo
.aAnchor
;
1864 bMovProt
=rGeo
.bMovProt
;
1865 bSizProt
=rGeo
.bSizProt
;
1866 bNoPrint
=rGeo
.bNoPrint
;
1867 mbVisible
=rGeo
.mbVisible
;
1868 bClosedObj
=rGeo
.bClosedObj
;
1869 mnLayerID
= rGeo
.mnLayerID
;
1871 // user-defined glue points
1872 if (rGeo
.pGPL
!=nullptr) {
1874 if (pPlusData
->pGluePoints
!=nullptr) {
1875 *pPlusData
->pGluePoints
=*rGeo
.pGPL
;
1877 pPlusData
->pGluePoints
.reset(new SdrGluePointList(*rGeo
.pGPL
));
1880 if (pPlusData
!=nullptr && pPlusData
->pGluePoints
!=nullptr) {
1881 pPlusData
->pGluePoints
.reset();
1886 SdrObjGeoData
* SdrObject::GetGeoData() const
1888 SdrObjGeoData
* pGeo
=NewGeoData();
1893 void SdrObject::SetGeoData(const SdrObjGeoData
& rGeo
)
1895 tools::Rectangle aBoundRect0
; if (pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1898 BroadcastObjectChange();
1899 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1905 const SfxItemSet
& SdrObject::GetObjectItemSet() const
1907 return GetProperties().GetObjectItemSet();
1910 const SfxItemSet
& SdrObject::GetMergedItemSet() const
1912 return GetProperties().GetMergedItemSet();
1915 void SdrObject::SetObjectItem(const SfxPoolItem
& rItem
)
1917 GetProperties().SetObjectItem(rItem
);
1920 void SdrObject::SetMergedItem(const SfxPoolItem
& rItem
)
1922 GetProperties().SetMergedItem(rItem
);
1925 void SdrObject::ClearMergedItem(const sal_uInt16 nWhich
)
1927 GetProperties().ClearMergedItem(nWhich
);
1930 void SdrObject::SetObjectItemSet(const SfxItemSet
& rSet
)
1932 GetProperties().SetObjectItemSet(rSet
);
1935 void SdrObject::SetMergedItemSet(const SfxItemSet
& rSet
, bool bClearAllItems
)
1937 GetProperties().SetMergedItemSet(rSet
, bClearAllItems
);
1940 const SfxPoolItem
& SdrObject::GetObjectItem(const sal_uInt16 nWhich
) const
1942 return GetObjectItemSet().Get(nWhich
);
1945 const SfxPoolItem
& SdrObject::GetMergedItem(const sal_uInt16 nWhich
) const
1947 return GetMergedItemSet().Get(nWhich
);
1950 void SdrObject::SetMergedItemSetAndBroadcast(const SfxItemSet
& rSet
, bool bClearAllItems
)
1952 GetProperties().SetMergedItemSetAndBroadcast(rSet
, bClearAllItems
);
1955 void SdrObject::ApplyNotPersistAttr(const SfxItemSet
& rAttr
)
1957 tools::Rectangle aBoundRect0
; if (pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1958 NbcApplyNotPersistAttr(rAttr
);
1960 BroadcastObjectChange();
1961 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1964 void SdrObject::NbcApplyNotPersistAttr(const SfxItemSet
& rAttr
)
1966 const tools::Rectangle
& rSnap
=GetSnapRect();
1967 const tools::Rectangle
& rLogic
=GetLogicRect();
1968 Point
aRef1(rSnap
.Center());
1969 const SfxPoolItem
*pPoolItem
=nullptr;
1970 if (rAttr
.GetItemState(SDRATTR_TRANSFORMREF1X
,true,&pPoolItem
)==SfxItemState::SET
) {
1971 aRef1
.setX(static_cast<const SdrTransformRef1XItem
*>(pPoolItem
)->GetValue() );
1973 if (rAttr
.GetItemState(SDRATTR_TRANSFORMREF1Y
,true,&pPoolItem
)==SfxItemState::SET
) {
1974 aRef1
.setY(static_cast<const SdrTransformRef1YItem
*>(pPoolItem
)->GetValue() );
1977 tools::Rectangle
aNewSnap(rSnap
);
1978 if (rAttr
.GetItemState(SDRATTR_MOVEX
,true,&pPoolItem
)==SfxItemState::SET
) {
1979 tools::Long n
=static_cast<const SdrMoveXItem
*>(pPoolItem
)->GetValue();
1982 if (rAttr
.GetItemState(SDRATTR_MOVEY
,true,&pPoolItem
)==SfxItemState::SET
) {
1983 tools::Long n
=static_cast<const SdrMoveYItem
*>(pPoolItem
)->GetValue();
1986 if (rAttr
.GetItemState(SDRATTR_ONEPOSITIONX
,true,&pPoolItem
)==SfxItemState::SET
) {
1987 tools::Long n
=static_cast<const SdrOnePositionXItem
*>(pPoolItem
)->GetValue();
1988 aNewSnap
.Move(n
-aNewSnap
.Left(),0);
1990 if (rAttr
.GetItemState(SDRATTR_ONEPOSITIONY
,true,&pPoolItem
)==SfxItemState::SET
) {
1991 tools::Long n
=static_cast<const SdrOnePositionYItem
*>(pPoolItem
)->GetValue();
1992 aNewSnap
.Move(0,n
-aNewSnap
.Top());
1994 if (rAttr
.GetItemState(SDRATTR_ONESIZEWIDTH
,true,&pPoolItem
)==SfxItemState::SET
) {
1995 tools::Long n
=static_cast<const SdrOneSizeWidthItem
*>(pPoolItem
)->GetValue();
1996 aNewSnap
.SetRight(aNewSnap
.Left()+n
);
1998 if (rAttr
.GetItemState(SDRATTR_ONESIZEHEIGHT
,true,&pPoolItem
)==SfxItemState::SET
) {
1999 tools::Long n
=static_cast<const SdrOneSizeHeightItem
*>(pPoolItem
)->GetValue();
2000 aNewSnap
.SetBottom(aNewSnap
.Top()+n
);
2002 if (aNewSnap
!=rSnap
) {
2003 if (aNewSnap
.GetSize()==rSnap
.GetSize()) {
2004 NbcMove(Size(aNewSnap
.Left()-rSnap
.Left(),aNewSnap
.Top()-rSnap
.Top()));
2006 NbcSetSnapRect(aNewSnap
);
2010 if (rAttr
.GetItemState(SDRATTR_SHEARANGLE
,true,&pPoolItem
)==SfxItemState::SET
) {
2011 tools::Long n
=static_cast<const SdrShearAngleItem
*>(pPoolItem
)->GetValue();
2014 double nTan
= tan(n
* F_PI18000
);
2015 NbcShear(aRef1
,n
,nTan
,false);
2018 if (rAttr
.GetItemState(SDRATTR_ROTATEANGLE
,true,&pPoolItem
)==SfxItemState::SET
) {
2019 tools::Long n
=static_cast<const SdrAngleItem
*>(pPoolItem
)->GetValue();
2020 n
-=GetRotateAngle();
2022 double nSin
= sin(n
* F_PI18000
);
2023 double nCos
= cos(n
* F_PI18000
);
2024 NbcRotate(aRef1
,n
,nSin
,nCos
);
2027 if (rAttr
.GetItemState(SDRATTR_ROTATEONE
,true,&pPoolItem
)==SfxItemState::SET
) {
2028 tools::Long n
=static_cast<const SdrRotateOneItem
*>(pPoolItem
)->GetValue();
2029 double nSin
= sin(n
* F_PI18000
);
2030 double nCos
= cos(n
* F_PI18000
);
2031 NbcRotate(aRef1
,n
,nSin
,nCos
);
2033 if (rAttr
.GetItemState(SDRATTR_HORZSHEARONE
,true,&pPoolItem
)==SfxItemState::SET
) {
2034 tools::Long n
=static_cast<const SdrHorzShearOneItem
*>(pPoolItem
)->GetValue();
2035 double nTan
= tan(n
* F_PI18000
);
2036 NbcShear(aRef1
,n
,nTan
,false);
2038 if (rAttr
.GetItemState(SDRATTR_VERTSHEARONE
,true,&pPoolItem
)==SfxItemState::SET
) {
2039 tools::Long n
=static_cast<const SdrVertShearOneItem
*>(pPoolItem
)->GetValue();
2040 double nTan
= tan(n
* F_PI18000
);
2041 NbcShear(aRef1
,n
,nTan
,true);
2044 if (rAttr
.GetItemState(SDRATTR_OBJMOVEPROTECT
,true,&pPoolItem
)==SfxItemState::SET
) {
2045 bool b
=static_cast<const SdrYesNoItem
*>(pPoolItem
)->GetValue();
2048 if (rAttr
.GetItemState(SDRATTR_OBJSIZEPROTECT
,true,&pPoolItem
)==SfxItemState::SET
) {
2049 bool b
=static_cast<const SdrYesNoItem
*>(pPoolItem
)->GetValue();
2050 SetResizeProtect(b
);
2053 /* move protect always sets size protect */
2054 if( IsMoveProtect() )
2055 SetResizeProtect( true );
2057 if (rAttr
.GetItemState(SDRATTR_OBJPRINTABLE
,true,&pPoolItem
)==SfxItemState::SET
) {
2058 bool b
=static_cast<const SdrObjPrintableItem
*>(pPoolItem
)->GetValue();
2062 if (rAttr
.GetItemState(SDRATTR_OBJVISIBLE
,true,&pPoolItem
)==SfxItemState::SET
) {
2063 bool b
=static_cast<const SdrObjVisibleItem
*>(pPoolItem
)->GetValue();
2067 SdrLayerID nLayer
=SDRLAYER_NOTFOUND
;
2068 if (rAttr
.GetItemState(SDRATTR_LAYERID
,true,&pPoolItem
)==SfxItemState::SET
) {
2069 nLayer
=static_cast<const SdrLayerIdItem
*>(pPoolItem
)->GetValue();
2071 if (rAttr
.GetItemState(SDRATTR_LAYERNAME
,true,&pPoolItem
)==SfxItemState::SET
)
2073 OUString aLayerName
= static_cast<const SdrLayerNameItem
*>(pPoolItem
)->GetValue();
2074 const SdrLayerAdmin
& rLayAd(nullptr != getSdrPageFromSdrObject()
2075 ? getSdrPageFromSdrObject()->GetLayerAdmin()
2076 : getSdrModelFromSdrObject().GetLayerAdmin());
2077 const SdrLayer
* pLayer
= rLayAd
.GetLayer(aLayerName
);
2079 if(nullptr != pLayer
)
2081 nLayer
=pLayer
->GetID();
2084 if (nLayer
!=SDRLAYER_NOTFOUND
) {
2085 NbcSetLayer(nLayer
);
2088 if (rAttr
.GetItemState(SDRATTR_OBJECTNAME
,true,&pPoolItem
)==SfxItemState::SET
) {
2089 OUString aName
=static_cast<const SfxStringItem
*>(pPoolItem
)->GetValue();
2092 tools::Rectangle
aNewLogic(rLogic
);
2093 if (rAttr
.GetItemState(SDRATTR_LOGICSIZEWIDTH
,true,&pPoolItem
)==SfxItemState::SET
) {
2094 tools::Long n
=static_cast<const SdrLogicSizeWidthItem
*>(pPoolItem
)->GetValue();
2095 aNewLogic
.SetRight(aNewLogic
.Left()+n
);
2097 if (rAttr
.GetItemState(SDRATTR_LOGICSIZEHEIGHT
,true,&pPoolItem
)==SfxItemState::SET
) {
2098 tools::Long n
=static_cast<const SdrLogicSizeHeightItem
*>(pPoolItem
)->GetValue();
2099 aNewLogic
.SetBottom(aNewLogic
.Top()+n
);
2101 if (aNewLogic
!=rLogic
) {
2102 NbcSetLogicRect(aNewLogic
);
2104 Fraction
aResizeX(1,1);
2105 Fraction
aResizeY(1,1);
2106 if (rAttr
.GetItemState(SDRATTR_RESIZEXONE
,true,&pPoolItem
)==SfxItemState::SET
) {
2107 aResizeX
*=static_cast<const SdrResizeXOneItem
*>(pPoolItem
)->GetValue();
2109 if (rAttr
.GetItemState(SDRATTR_RESIZEYONE
,true,&pPoolItem
)==SfxItemState::SET
) {
2110 aResizeY
*=static_cast<const SdrResizeYOneItem
*>(pPoolItem
)->GetValue();
2112 if (aResizeX
!=Fraction(1,1) || aResizeY
!=Fraction(1,1)) {
2113 NbcResize(aRef1
,aResizeX
,aResizeY
);
2117 void SdrObject::TakeNotPersistAttr(SfxItemSet
& rAttr
) const
2119 const tools::Rectangle
& rSnap
=GetSnapRect();
2120 const tools::Rectangle
& rLogic
=GetLogicRect();
2121 rAttr
.Put(SdrYesNoItem(SDRATTR_OBJMOVEPROTECT
, IsMoveProtect()));
2122 rAttr
.Put(SdrYesNoItem(SDRATTR_OBJSIZEPROTECT
, IsResizeProtect()));
2123 rAttr
.Put(SdrObjPrintableItem(IsPrintable()));
2124 rAttr
.Put(SdrObjVisibleItem(IsVisible()));
2125 rAttr
.Put(SdrAngleItem(SDRATTR_ROTATEANGLE
, GetRotateAngle()));
2126 rAttr
.Put(SdrShearAngleItem(GetShearAngle()));
2127 rAttr
.Put(SdrOneSizeWidthItem(rSnap
.GetWidth()-1));
2128 rAttr
.Put(SdrOneSizeHeightItem(rSnap
.GetHeight()-1));
2129 rAttr
.Put(SdrOnePositionXItem(rSnap
.Left()));
2130 rAttr
.Put(SdrOnePositionYItem(rSnap
.Top()));
2131 if (rLogic
.GetWidth()!=rSnap
.GetWidth()) {
2132 rAttr
.Put(SdrLogicSizeWidthItem(rLogic
.GetWidth()-1));
2134 if (rLogic
.GetHeight()!=rSnap
.GetHeight()) {
2135 rAttr
.Put(SdrLogicSizeHeightItem(rLogic
.GetHeight()-1));
2137 OUString
aName(GetName());
2139 if (!aName
.isEmpty())
2141 rAttr
.Put(SfxStringItem(SDRATTR_OBJECTNAME
, aName
));
2144 rAttr
.Put(SdrLayerIdItem(GetLayer()));
2145 const SdrLayerAdmin
& rLayAd(nullptr != getSdrPageFromSdrObject()
2146 ? getSdrPageFromSdrObject()->GetLayerAdmin()
2147 : getSdrModelFromSdrObject().GetLayerAdmin());
2148 const SdrLayer
* pLayer
= rLayAd
.GetLayerPerID(GetLayer());
2149 if(nullptr != pLayer
)
2151 rAttr
.Put(SdrLayerNameItem(pLayer
->GetName()));
2153 Point
aRef1(rSnap
.Center());
2154 Point
aRef2(aRef1
); aRef2
.AdjustY( 1 );
2155 rAttr
.Put(SdrTransformRef1XItem(aRef1
.X()));
2156 rAttr
.Put(SdrTransformRef1YItem(aRef1
.Y()));
2157 rAttr
.Put(SdrTransformRef2XItem(aRef2
.X()));
2158 rAttr
.Put(SdrTransformRef2YItem(aRef2
.Y()));
2161 SfxStyleSheet
* SdrObject::GetStyleSheet() const
2163 return GetProperties().GetStyleSheet();
2166 void SdrObject::SetStyleSheet(SfxStyleSheet
* pNewStyleSheet
, bool bDontRemoveHardAttr
)
2168 tools::Rectangle aBoundRect0
;
2171 aBoundRect0
= GetLastBoundRect();
2173 NbcSetStyleSheet(pNewStyleSheet
, bDontRemoveHardAttr
);
2175 BroadcastObjectChange();
2176 SendUserCall(SdrUserCallType::ChangeAttr
, aBoundRect0
);
2179 void SdrObject::NbcSetStyleSheet(SfxStyleSheet
* pNewStyleSheet
, bool bDontRemoveHardAttr
)
2181 GetProperties().SetStyleSheet(pNewStyleSheet
, bDontRemoveHardAttr
);
2184 // Broadcasting while setting attributes is managed by the AttrObj.
2187 SdrGluePoint
SdrObject::GetVertexGluePoint(sal_uInt16 nPosNum
) const
2189 // #i41936# Use SnapRect for default GluePoints
2190 const tools::Rectangle
aR(GetSnapRect());
2195 case 0 : aPt
= aR
.TopCenter(); break;
2196 case 1 : aPt
= aR
.RightCenter(); break;
2197 case 2 : aPt
= aR
.BottomCenter(); break;
2198 case 3 : aPt
= aR
.LeftCenter(); break;
2202 SdrGluePoint
aGP(aPt
);
2203 aGP
.SetPercent(false);
2208 SdrGluePoint
SdrObject::GetCornerGluePoint(sal_uInt16 nPosNum
) const
2210 tools::Rectangle
aR(GetCurrentBoundRect());
2213 case 0 : aPt
=aR
.TopLeft(); break;
2214 case 1 : aPt
=aR
.TopRight(); break;
2215 case 2 : aPt
=aR
.BottomRight(); break;
2216 case 3 : aPt
=aR
.BottomLeft(); break;
2218 aPt
-=GetSnapRect().Center();
2219 SdrGluePoint
aGP(aPt
);
2220 aGP
.SetPercent(false);
2224 const SdrGluePointList
* SdrObject::GetGluePointList() const
2226 if (pPlusData
!=nullptr) return pPlusData
->pGluePoints
.get();
2231 SdrGluePointList
* SdrObject::ForceGluePointList()
2234 if (pPlusData
->pGluePoints
==nullptr) {
2235 pPlusData
->pGluePoints
.reset(new SdrGluePointList
);
2237 return pPlusData
->pGluePoints
.get();
2240 void SdrObject::SetGlueReallyAbsolute(bool bOn
)
2242 // First a const call to see whether there are any glue points.
2243 // Force const call!
2244 if (GetGluePointList()!=nullptr) {
2245 SdrGluePointList
* pGPL
=ForceGluePointList();
2246 pGPL
->SetReallyAbsolute(bOn
,*this);
2250 void SdrObject::NbcRotateGluePoints(const Point
& rRef
, tools::Long nAngle
, double sn
, double cs
)
2252 // First a const call to see whether there are any glue points.
2253 // Force const call!
2254 if (GetGluePointList()!=nullptr) {
2255 SdrGluePointList
* pGPL
=ForceGluePointList();
2256 pGPL
->Rotate(rRef
,nAngle
,sn
,cs
,this);
2260 void SdrObject::NbcMirrorGluePoints(const Point
& rRef1
, const Point
& rRef2
)
2262 // First a const call to see whether there are any glue points.
2263 // Force const call!
2264 if (GetGluePointList()!=nullptr) {
2265 SdrGluePointList
* pGPL
=ForceGluePointList();
2266 pGPL
->Mirror(rRef1
,rRef2
,this);
2270 void SdrObject::NbcShearGluePoints(const Point
& rRef
, double tn
, bool bVShear
)
2272 // First a const call to see whether there are any glue points.
2273 // Force const call!
2274 if (GetGluePointList()!=nullptr) {
2275 SdrGluePointList
* pGPL
=ForceGluePointList();
2276 pGPL
->Shear(rRef
,tn
,bVShear
,this);
2280 void SdrObject::ConnectToNode(bool /*bTail1*/, SdrObject
* /*pObj*/)
2284 void SdrObject::DisconnectFromNode(bool /*bTail1*/)
2288 SdrObject
* SdrObject::GetConnectedNode(bool /*bTail1*/) const
2294 static void extractLineContourFromPrimitive2DSequence(
2295 const drawinglayer::primitive2d::Primitive2DContainer
& rxSequence
,
2296 basegfx::B2DPolygonVector
& rExtractedHairlines
,
2297 basegfx::B2DPolyPolygonVector
& rExtractedLineFills
)
2299 rExtractedHairlines
.clear();
2300 rExtractedLineFills
.clear();
2302 if(rxSequence
.empty())
2305 // use neutral ViewInformation
2306 const drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
2308 // create extractor, process and get result
2309 drawinglayer::processor2d::LineGeometryExtractor2D
aExtractor(aViewInformation2D
);
2310 aExtractor
.process(rxSequence
);
2312 // copy line results
2313 rExtractedHairlines
= aExtractor
.getExtractedHairlines();
2316 rExtractedLineFills
= aExtractor
.getExtractedLineFills();
2320 SdrObject
* SdrObject::ImpConvertToContourObj(bool bForceLineDash
)
2322 SdrObject
* pRetval(nullptr);
2324 if(LineGeometryUsageIsNecessary())
2326 basegfx::B2DPolyPolygon aMergedLineFillPolyPolygon
;
2327 basegfx::B2DPolyPolygon aMergedHairlinePolyPolygon
;
2328 const drawinglayer::primitive2d::Primitive2DContainer
& xSequence(GetViewContact().getViewIndependentPrimitive2DContainer());
2330 if(!xSequence
.empty())
2332 basegfx::B2DPolygonVector aExtractedHairlines
;
2333 basegfx::B2DPolyPolygonVector aExtractedLineFills
;
2335 extractLineContourFromPrimitive2DSequence(xSequence
, aExtractedHairlines
, aExtractedLineFills
);
2337 // for SdrObject creation, just copy all to a single Hairline-PolyPolygon
2338 for(const basegfx::B2DPolygon
& rExtractedHairline
: aExtractedHairlines
)
2340 aMergedHairlinePolyPolygon
.append(rExtractedHairline
);
2343 // check for fill rsults
2344 if (!aExtractedLineFills
.empty() && !utl::ConfigManager::IsFuzzing())
2346 // merge to a single tools::PolyPolygon (OR)
2347 aMergedLineFillPolyPolygon
= basegfx::utils::mergeToSinglePolyPolygon(aExtractedLineFills
);
2351 if(aMergedLineFillPolyPolygon
.count() || (bForceLineDash
&& aMergedHairlinePolyPolygon
.count()))
2353 SfxItemSet
aSet(GetMergedItemSet());
2354 drawing::FillStyle eOldFillStyle
= aSet
.Get(XATTR_FILLSTYLE
).GetValue();
2355 SdrPathObj
* aLinePolygonPart
= nullptr;
2356 SdrPathObj
* aLineHairlinePart
= nullptr;
2357 bool bBuildGroup(false);
2359 if(aMergedLineFillPolyPolygon
.count())
2361 // create SdrObject for filled line geometry
2362 aLinePolygonPart
= new SdrPathObj(
2363 getSdrModelFromSdrObject(),
2365 aMergedLineFillPolyPolygon
);
2367 // correct item properties
2368 aSet
.Put(XLineWidthItem(0));
2369 aSet
.Put(XLineStyleItem(drawing::LineStyle_NONE
));
2370 Color aColorLine
= aSet
.Get(XATTR_LINECOLOR
).GetColorValue();
2371 sal_uInt16 nTransLine
= aSet
.Get(XATTR_LINETRANSPARENCE
).GetValue();
2372 aSet
.Put(XFillColorItem(OUString(), aColorLine
));
2373 aSet
.Put(XFillStyleItem(drawing::FillStyle_SOLID
));
2374 aSet
.Put(XFillTransparenceItem(nTransLine
));
2376 aLinePolygonPart
->SetMergedItemSet(aSet
);
2379 if(aMergedHairlinePolyPolygon
.count())
2381 // create SdrObject for hairline geometry
2382 // OBJ_PATHLINE is necessary here, not OBJ_PATHFILL. This is intended
2383 // to get a non-filled object. If the poly is closed, the PathObj takes care for
2384 // the correct closed state.
2385 aLineHairlinePart
= new SdrPathObj(
2386 getSdrModelFromSdrObject(),
2388 aMergedHairlinePolyPolygon
);
2390 aSet
.Put(XLineWidthItem(0));
2391 aSet
.Put(XFillStyleItem(drawing::FillStyle_NONE
));
2392 aSet
.Put(XLineStyleItem(drawing::LineStyle_SOLID
));
2394 // it is also necessary to switch off line start and ends here
2395 aSet
.Put(XLineStartWidthItem(0));
2396 aSet
.Put(XLineEndWidthItem(0));
2398 aLineHairlinePart
->SetMergedItemSet(aSet
);
2400 if(aLinePolygonPart
)
2406 // check if original geometry should be added (e.g. filled and closed)
2407 bool bAddOriginalGeometry(false);
2408 SdrPathObj
* pPath
= dynamic_cast<SdrPathObj
*>(this);
2410 if(pPath
&& pPath
->IsClosed())
2412 if(eOldFillStyle
!= drawing::FillStyle_NONE
)
2414 bAddOriginalGeometry
= true;
2418 // do we need a group?
2419 if(bBuildGroup
|| bAddOriginalGeometry
)
2421 SdrObject
* pGroup
= new SdrObjGroup(getSdrModelFromSdrObject());
2423 if(bAddOriginalGeometry
)
2425 // Add a clone of the original geometry.
2427 aSet
.Put(GetMergedItemSet());
2428 aSet
.Put(XLineStyleItem(drawing::LineStyle_NONE
));
2429 aSet
.Put(XLineWidthItem(0));
2431 SdrObject
* pClone(CloneSdrObject(getSdrModelFromSdrObject()));
2432 pClone
->SetMergedItemSet(aSet
);
2434 pGroup
->GetSubList()->NbcInsertObject(pClone
);
2437 if(aLinePolygonPart
)
2439 pGroup
->GetSubList()->NbcInsertObject(aLinePolygonPart
);
2442 if(aLineHairlinePart
)
2444 pGroup
->GetSubList()->NbcInsertObject(aLineHairlinePart
);
2451 if(aLinePolygonPart
)
2453 pRetval
= aLinePolygonPart
;
2455 else if(aLineHairlinePart
)
2457 pRetval
= aLineHairlinePart
;
2463 if(nullptr == pRetval
)
2465 // due to current method usage, create and return a clone when nothing has changed
2466 SdrObject
* pClone(CloneSdrObject(getSdrModelFromSdrObject()));
2474 void SdrObject::SetMarkProtect(bool bProt
)
2480 void SdrObject::SetEmptyPresObj(bool bEpt
)
2482 bEmptyPresObj
= bEpt
;
2486 void SdrObject::SetNotVisibleAsMaster(bool bFlg
)
2488 bNotVisibleAsMaster
=bFlg
;
2492 // convert this path object to contour object, even when it is a group
2493 SdrObject
* SdrObject::ConvertToContourObj(SdrObject
* pRet
, bool bForceLineDash
) const
2495 if(dynamic_cast<const SdrObjGroup
*>( pRet
) != nullptr)
2497 SdrObjList
* pObjList2
= pRet
->GetSubList();
2498 SdrObject
* pGroup
= new SdrObjGroup(getSdrModelFromSdrObject());
2500 for(size_t a
=0; a
<pObjList2
->GetObjCount(); ++a
)
2502 SdrObject
* pIterObj
= pObjList2
->GetObj(a
);
2503 pGroup
->GetSubList()->NbcInsertObject(ConvertToContourObj(pIterObj
, bForceLineDash
));
2510 if (SdrPathObj
*pPathObj
= dynamic_cast<SdrPathObj
*>(pRet
))
2512 // bezier geometry got created, even for straight edges since the given
2513 // object is a result of DoConvertToPolyObj. For conversion to contour
2514 // this is not really needed and can be reduced again AFAP
2515 pPathObj
->SetPathPoly(basegfx::utils::simplifyCurveSegments(pPathObj
->GetPathPoly()));
2518 pRet
= pRet
->ImpConvertToContourObj(bForceLineDash
);
2521 // #i73441# preserve LayerID
2522 if(pRet
&& pRet
->GetLayer() != GetLayer())
2524 pRet
->SetLayer(GetLayer());
2531 SdrObjectUniquePtr
SdrObject::ConvertToPolyObj(bool bBezier
, bool bLineToArea
) const
2533 SdrObjectUniquePtr pRet
= DoConvertToPolyObj(bBezier
, true);
2535 if(pRet
&& bLineToArea
)
2537 SdrObject
* pNewRet
= ConvertToContourObj(pRet
.get());
2538 pRet
.reset(pNewRet
);
2541 // #i73441# preserve LayerID
2542 if(pRet
&& pRet
->GetLayer() != GetLayer())
2544 pRet
->SetLayer(GetLayer());
2551 SdrObjectUniquePtr
SdrObject::DoConvertToPolyObj(bool /*bBezier*/, bool /*bAddText*/) const
2557 void SdrObject::InsertedStateChange()
2559 const bool bIsInserted(nullptr != getParentSdrObjListFromSdrObject());
2560 const tools::Rectangle
aBoundRect0(GetLastBoundRect());
2564 SendUserCall(SdrUserCallType::Inserted
, aBoundRect0
);
2568 SendUserCall(SdrUserCallType::Removed
, aBoundRect0
);
2571 if(nullptr != pPlusData
&& nullptr != pPlusData
->pBroadcast
)
2573 SdrHint
aHint(bIsInserted
? SdrHintKind::ObjectInserted
: SdrHintKind::ObjectRemoved
, *this);
2574 pPlusData
->pBroadcast
->Broadcast(aHint
);
2578 void SdrObject::SetMoveProtect(bool bProt
)
2580 if(IsMoveProtect() != bProt
)
2582 // #i77187# secured and simplified
2585 BroadcastObjectChange();
2589 void SdrObject::SetResizeProtect(bool bProt
)
2591 if(IsResizeProtect() != bProt
)
2593 // #i77187# secured and simplified
2596 BroadcastObjectChange();
2600 void SdrObject::SetPrintable(bool bPrn
)
2602 if( bPrn
== bNoPrint
)
2608 SdrHint
aHint(SdrHintKind::ObjectChange
, *this);
2609 getSdrModelFromSdrObject().Broadcast(aHint
);
2614 void SdrObject::SetVisible(bool bVisible
)
2616 if( bVisible
!= mbVisible
)
2618 mbVisible
= bVisible
;
2622 SdrHint
aHint(SdrHintKind::ObjectChange
, *this);
2623 getSdrModelFromSdrObject().Broadcast(aHint
);
2629 sal_uInt16
SdrObject::GetUserDataCount() const
2631 if (pPlusData
==nullptr || pPlusData
->pUserDataList
==nullptr) return 0;
2632 return pPlusData
->pUserDataList
->GetUserDataCount();
2635 SdrObjUserData
* SdrObject::GetUserData(sal_uInt16 nNum
) const
2637 if (pPlusData
==nullptr || pPlusData
->pUserDataList
==nullptr) return nullptr;
2638 return &pPlusData
->pUserDataList
->GetUserData(nNum
);
2641 void SdrObject::AppendUserData(std::unique_ptr
<SdrObjUserData
> pData
)
2645 OSL_FAIL("SdrObject::AppendUserData(): pData is NULL pointer.");
2650 if (!pPlusData
->pUserDataList
)
2651 pPlusData
->pUserDataList
.reset( new SdrObjUserDataList
);
2653 pPlusData
->pUserDataList
->AppendUserData(std::move(pData
));
2656 void SdrObject::DeleteUserData(sal_uInt16 nNum
)
2658 sal_uInt16 nCount
=GetUserDataCount();
2660 pPlusData
->pUserDataList
->DeleteUserData(nNum
);
2662 pPlusData
->pUserDataList
.reset();
2665 OSL_FAIL("SdrObject::DeleteUserData(): Invalid Index.");
2669 void SdrObject::SetUserCall(SdrObjUserCall
* pUser
)
2675 void SdrObject::SendUserCall(SdrUserCallType eUserCall
, const tools::Rectangle
& rBoundRect
) const
2677 SdrObject
* pGroup(getParentSdrObjectFromSdrObject());
2681 pUserCall
->Changed( *this, eUserCall
, rBoundRect
);
2684 if(nullptr != pGroup
&& pGroup
->GetUserCall())
2686 // broadcast to group
2687 SdrUserCallType eChildUserType
= SdrUserCallType::ChildChangeAttr
;
2691 case SdrUserCallType::MoveOnly
:
2692 eChildUserType
= SdrUserCallType::ChildMoveOnly
;
2695 case SdrUserCallType::Resize
:
2696 eChildUserType
= SdrUserCallType::ChildResize
;
2699 case SdrUserCallType::ChangeAttr
:
2700 eChildUserType
= SdrUserCallType::ChildChangeAttr
;
2703 case SdrUserCallType::Delete
:
2704 eChildUserType
= SdrUserCallType::ChildDelete
;
2707 case SdrUserCallType::Inserted
:
2708 eChildUserType
= SdrUserCallType::ChildInserted
;
2711 case SdrUserCallType::Removed
:
2712 eChildUserType
= SdrUserCallType::ChildRemoved
;
2718 pGroup
->GetUserCall()->Changed( *this, eChildUserType
, rBoundRect
);
2721 // notify our UNO shape listeners
2722 switch ( eUserCall
)
2724 case SdrUserCallType::Resize
:
2725 notifyShapePropertyChange( svx::ShapeProperty::Size
);
2726 [[fallthrough
]]; // RESIZE might also imply a change of the position
2727 case SdrUserCallType::MoveOnly
:
2728 notifyShapePropertyChange( svx::ShapeProperty::Position
);
2731 // not interested in
2736 void SdrObject::impl_setUnoShape( const uno::Reference
< uno::XInterface
>& _rxUnoShape
)
2738 const uno::Reference
< uno::XInterface
>& xOldUnoShape( maWeakUnoShape
);
2739 // the UNO shape would be gutted by the following code; return early
2740 if ( _rxUnoShape
== xOldUnoShape
)
2742 if ( !xOldUnoShape
.is() )
2744 // make sure there is no stale impl. pointer if the UNO
2745 // shape was destroyed meanwhile (remember we only hold weak
2746 // reference to it!)
2747 mpSvxShape
= nullptr;
2752 bool bTransferOwnership( false );
2753 if ( xOldUnoShape
.is() )
2755 bTransferOwnership
= mpSvxShape
->HasSdrObjectOwnership();
2756 // Remove yourself from the current UNO shape. Its destructor
2757 // will reset our UNO shape otherwise.
2758 mpSvxShape
->InvalidateSdrObject();
2761 maWeakUnoShape
= _rxUnoShape
;
2762 mpSvxShape
= comphelper::getUnoTunnelImplementation
<SvxShape
>( _rxUnoShape
);
2764 // I think this may never happen... But I am not sure enough .-)
2765 if ( bTransferOwnership
)
2768 mpSvxShape
->TakeSdrObjectOwnership();
2769 SAL_WARN( "svx.uno", "a UNO shape took over an SdrObject previously owned by another UNO shape!");
2773 /** only for internal use! */
2774 SvxShape
* SdrObject::getSvxShape()
2776 DBG_TESTSOLARMUTEX();
2777 // retrieving the impl pointer and subsequently using it is not thread-safe, of course, so it needs to be
2778 // guarded by the SolarMutex
2780 uno::Reference
< uno::XInterface
> xShape( maWeakUnoShape
);
2781 #if OSL_DEBUG_LEVEL > 0
2782 OSL_ENSURE( !( !xShape
.is() && mpSvxShape
),
2783 "SdrObject::getSvxShape: still having IMPL-Pointer to dead object!" );
2785 //#113608#, make sure mpSvxShape is always synchronized with maWeakUnoShape
2786 if ( mpSvxShape
&& !xShape
.is() )
2787 mpSvxShape
= nullptr;
2792 css::uno::Reference
< css::uno::XInterface
> SdrObject::getUnoShape()
2794 // try weak reference first
2795 uno::Reference
< uno::XInterface
> xShape( getWeakUnoShape() );
2798 OSL_ENSURE( mpSvxShape
== nullptr, "SdrObject::getUnoShape: XShape already dead, but still an IMPL pointer!" );
2800 // try to access SdrPage from this SdrObject. This will only exist if the SdrObject is
2801 // inserted in a SdrObjList (page/group/3dScene)
2802 SdrPage
* pPageCandidate(getSdrPageFromSdrObject());
2804 // tdf#12152, tdf#120728
2806 // With the paradigm change to only get a SdrPage for a SdrObject when the SdrObject
2807 // is *inserted*, the functionality for creating 1:1 associated UNO API implementation
2808 // SvxShapes was partially broken: The used ::CreateShape relies on the SvxPage being
2809 // derived and the CreateShape method overloaded, implementing additional SdrInventor
2812 // The fallback to use SvxDrawPage::CreateShapeByTypeAndInventor is a trap: It's only
2813 // a static fallback that handles the SdrInventor types SdrInventor::E3d and
2814 // SdrInventor::Default. Due to that, e.g. the ReportDesigner broke in various conditions.
2816 // That again has to do with the ReportDesigner being implemented using the UNO API
2817 // aspects of SdrObjects early during their construction, not just after these are
2818 // inserted to a SdrPage - but that is not illegal or wrong, the SdrObject exists already.
2820 // As a current solution, use the (now always available) SdrModel and any of the
2821 // existing SdrPages. The only important thing is to get a SdrPage where ::CreateShape is
2822 // overloaded and implemented as needed.
2824 // Note for the future:
2825 // In a more ideal world there would be only one factory method for creating SdrObjects (not
2826 // ::CreateShape and ::CreateShapeByTypeAndInventor). This also would not be placed at
2827 // SdrPage/SvxPage at all, but at the Model where it belongs - where else would you expect
2828 // objects for the current Model to be constructed? To have this at the Page only would make
2829 // sense if different shapes would need to be constructed for different Pages in the same Model
2830 // - this is never the case.
2831 // At that Model extended functionality for that factory (or overloads and implementations)
2832 // should be placed. But to be realistic, migrating the factories to Model now is too much
2833 // work - maybe over time when melting SdrObject/SvxObject one day...
2834 if(nullptr == pPageCandidate
)
2836 // If not inserted, alternatively access a SdrPage using the SdrModel. There is
2837 // no reason not to create and return a UNO API XShape when the SdrObject is not
2838 // inserted - it may be in construction. Main paradigm is that it exists.
2839 if(0 != getSdrModelFromSdrObject().GetPageCount())
2841 // Take 1st SdrPage. That may be e.g. a special page (in SD), but the
2842 // to-be-used method ::CreateShape will be correctly overloaded in
2844 pPageCandidate
= getSdrModelFromSdrObject().GetPage(0);
2848 if(nullptr != pPageCandidate
)
2850 uno::Reference
< uno::XInterface
> xPage(pPageCandidate
->getUnoPage());
2853 SvxDrawPage
* pDrawPage
= comphelper::getUnoTunnelImplementation
<SvxDrawPage
>(xPage
);
2857 xShape
= pDrawPage
->CreateShape( this );
2858 impl_setUnoShape( xShape
);
2864 // Fallback to static base functionality. CAUTION: This will only support
2865 // the most basic stuff like SdrInventor::E3d and SdrInventor::Default. All
2866 // the other SdrInventor enum entries are from overloads and are *not accessible*
2867 // using this fallback (!) - what a bad trap
2868 mpSvxShape
= SvxDrawPage::CreateShapeByTypeAndInventor( GetObjIdentifier(), GetObjInventor(), this );
2869 maWeakUnoShape
= xShape
= static_cast< ::cppu::OWeakObject
* >( mpSvxShape
);
2876 void SdrObject::setUnoShape(const uno::Reference
<uno::XInterface
>& _rxUnoShape
)
2878 impl_setUnoShape( _rxUnoShape
);
2881 svx::PropertyChangeNotifier
& SdrObject::getShapePropertyChangeNotifier()
2883 DBG_TESTSOLARMUTEX();
2885 SvxShape
* pSvxShape
= getSvxShape();
2886 ENSURE_OR_THROW( pSvxShape
, "no SvxShape, yet!" );
2887 return pSvxShape
->getShapePropertyChangeNotifier();
2890 void SdrObject::notifyShapePropertyChange( const svx::ShapeProperty _eProperty
) const
2892 DBG_TESTSOLARMUTEX();
2894 SvxShape
* pSvxShape
= const_cast< SdrObject
* >( this )->getSvxShape();
2896 return pSvxShape
->getShapePropertyChangeNotifier().notifyPropertyChange( _eProperty
);
2900 // transformation interface for StarOfficeAPI. This implements support for
2901 // homogeneous 3x3 matrices containing the transformation of the SdrObject. At the
2902 // moment it contains a shearX, rotation and translation, but for setting all linear
2903 // transforms like Scale, ShearX, ShearY, Rotate and Translate are supported.
2906 // gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon
2907 // with the base geometry and returns TRUE. Otherwise it returns FALSE.
2908 bool SdrObject::TRGetBaseGeometry(basegfx::B2DHomMatrix
& rMatrix
, basegfx::B2DPolyPolygon
& /*rPolyPolygon*/) const
2910 // any kind of SdrObject, just use SnapRect
2911 tools::Rectangle
aRectangle(GetSnapRect());
2913 // convert to transformation values
2914 basegfx::B2DTuple
aScale(aRectangle
.GetWidth(), aRectangle
.GetHeight());
2915 basegfx::B2DTuple
aTranslate(aRectangle
.Left(), aRectangle
.Top());
2917 // position maybe relative to anchorpos, convert
2918 if(getSdrModelFromSdrObject().IsWriter())
2920 if(GetAnchorPos().X() || GetAnchorPos().Y())
2922 aTranslate
-= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
2927 rMatrix
= basegfx::utils::createScaleTranslateB2DHomMatrix(aScale
, aTranslate
);
2932 // sets the base geometry of the object using infos contained in the homogeneous 3x3 matrix.
2933 // If it's an SdrPathObj it will use the provided geometry information. The Polygon has
2934 // to use (0,0) as upper left and will be scaled to the given size in the matrix.
2935 void SdrObject::TRSetBaseGeometry(const basegfx::B2DHomMatrix
& rMatrix
, const basegfx::B2DPolyPolygon
& /*rPolyPolygon*/)
2938 basegfx::B2DTuple aScale
;
2939 basegfx::B2DTuple aTranslate
;
2940 double fRotate
, fShearX
;
2941 rMatrix
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
2943 // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
2944 // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
2945 if(basegfx::fTools::less(aScale
.getX(), 0.0) && basegfx::fTools::less(aScale
.getY(), 0.0))
2947 aScale
.setX(fabs(aScale
.getX()));
2948 aScale
.setY(fabs(aScale
.getY()));
2951 // if anchor is used, make position relative to it
2952 if(getSdrModelFromSdrObject().IsWriter())
2954 if(GetAnchorPos().X() || GetAnchorPos().Y())
2956 aTranslate
+= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
2961 Point
aPoint(FRound(aTranslate
.getX()), FRound(aTranslate
.getY()));
2962 tools::Rectangle
aBaseRect(aPoint
, Size(FRound(aScale
.getX()), FRound(aScale
.getY())));
2965 SetSnapRect(aBaseRect
);
2968 // Give info if object is in destruction
2969 bool SdrObject::IsInDestruction() const
2971 return getSdrModelFromSdrObject().IsInDestruction();
2974 // return if fill is != drawing::FillStyle_NONE
2975 bool SdrObject::HasFillStyle() const
2977 return GetObjectItem(XATTR_FILLSTYLE
).GetValue() != drawing::FillStyle_NONE
;
2980 bool SdrObject::HasLineStyle() const
2982 return GetObjectItem(XATTR_LINESTYLE
).GetValue() != drawing::LineStyle_NONE
;
2987 // on import of OLE object from MS documents the BLIP size might be retrieved,
2988 // the following four methods are used to control it;
2989 // usually this data makes no sense after the import is finished, since the object
2993 void SdrObject::SetBLIPSizeRectangle( const tools::Rectangle
& aRect
)
2995 maBLIPSizeRectangle
= aRect
;
2998 void SdrObject::SetContextWritingMode( const sal_Int16
/*_nContextWritingMode*/ )
3000 // this base class does not support different writing modes, so ignore the call
3003 void SdrObject::SetDoNotInsertIntoPageAutomatically(const bool bSet
)
3005 mbDoNotInsertIntoPageAutomatically
= bSet
;
3010 bool SdrObject::HasText() const
3015 bool SdrObject::IsTextBox() const
3020 void SdrObject::MakeNameUnique()
3022 std::unordered_set
<OUString
> aNameSet
;
3023 MakeNameUnique(aNameSet
);
3026 void SdrObject::MakeNameUnique(std::unordered_set
<OUString
>& rNameSet
)
3028 if (GetName().isEmpty())
3031 if (rNameSet
.empty())
3035 for (sal_uInt16
nPage(0); nPage
< mrSdrModelFromSdrObject
.GetPageCount(); ++nPage
)
3037 pPage
= mrSdrModelFromSdrObject
.GetPage(nPage
);
3038 SdrObjListIter
aIter(pPage
, SdrIterMode::DeepWithGroups
);
3039 while (aIter
.IsMore())
3041 pObj
= aIter
.Next();
3043 rNameSet
.insert(pObj
->GetName());
3048 OUString
sName(GetName());
3049 OUString
sRootName(GetName());
3050 sal_Int32 index
= sName
.lastIndexOf("_");
3052 sRootName
= sRootName
.copy(0, index
);
3055 while (rNameSet
.find(sName
) != rNameSet
.end())
3057 sName
= sRootName
+ "_" + OUString::number(n
++);
3059 rNameSet
.insert(sName
);
3064 SdrObject
* SdrObjFactory::CreateObjectFromFactory(SdrModel
& rSdrModel
, SdrInventor nInventor
, SdrObjKind nObjIdentifier
)
3066 SdrObjCreatorParams aParams
{ nInventor
, nObjIdentifier
, rSdrModel
};
3067 for (const auto & i
: ImpGetUserMakeObjHdl()) {
3068 SdrObject
* pObj
= i
.Call(aParams
);
3076 SdrObject
* SdrObjFactory::MakeNewObject(
3077 SdrModel
& rSdrModel
,
3078 SdrInventor nInventor
,
3079 SdrObjKind nIdentifier
,
3080 const tools::Rectangle
* pSnapRect
)
3082 SdrObject
* pObj(nullptr);
3083 bool bSetSnapRect(nullptr != pSnapRect
);
3085 if (nInventor
== SdrInventor::Default
)
3087 switch (nIdentifier
)
3091 if(nullptr != pSnapRect
)
3093 pObj
= new SdrMeasureObj(
3095 pSnapRect
->TopLeft(),
3096 pSnapRect
->BottomRight());
3100 pObj
= new SdrMeasureObj(rSdrModel
);
3106 if(nullptr != pSnapRect
)
3108 basegfx::B2DPolygon aPoly
;
3117 pSnapRect
->Bottom()));
3118 pObj
= new SdrPathObj(
3121 basegfx::B2DPolyPolygon(aPoly
));
3125 pObj
= new SdrPathObj(
3133 case OBJ_OUTLINETEXT
:
3135 if(nullptr != pSnapRect
)
3137 pObj
= new SdrRectObj(
3141 bSetSnapRect
= false;
3145 pObj
= new SdrRectObj(
3156 SdrCircKind eCircKind
= ToSdrCircKind(nIdentifier
);
3157 if(nullptr != pSnapRect
)
3159 pObj
= new SdrCircObj(rSdrModel
, eCircKind
, *pSnapRect
);
3160 bSetSnapRect
= false;
3164 pObj
= new SdrCircObj(rSdrModel
, eCircKind
);
3168 case OBJ_NONE
: pObj
=new SdrObject(rSdrModel
); break;
3169 case OBJ_GRUP
: pObj
=new SdrObjGroup(rSdrModel
); break;
3170 case OBJ_POLY
: pObj
=new SdrPathObj(rSdrModel
, OBJ_POLY
); break;
3171 case OBJ_PLIN
: pObj
=new SdrPathObj(rSdrModel
, OBJ_PLIN
); break;
3172 case OBJ_PATHLINE
: pObj
=new SdrPathObj(rSdrModel
, OBJ_PATHLINE
); break;
3173 case OBJ_PATHFILL
: pObj
=new SdrPathObj(rSdrModel
, OBJ_PATHFILL
); break;
3174 case OBJ_FREELINE
: pObj
=new SdrPathObj(rSdrModel
, OBJ_FREELINE
); break;
3175 case OBJ_FREEFILL
: pObj
=new SdrPathObj(rSdrModel
, OBJ_FREEFILL
); break;
3176 case OBJ_PATHPOLY
: pObj
=new SdrPathObj(rSdrModel
, OBJ_POLY
); break;
3177 case OBJ_PATHPLIN
: pObj
=new SdrPathObj(rSdrModel
, OBJ_PLIN
); break;
3178 case OBJ_EDGE
: pObj
=new SdrEdgeObj(rSdrModel
); break;
3179 case OBJ_RECT
: pObj
=new SdrRectObj(rSdrModel
); break;
3180 case OBJ_GRAF
: pObj
=new SdrGrafObj(rSdrModel
); break;
3181 case OBJ_OLE2
: pObj
=new SdrOle2Obj(rSdrModel
); break;
3182 case OBJ_FRAME
: pObj
=new SdrOle2Obj(rSdrModel
, true); break;
3183 case OBJ_CAPTION
: pObj
=new SdrCaptionObj(rSdrModel
); break;
3184 case OBJ_PAGE
: pObj
=new SdrPageObj(rSdrModel
); break;
3185 case OBJ_UNO
: pObj
=new SdrUnoObj(rSdrModel
, OUString()); break;
3186 case OBJ_CUSTOMSHAPE
: pObj
=new SdrObjCustomShape(rSdrModel
); break;
3187 #if HAVE_FEATURE_AVMEDIA
3188 case OBJ_MEDIA
: pObj
=new SdrMediaObj(rSdrModel
); break;
3190 case OBJ_TABLE
: pObj
=new sdr::table::SdrTableObj(rSdrModel
); break;
3197 pObj
= CreateObjectFromFactory(rSdrModel
, nInventor
, nIdentifier
);
3202 // Well, if no one wants it...
3206 if(bSetSnapRect
&& nullptr != pSnapRect
)
3208 pObj
->SetSnapRect(*pSnapRect
);
3214 void SdrObjFactory::InsertMakeObjectHdl(Link
<SdrObjCreatorParams
, SdrObject
*> const & rLink
)
3216 std::vector
<Link
<SdrObjCreatorParams
, SdrObject
*>>& rLL
=ImpGetUserMakeObjHdl();
3217 auto it
= std::find(rLL
.begin(), rLL
.end(), rLink
);
3218 if (it
!= rLL
.end()) {
3219 OSL_FAIL("SdrObjFactory::InsertMakeObjectHdl(): Link already in place.");
3221 rLL
.push_back(rLink
);
3225 void SdrObjFactory::RemoveMakeObjectHdl(Link
<SdrObjCreatorParams
, SdrObject
*> const & rLink
)
3227 std::vector
<Link
<SdrObjCreatorParams
, SdrObject
*>>& rLL
=ImpGetUserMakeObjHdl();
3228 auto it
= std::find(rLL
.begin(), rLL
.end(), rLink
);
3229 if (it
!= rLL
.end())
3235 ISdrObjectFilter::~ISdrObjectFilter()
3240 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */