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>
26 #include <com/sun/star/lang/XComponent.hpp>
27 #include <com/sun/star/text/RelOrientation.hpp>
28 #include <com/sun/star/frame/XTerminateListener.hpp>
29 #include <com/sun/star/frame/Desktop.hpp>
31 #include <basegfx/matrix/b2dhommatrix.hxx>
32 #include <basegfx/matrix/b2dhommatrixtools.hxx>
33 #include <basegfx/polygon/b2dpolygon.hxx>
34 #include <basegfx/polygon/b2dpolygontools.hxx>
35 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
36 #include <basegfx/polygon/b2dpolypolygontools.hxx>
37 #include <basegfx/range/b2drange.hxx>
38 #include <drawinglayer/processor2d/contourextractor2d.hxx>
39 #include <drawinglayer/processor2d/linegeometryextractor2d.hxx>
40 #include <comphelper/processfactory.hxx>
41 #include <editeng/editeng.hxx>
42 #include <editeng/outlobj.hxx>
43 #include <o3tl/deleter.hxx>
45 #include <svl/grabbagitem.hxx>
46 #include <tools/bigint.hxx>
47 #include <comphelper/diagnose_ex.hxx>
48 #include <tools/helpers.hxx>
49 #include <unotools/configmgr.hxx>
50 #include <vcl/canvastools.hxx>
51 #include <vcl/ptrstyle.hxx>
54 #include <svx/svdotable.hxx>
56 #include <svx/sdr/contact/displayinfo.hxx>
57 #include <sdr/contact/objectcontactofobjlistpainter.hxx>
58 #include <svx/sdr/contact/viewcontactofsdrobj.hxx>
59 #include <sdr/properties/emptyproperties.hxx>
60 #include <svx/sdrhittesthelper.hxx>
61 #include <svx/sdrobjectuser.hxx>
62 #include <svx/sdrobjectfilter.hxx>
63 #include <svx/svddrag.hxx>
64 #include <svx/svdetc.hxx>
65 #include <svx/svdhdl.hxx>
66 #include <svx/svditer.hxx>
67 #include <svx/svdmodel.hxx>
68 #include <svx/svdoashp.hxx>
69 #include <svx/svdocapt.hxx>
70 #include <svx/svdocirc.hxx>
71 #include <svx/svdoedge.hxx>
72 #include <svx/svdograf.hxx>
73 #include <svx/svdogrp.hxx>
74 #include <svx/svdomeas.hxx>
75 #include <svx/svdomedia.hxx>
76 #include <svx/svdoole2.hxx>
77 #include <svx/svdopage.hxx>
78 #include <svx/svdopath.hxx>
79 #include <svx/svdorect.hxx>
80 #include <svx/svdotext.hxx>
81 #include <svx/svdouno.hxx>
82 #include <svx/svdovirt.hxx>
83 #include <svx/svdpage.hxx>
84 #include <svx/svdpool.hxx>
85 #include <svx/strings.hrc>
86 #include <svx/dialmgr.hxx>
87 #include <svx/svdtrans.hxx>
88 #include <svx/svdundo.hxx>
89 #include <svx/svdview.hxx>
90 #include <sxlayitm.hxx>
91 #include <sxlogitm.hxx>
92 #include <sxmovitm.hxx>
93 #include <sxoneitm.hxx>
94 #include <sxopitm.hxx>
95 #include <sxreoitm.hxx>
96 #include <sxrooitm.hxx>
97 #include <sxsaitm.hxx>
98 #include <sxsoitm.hxx>
99 #include <sxtraitm.hxx>
100 #include <svx/unopage.hxx>
101 #include <svx/unoshape.hxx>
102 #include <svx/xfillit0.hxx>
103 #include <svx/xflclit.hxx>
104 #include <svx/xfltrit.hxx>
105 #include <svx/xlineit0.hxx>
106 #include <svx/xlnclit.hxx>
107 #include <svx/xlnedwit.hxx>
108 #include <svx/xlnstwit.hxx>
109 #include <svx/xlntrit.hxx>
110 #include <svx/xlnwtit.hxx>
111 #include <svx/svdglue.hxx>
112 #include <svx/svdsob.hxx>
113 #include <svdobjplusdata.hxx>
114 #include <svdobjuserdatalist.hxx>
116 #include <unordered_set>
119 #include <libxml/xmlwriter.h>
122 #include <svx/scene3d.hxx>
123 #include <rtl/character.hxx>
124 #include <tools/UnitConversion.hxx>
125 #include <o3tl/string_view.hxx>
127 using namespace ::com::sun::star
;
130 SdrObjUserCall::~SdrObjUserCall()
134 void SdrObjUserCall::Changed(const SdrObject
& /*rObj*/, SdrUserCallType
/*eType*/, const tools::Rectangle
& /*rOldBoundRect*/)
138 void const* SdrObjUserCall::GetPDFAnchorStructureElementKey(SdrObject
const&)
143 SdrObjMacroHitRec::SdrObjMacroHitRec() :
149 SdrObjUserData::SdrObjUserData(SdrInventor nInv
, sal_uInt16 nId
) :
151 m_nIdentifier(nId
) {}
153 SdrObjUserData::SdrObjUserData(const SdrObjUserData
& rData
) :
154 m_nInventor(rData
.m_nInventor
),
155 m_nIdentifier(rData
.m_nIdentifier
) {}
157 SdrObjUserData::~SdrObjUserData() {}
159 SdrObjGeoData::SdrObjGeoData():
169 SdrObjGeoData::~SdrObjGeoData()
173 SdrObjTransformInfoRec::SdrObjTransformInfoRec() :
175 bResizeFreeAllowed(true),
176 bResizePropAllowed(true),
177 bRotateFreeAllowed(true),
178 bRotate90Allowed(true),
179 bMirrorFreeAllowed(true),
180 bMirror45Allowed(true),
181 bMirror90Allowed(true),
182 bTransparenceAllowed(true),
184 bEdgeRadiusAllowed(true),
185 bNoOrthoDesired(true),
187 bCanConvToPath(true),
188 bCanConvToPoly(true),
189 bCanConvToContour(false),
190 bCanConvToPathLineToArea(true),
191 bCanConvToPolyLineToArea(true) {}
193 struct SdrObject::Impl
195 sdr::ObjectUserVector maObjectUsers
;
196 std::optional
<double> mnRelativeWidth
;
197 std::optional
<double> mnRelativeHeight
;
198 sal_Int16 meRelativeWidthRelation
;
199 sal_Int16 meRelativeHeightRelation
;
202 meRelativeWidthRelation(text::RelOrientation::PAGE_FRAME
),
203 meRelativeHeightRelation(text::RelOrientation::PAGE_FRAME
) {}
206 const std::shared_ptr
< svx::diagram::IDiagramHelper
>& SdrObject::getDiagramHelper() const
208 static std::shared_ptr
< svx::diagram::IDiagramHelper
> aEmpty
;
212 // BaseProperties section
214 sdr::properties::BaseProperties
& SdrObject::GetProperties() const
218 // CAUTION(!) Do *not* call this during SdrObject construction,
219 // that will lead to wrong type-casts (dependent on constructor-level)
220 // and thus eventually create the wrong sdr::properties (!). Is there
221 // a way to check if on the stack is a SdrObject-constructor (?)
222 const_cast< SdrObject
* >(this)->mpProperties
=
223 const_cast< SdrObject
* >(this)->CreateObjectSpecificProperties();
226 return *mpProperties
;
230 // ObjectUser section
232 void SdrObject::AddObjectUser(sdr::ObjectUser
& rNewUser
)
234 mpImpl
->maObjectUsers
.push_back(&rNewUser
);
237 void SdrObject::RemoveObjectUser(sdr::ObjectUser
& rOldUser
)
239 const sdr::ObjectUserVector::iterator aFindResult
=
240 std::find(mpImpl
->maObjectUsers
.begin(), mpImpl
->maObjectUsers
.end(), &rOldUser
);
241 if (aFindResult
!= mpImpl
->maObjectUsers
.end())
243 mpImpl
->maObjectUsers
.erase(aFindResult
);
248 // DrawContact section
250 std::unique_ptr
<sdr::contact::ViewContact
> SdrObject::CreateObjectSpecificViewContact()
252 return std::make_unique
<sdr::contact::ViewContactOfSdrObj
>(*this);
255 sdr::contact::ViewContact
& SdrObject::GetViewContact() const
259 const_cast< SdrObject
* >(this)->mpViewContact
=
260 const_cast< SdrObject
* >(this)->CreateObjectSpecificViewContact();
263 return *mpViewContact
;
266 // DrawContact support: Methods for handling Object changes
267 void SdrObject::ActionChanged() const
269 // Do necessary ViewContact actions
270 GetViewContact().ActionChanged();
273 SdrPage
* SdrObject::getSdrPageFromSdrObject() const
275 if (SdrObjList
* pParentList
= getParentSdrObjListFromSdrObject())
277 return pParentList
->getSdrPageFromSdrObjList();
283 SdrModel
& SdrObject::getSdrModelFromSdrObject() const
285 return mrSdrModelFromSdrObject
;
288 void SdrObject::setParentOfSdrObject(SdrObjList
* pNewObjList
)
290 assert(!pNewObjList
|| mpParentOfSdrObject
!= pNewObjList
);
291 if(mpParentOfSdrObject
== pNewObjList
)
293 // we need to be removed from the old parent before we are attached to the new parent
294 assert(bool(mpParentOfSdrObject
) != bool(pNewObjList
) && "may only transition empty->full or full->empty");
296 // remember current page
297 SdrPage
* pOldPage(getSdrPageFromSdrObject());
300 mpParentOfSdrObject
= pNewObjList
;
303 SdrPage
* pNewPage(getSdrPageFromSdrObject());
305 // broadcast page change over objects if needed
306 if(pOldPage
!= pNewPage
)
308 handlePageChange(pOldPage
, pNewPage
);
312 SdrObjList
* SdrObject::getParentSdrObjListFromSdrObject() const
314 return mpParentOfSdrObject
;
317 SdrObjList
* SdrObject::getChildrenOfSdrObject() const
319 // default has no children
323 void SdrObject::SetBoundRectDirty()
329 // SdrObjectLifetimeWatchDog:
330 void impAddIncarnatedSdrObjectToSdrModel(SdrObject
& rSdrObject
, SdrModel
& rSdrModel
)
332 rSdrModel
.maAllIncarnatedObjects
.insert(&rSdrObject
);
334 void impRemoveIncarnatedSdrObjectToSdrModel(SdrObject
& rSdrObject
, SdrModel
& rSdrModel
)
336 if(!rSdrModel
.maAllIncarnatedObjects
.erase(&rSdrObject
))
338 assert(false && "SdrObject::~SdrObject: Destructed incarnation of SdrObject not member of this SdrModel (!)");
343 SdrObject::SdrObject(SdrModel
& rSdrModel
)
344 : mpFillGeometryDefiningShape(nullptr)
345 ,mrSdrModelFromSdrObject(rSdrModel
)
346 ,m_pUserCall(nullptr)
348 ,mpParentOfSdrObject(nullptr)
350 ,mnNavigationPosition(SAL_MAX_UINT32
)
352 ,mpSvxShape( nullptr )
353 ,mbDoNotInsertIntoPageAutomatically(false)
356 m_bSnapRectDirty
=true;
360 m_bEmptyPresObj
=false;
361 m_bNotVisibleAsMaster
=false;
366 mbLineIsOutsideGeometry
= false;
369 mbSupportTextIndentingOnLineWidthChange
= false;
376 // SdrObjectLifetimeWatchDog:
377 impAddIncarnatedSdrObjectToSdrModel(*this, getSdrModelFromSdrObject());
381 SdrObject::SdrObject(SdrModel
& rSdrModel
, SdrObject
const & rSource
)
382 : mpFillGeometryDefiningShape(nullptr)
383 ,mrSdrModelFromSdrObject(rSdrModel
)
384 ,m_pUserCall(nullptr)
386 ,mpParentOfSdrObject(nullptr)
388 ,mnNavigationPosition(SAL_MAX_UINT32
)
390 ,mpSvxShape( nullptr )
391 ,mbDoNotInsertIntoPageAutomatically(false)
394 m_bSnapRectDirty
=true;
398 m_bEmptyPresObj
=false;
399 m_bNotVisibleAsMaster
=false;
404 mbLineIsOutsideGeometry
= false;
407 mbSupportTextIndentingOnLineWidthChange
= false;
414 mpProperties
.reset();
415 mpViewContact
.reset();
417 // The CloneSdrObject() method uses the local copy constructor from the individual
418 // sdr::properties::BaseProperties class. Since the target class maybe for another
419 // draw object, an SdrObject needs to be provided, as in the normal constructor.
420 mpProperties
= rSource
.GetProperties().Clone(*this);
422 setOutRectangle(rSource
.getOutRectangle());
423 mnLayerID
= rSource
.mnLayerID
;
424 m_aAnchor
=rSource
.m_aAnchor
;
425 m_bVirtObj
=rSource
.m_bVirtObj
;
426 m_bSizProt
=rSource
.m_bSizProt
;
427 m_bMovProt
=rSource
.m_bMovProt
;
428 m_bNoPrint
=rSource
.m_bNoPrint
;
429 mbVisible
=rSource
.mbVisible
;
430 m_bMarkProt
=rSource
.m_bMarkProt
;
431 m_bEmptyPresObj
=rSource
.m_bEmptyPresObj
;
432 m_bNotVisibleAsMaster
=rSource
.m_bNotVisibleAsMaster
;
433 m_bSnapRectDirty
=true;
435 if (rSource
.m_pPlusData
!=nullptr) {
436 m_pPlusData
.reset(rSource
.m_pPlusData
->Clone(this));
438 if (m_pPlusData
!=nullptr && m_pPlusData
->pBroadcast
!=nullptr) {
439 m_pPlusData
->pBroadcast
.reset(); // broadcaster isn't copied
442 m_pGrabBagItem
.reset();
443 if (rSource
.m_pGrabBagItem
!=nullptr)
444 m_pGrabBagItem
.reset(rSource
.m_pGrabBagItem
->Clone());
446 // SdrObjectLifetimeWatchDog:
447 impAddIncarnatedSdrObjectToSdrModel(*this, getSdrModelFromSdrObject());
451 SdrObject::~SdrObject()
454 // see logic in SdrObject::release
455 assert(m_refCount
== -1);
457 // Tell all the registered ObjectUsers that the page is in destruction.
458 // And clear the vector. This means that user do not need to call RemoveObjectUser()
459 // when they get called from ObjectInDestruction().
460 sdr::ObjectUserVector aList
;
461 aList
.swap(mpImpl
->maObjectUsers
);
462 for(sdr::ObjectUser
* pObjectUser
: aList
)
464 DBG_ASSERT(pObjectUser
, "SdrObject::~SdrObject: corrupt ObjectUser list (!)");
465 pObjectUser
->ObjectInDestruction(*this);
469 SendUserCall(SdrUserCallType::Delete
, GetLastBoundRect());
470 o3tl::reset_preserve_ptr_during(m_pPlusData
);
472 m_pGrabBagItem
.reset();
473 mpProperties
.reset();
474 mpViewContact
.reset();
476 // SdrObjectLifetimeWatchDog:
477 impRemoveIncarnatedSdrObjectToSdrModel(*this, getSdrModelFromSdrObject());
481 void SdrObject::acquire() noexcept
484 assert(m_refCount
!= -1);
486 osl_atomic_increment( &m_refCount
);
489 void SdrObject::release() noexcept
491 oslInterlockedCount x
= osl_atomic_decrement( &m_refCount
);
494 disposeWeakConnectionPoint();
496 // make sure it doesn't accidentally come back to life, see assert in acquire()
497 osl_atomic_decrement( &m_refCount
);
503 void SdrObject::SetBoundAndSnapRectsDirty(bool bNotMyself
, bool bRecursive
)
508 m_bSnapRectDirty
=true;
511 if (bRecursive
&& nullptr != getParentSdrObjListFromSdrObject())
513 getParentSdrObjListFromSdrObject()->SetSdrObjListRectsDirty();
517 void SdrObject::handlePageChange(SdrPage
*, SdrPage
* )
522 // global static ItemPool for not-yet-inserted items
523 static rtl::Reference
<SdrItemPool
> mpGlobalItemPool
;
525 /** If we let the libc runtime clean us up, we trigger a crash */
528 class TerminateListener
: public ::cppu::WeakImplHelper
< css::frame::XTerminateListener
>
530 void SAL_CALL
queryTermination( const lang::EventObject
& ) override
532 void SAL_CALL
notifyTermination( const lang::EventObject
& ) override
534 mpGlobalItemPool
.clear();
536 virtual void SAL_CALL
disposing( const ::css::lang::EventObject
& ) override
541 // init global static itempool
542 SdrItemPool
& SdrObject::GetGlobalDrawObjectItemPool()
544 if(!mpGlobalItemPool
)
546 mpGlobalItemPool
= new SdrItemPool();
547 rtl::Reference
<SfxItemPool
> pGlobalOutlPool
= EditEngine::CreatePool();
548 mpGlobalItemPool
->SetSecondaryPool(pGlobalOutlPool
.get());
549 mpGlobalItemPool
->SetDefaultMetric(SdrEngineDefaults::GetMapUnit());
550 mpGlobalItemPool
->FreezeIdRanges();
551 if (utl::ConfigManager::IsFuzzing())
552 mpGlobalItemPool
->acquire();
555 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create(comphelper::getProcessComponentContext());
556 uno::Reference
< frame::XTerminateListener
> xListener( new TerminateListener
);
557 xDesktop
->addTerminateListener( xListener
);
561 return *mpGlobalItemPool
;
564 void SdrObject::SetRelativeWidth( double nValue
)
566 mpImpl
->mnRelativeWidth
= nValue
;
569 void SdrObject::SetRelativeWidthRelation( sal_Int16 eValue
)
571 mpImpl
->meRelativeWidthRelation
= eValue
;
574 void SdrObject::SetRelativeHeight( double nValue
)
576 mpImpl
->mnRelativeHeight
= nValue
;
579 void SdrObject::SetRelativeHeightRelation( sal_Int16 eValue
)
581 mpImpl
->meRelativeHeightRelation
= eValue
;
584 const double* SdrObject::GetRelativeWidth( ) const
586 if (!mpImpl
->mnRelativeWidth
)
589 return &*mpImpl
->mnRelativeWidth
;
592 sal_Int16
SdrObject::GetRelativeWidthRelation() const
594 return mpImpl
->meRelativeWidthRelation
;
597 const double* SdrObject::GetRelativeHeight( ) const
599 if (!mpImpl
->mnRelativeHeight
)
602 return &*mpImpl
->mnRelativeHeight
;
605 sal_Int16
SdrObject::GetRelativeHeightRelation() const
607 return mpImpl
->meRelativeHeightRelation
;
610 SfxItemPool
& SdrObject::GetObjectItemPool() const
612 return getSdrModelFromSdrObject().GetItemPool();
615 SdrInventor
SdrObject::GetObjInventor() const
617 return SdrInventor::Default
;
620 SdrObjKind
SdrObject::GetObjIdentifier() const
622 return SdrObjKind::NONE
;
625 void SdrObject::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
627 rInfo
.bRotateFreeAllowed
=false;
628 rInfo
.bMirrorFreeAllowed
=false;
629 rInfo
.bTransparenceAllowed
= false;
630 rInfo
.bShearAllowed
=false;
631 rInfo
.bEdgeRadiusAllowed
=false;
632 rInfo
.bCanConvToPath
=false;
633 rInfo
.bCanConvToPoly
=false;
634 rInfo
.bCanConvToContour
= false;
635 rInfo
.bCanConvToPathLineToArea
=false;
636 rInfo
.bCanConvToPolyLineToArea
=false;
639 SdrLayerID
SdrObject::GetLayer() const
644 bool SdrObject::isVisibleOnAnyOfTheseLayers(const SdrLayerIDSet
& rSet
) const
646 if (rSet
.IsSet(GetLayer()))
648 SdrObjList
* pOL
=GetSubList();
651 for (const rtl::Reference
<SdrObject
>& pObject
: *pOL
)
652 if (pObject
->isVisibleOnAnyOfTheseLayers(rSet
))
657 void SdrObject::NbcSetLayer(SdrLayerID nLayer
)
662 void SdrObject::SetLayer(SdrLayerID nLayer
)
666 BroadcastObjectChange();
669 void SdrObject::AddListener(SfxListener
& rListener
)
672 if (m_pPlusData
->pBroadcast
==nullptr) m_pPlusData
->pBroadcast
.reset(new SfxBroadcaster
);
674 // SdrEdgeObj may be connected to same SdrObject on both ends so allow it
676 SdrEdgeObj
const*const pEdge(dynamic_cast<SdrEdgeObj
const*>(&rListener
));
677 rListener
.StartListening(*m_pPlusData
->pBroadcast
, pEdge
? DuplicateHandling::Allow
: DuplicateHandling::Unexpected
);
680 void SdrObject::RemoveListener(SfxListener
& rListener
)
682 if (m_pPlusData
!=nullptr && m_pPlusData
->pBroadcast
!=nullptr) {
683 rListener
.EndListening(*m_pPlusData
->pBroadcast
);
684 if (!m_pPlusData
->pBroadcast
->HasListeners()) {
685 m_pPlusData
->pBroadcast
.reset();
690 const SfxBroadcaster
* SdrObject::GetBroadcaster() const
692 return m_pPlusData
!=nullptr ? m_pPlusData
->pBroadcast
.get() : nullptr;
695 void SdrObject::AddReference(SdrVirtObj
& rVrtObj
)
697 AddListener(rVrtObj
);
700 void SdrObject::DelReference(SdrVirtObj
& rVrtObj
)
702 RemoveListener(rVrtObj
);
705 bool SdrObject::IsGroupObject() const
707 return GetSubList()!=nullptr;
710 SdrObjList
* SdrObject::GetSubList() const
715 SdrObject
* SdrObject::getParentSdrObjectFromSdrObject() const
717 SdrObjList
* pParent(getParentSdrObjListFromSdrObject());
719 if(nullptr == pParent
)
724 return pParent
->getSdrObjectFromSdrObjList();
727 void SdrObject::SetName(const OUString
& rStr
, const bool bSetChanged
)
729 if (!rStr
.isEmpty() && !m_pPlusData
)
734 if(!(m_pPlusData
&& m_pPlusData
->aObjName
!= rStr
))
737 // Undo/Redo for setting object's name (#i73249#)
739 if ( getSdrModelFromSdrObject().IsUndoEnabled() )
742 std::unique_ptr
<SdrUndoAction
> pUndoAction
=
743 SdrUndoFactory::CreateUndoObjectStrAttr(
745 SdrUndoObjStrAttr::ObjStrAttrType::Name
,
748 getSdrModelFromSdrObject().BegUndo( pUndoAction
->GetComment() );
749 getSdrModelFromSdrObject().AddUndo( std::move(pUndoAction
) );
751 m_pPlusData
->aObjName
= rStr
;
752 // Undo/Redo for setting object's name (#i73249#)
755 getSdrModelFromSdrObject().EndUndo();
760 BroadcastObjectChange();
764 const OUString
& SdrObject::GetName() const
766 static const OUString EMPTY
= u
""_ustr
;
770 return m_pPlusData
->aObjName
;
776 void SdrObject::SetTitle(const OUString
& rStr
)
778 if (!rStr
.isEmpty() && !m_pPlusData
)
783 if(!(m_pPlusData
&& m_pPlusData
->aObjTitle
!= rStr
))
786 // Undo/Redo for setting object's title (#i73249#)
788 if ( getSdrModelFromSdrObject().IsUndoEnabled() )
791 std::unique_ptr
<SdrUndoAction
> pUndoAction
=
792 SdrUndoFactory::CreateUndoObjectStrAttr(
794 SdrUndoObjStrAttr::ObjStrAttrType::Title
,
797 getSdrModelFromSdrObject().BegUndo( pUndoAction
->GetComment() );
798 getSdrModelFromSdrObject().AddUndo( std::move(pUndoAction
) );
800 m_pPlusData
->aObjTitle
= rStr
;
801 // Undo/Redo for setting object's title (#i73249#)
804 getSdrModelFromSdrObject().EndUndo();
807 BroadcastObjectChange();
810 OUString
SdrObject::GetTitle() const
814 return m_pPlusData
->aObjTitle
;
820 void SdrObject::SetDescription(const OUString
& rStr
)
822 if (!rStr
.isEmpty() && !m_pPlusData
)
827 if(!(m_pPlusData
&& m_pPlusData
->aObjDescription
!= rStr
))
830 // Undo/Redo for setting object's description (#i73249#)
832 if ( getSdrModelFromSdrObject().IsUndoEnabled() )
835 std::unique_ptr
<SdrUndoAction
> pUndoAction
=
836 SdrUndoFactory::CreateUndoObjectStrAttr(
838 SdrUndoObjStrAttr::ObjStrAttrType::Description
,
841 getSdrModelFromSdrObject().BegUndo( pUndoAction
->GetComment() );
842 getSdrModelFromSdrObject().AddUndo( std::move(pUndoAction
) );
844 m_pPlusData
->aObjDescription
= rStr
;
845 // Undo/Redo for setting object's description (#i73249#)
848 getSdrModelFromSdrObject().EndUndo();
851 BroadcastObjectChange();
854 OUString
SdrObject::GetDescription() const
858 return m_pPlusData
->aObjDescription
;
864 void SdrObject::SetDecorative(bool const isDecorative
)
868 if (m_pPlusData
->isDecorative
== isDecorative
)
873 if (getSdrModelFromSdrObject().IsUndoEnabled())
875 std::unique_ptr
<SdrUndoAction
> pUndoAction(
876 SdrUndoFactory::CreateUndoObjectDecorative(
877 *this, m_pPlusData
->isDecorative
));
878 getSdrModelFromSdrObject().BegUndo(pUndoAction
->GetComment());
879 getSdrModelFromSdrObject().AddUndo(std::move(pUndoAction
));
882 m_pPlusData
->isDecorative
= isDecorative
;
884 if (getSdrModelFromSdrObject().IsUndoEnabled())
886 getSdrModelFromSdrObject().EndUndo();
890 BroadcastObjectChange();
893 bool SdrObject::IsDecorative() const
895 return m_pPlusData
== nullptr ? false : m_pPlusData
->isDecorative
;
898 sal_uInt32
SdrObject::GetOrdNum() const
900 if (SdrObjList
* pParentList
= getParentSdrObjListFromSdrObject())
902 if (pParentList
->IsObjOrdNumsDirty())
904 pParentList
->RecalcObjOrdNums();
906 } else const_cast<SdrObject
*>(this)->m_nOrdNum
=0;
910 void SdrObject::SetOrdNum(sal_uInt32 nNum
)
915 void SdrObject::GetGrabBagItem(css::uno::Any
& rVal
) const
917 if (m_pGrabBagItem
!= nullptr)
918 m_pGrabBagItem
->QueryValue(rVal
);
920 rVal
<<= uno::Sequence
<beans::PropertyValue
>();
923 void SdrObject::SetGrabBagItem(const css::uno::Any
& rVal
)
925 if (m_pGrabBagItem
== nullptr)
926 m_pGrabBagItem
.reset(new SfxGrabBagItem
);
928 m_pGrabBagItem
->PutValue(rVal
, 0);
931 BroadcastObjectChange();
934 sal_uInt32
SdrObject::GetNavigationPosition() const
936 if (nullptr != getParentSdrObjListFromSdrObject() && getParentSdrObjListFromSdrObject()->RecalcNavigationPositions())
938 return mnNavigationPosition
;
945 void SdrObject::SetNavigationPosition (const sal_uInt32 nNewPosition
)
947 mnNavigationPosition
= nNewPosition
;
951 // To make clearer that this method may trigger RecalcBoundRect and thus may be
952 // expensive and sometimes problematic (inside a bigger object change you will get
953 // non-useful BoundRects sometimes) I rename that method from GetBoundRect() to
954 // GetCurrentBoundRect().
955 const tools::Rectangle
& SdrObject::GetCurrentBoundRect() const
957 auto const& rRectangle
= getOutRectangle();
958 if (rRectangle
.IsEmpty())
960 const_cast< SdrObject
* >(this)->RecalcBoundRect();
966 // To have a possibility to get the last calculated BoundRect e.g for producing
967 // the first rectangle for repaints (old and new need to be used) without forcing
968 // a RecalcBoundRect (which may be problematical and expensive sometimes) I add here
969 // a new method for accessing the last BoundRect.
970 const tools::Rectangle
& SdrObject::GetLastBoundRect() const
972 return getOutRectangle();
975 void SdrObject::RecalcBoundRect()
977 // #i101680# suppress BoundRect calculations on import(s)
978 if ((getSdrModelFromSdrObject().isLocked()) || utl::ConfigManager::IsFuzzing())
981 auto const& rRectangle
= getOutRectangle();
983 // central new method which will calculate the BoundRect using primitive geometry
984 if (!rRectangle
.IsEmpty())
987 // Use view-independent data - we do not want any connections
988 // to e.g. GridOffset in SdrObject-level
989 drawinglayer::primitive2d::Primitive2DContainer xPrimitives
;
990 GetViewContact().getViewIndependentPrimitive2DContainer(xPrimitives
);
992 if (xPrimitives
.empty())
995 // use neutral ViewInformation and get the range of the primitives
996 const drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
997 const basegfx::B2DRange
aRange(xPrimitives
.getB2DRange(aViewInformation2D
));
999 if (!aRange
.isEmpty())
1001 tools::Rectangle
aNewRectangle(
1002 tools::Long(floor(aRange
.getMinX())),
1003 tools::Long(floor(aRange
.getMinY())),
1004 tools::Long(ceil(aRange
.getMaxX())),
1005 tools::Long(ceil(aRange
.getMaxY())));
1006 setOutRectangle(aNewRectangle
);
1011 void SdrObject::BroadcastObjectChange() const
1013 if ((getSdrModelFromSdrObject().isLocked()) || utl::ConfigManager::IsFuzzing())
1016 bool bPlusDataBroadcast(m_pPlusData
&& m_pPlusData
->pBroadcast
);
1017 bool bObjectChange(IsInserted());
1019 if(!(bPlusDataBroadcast
|| bObjectChange
))
1022 SdrHint
aHint(SdrHintKind::ObjectChange
, *this);
1024 if(bPlusDataBroadcast
)
1026 m_pPlusData
->pBroadcast
->Broadcast(aHint
);
1031 getSdrModelFromSdrObject().Broadcast(aHint
);
1035 void SdrObject::SetChanged()
1037 // For testing purposes, use the new ViewContact for change
1038 // notification now.
1041 // TTTT Need to check meaning/usage of IsInserted in one
1042 // of the next changes. It should not mean to have a SdrModel
1043 // set (this is guaranteed now), but should be connected to
1044 // being added to a SdrPage (?)
1045 // TTTT tdf#120066 Indeed - This triggers e.g. by CustomShape
1046 // geometry-presenting SdrObjects that are in a SdrObjGroup,
1047 // but the SdrObjGroup is *by purpose* not inserted.
1048 // Need to check deeper and maybe identify all ::IsInserted()
1049 // calls by rename and let the compiler work...
1050 if(nullptr != getSdrPageFromSdrObject())
1052 getSdrModelFromSdrObject().SetChanged();
1056 // tooling for painting a single object to an OutputDevice.
1057 void SdrObject::SingleObjectPainter(OutputDevice
& rOut
) const
1059 sdr::contact::SdrObjectVector aObjectVector
;
1060 aObjectVector
.push_back(const_cast< SdrObject
* >(this));
1062 sdr::contact::ObjectContactOfObjListPainter
aPainter(rOut
, std::move(aObjectVector
), getSdrPageFromSdrObject());
1063 sdr::contact::DisplayInfo aDisplayInfo
;
1065 aPainter
.ProcessDisplay(aDisplayInfo
);
1068 bool SdrObject::LineGeometryUsageIsNecessary() const
1070 drawing::LineStyle eXLS
= GetMergedItem(XATTR_LINESTYLE
).GetValue();
1071 return (eXLS
!= drawing::LineStyle_NONE
);
1074 bool SdrObject::HasLimitedRotation() const
1076 // RotGrfFlyFrame: Default is false, support full rotation
1080 OUString
SdrObject::TakeObjNameSingul() const
1082 OUString
sName(SvxResId(STR_ObjNameSingulNONE
));
1084 OUString
aName(GetName());
1085 if (!aName
.isEmpty())
1086 sName
+= " '" + aName
+ "'";
1090 OUString
SdrObject::TakeObjNamePlural() const
1092 return SvxResId(STR_ObjNamePluralNONE
);
1095 OUString
SdrObject::ImpGetDescriptionStr(TranslateId pStrCacheID
) const
1097 OUString aStr
= SvxResId(pStrCacheID
);
1098 sal_Int32 nPos
= aStr
.indexOf("%1");
1101 // Replace '%1' with the object name.
1102 OUString
aObjName(TakeObjNameSingul());
1103 aStr
= aStr
.replaceAt(nPos
, 2, aObjName
);
1106 nPos
= aStr
.indexOf("%2");
1108 // Replace '%2' with the passed value.
1109 aStr
= aStr
.replaceAt(nPos
, 2, u
"0");
1113 void SdrObject::ImpForcePlusData()
1116 m_pPlusData
.reset( new SdrObjPlusData
);
1119 OUString
SdrObject::GetMetrStr(tools::Long nVal
) const
1121 return getSdrModelFromSdrObject().GetMetricString(nVal
);
1124 basegfx::B2DPolyPolygon
SdrObject::TakeXorPoly() const
1126 basegfx::B2DPolyPolygon aRetval
;
1127 const tools::Rectangle
aR(GetCurrentBoundRect());
1128 aRetval
.append(basegfx::utils::createPolygonFromRect(vcl::unotools::b2DRectangleFromRectangle(aR
)));
1133 basegfx::B2DPolyPolygon
SdrObject::TakeContour() const
1135 basegfx::B2DPolyPolygon aRetval
;
1137 // create cloned object without text, but with drawing::LineStyle_SOLID,
1138 // COL_BLACK as line color and drawing::FillStyle_NONE
1139 rtl::Reference
<SdrObject
> pClone(CloneSdrObject(getSdrModelFromSdrObject()));
1143 const SdrTextObj
* pTextObj
= DynCastSdrTextObj(this);
1147 // no text and no text animation
1148 pClone
->SetMergedItem(SdrTextAniKindItem(SdrTextAniKind::NONE
));
1149 pClone
->SetOutlinerParaObject(std::nullopt
);
1152 const SdrEdgeObj
* pEdgeObj
= dynamic_cast< const SdrEdgeObj
* >(this);
1156 // create connections if connector, will be cleaned up when
1157 // deleting the connector again
1158 SdrObject
* pLeft
= pEdgeObj
->GetConnectedNode(true);
1159 SdrObject
* pRight
= pEdgeObj
->GetConnectedNode(false);
1163 pClone
->ConnectToNode(true, pLeft
);
1168 pClone
->ConnectToNode(false, pRight
);
1172 SfxItemSet
aNewSet(GetObjectItemPool());
1174 // #i101980# ignore LineWidth; that's what the old implementation
1175 // did. With line width, the result may be huge due to fat/thick
1176 // line decompositions
1177 aNewSet
.Put(XLineWidthItem(0));
1179 // solid black lines and no fill
1180 aNewSet
.Put(XLineStyleItem(drawing::LineStyle_SOLID
));
1181 aNewSet
.Put(XLineColorItem(OUString(), COL_BLACK
));
1182 aNewSet
.Put(XFillStyleItem(drawing::FillStyle_NONE
));
1183 pClone
->SetMergedItemSet(aNewSet
);
1185 // get sequence from clone
1186 const sdr::contact::ViewContact
& rVC(pClone
->GetViewContact());
1187 drawinglayer::primitive2d::Primitive2DContainer xSequence
;
1188 rVC
.getViewIndependentPrimitive2DContainer(xSequence
);
1190 if(!xSequence
.empty())
1192 // use neutral ViewInformation
1193 const drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
1195 // create extractor, process and get result (with hairlines as opened polygons)
1196 drawinglayer::processor2d::ContourExtractor2D
aExtractor(aViewInformation2D
, false);
1197 aExtractor
.process(xSequence
);
1198 const basegfx::B2DPolyPolygonVector
& rResult(aExtractor
.getExtractedContour());
1199 const sal_uInt32
nSize(rResult
.size());
1201 // when count is one, it is implied that the object has only its normal
1202 // contour anyways and TakeContour() is to return an empty PolyPolygon
1203 // (see old implementation for historical reasons)
1206 // the topology for contour is correctly a vector of PolyPolygons; for
1207 // historical reasons cut it back to a single tools::PolyPolygon here
1208 for(sal_uInt32
a(0); a
< nSize
; a
++)
1210 aRetval
.append(rResult
[a
]);
1219 sal_uInt32
SdrObject::GetHdlCount() const
1224 void SdrObject::AddToHdlList(SdrHdlList
& rHdlList
) const
1226 const tools::Rectangle
& rR
=GetSnapRect();
1227 for (sal_uInt32 nHdlNum
=0; nHdlNum
<8; ++nHdlNum
)
1229 std::unique_ptr
<SdrHdl
> pH
;
1231 case 0: pH
.reset(new SdrHdl(rR
.TopLeft(), SdrHdlKind::UpperLeft
)); break;
1232 case 1: pH
.reset(new SdrHdl(rR
.TopCenter(), SdrHdlKind::Upper
)); break;
1233 case 2: pH
.reset(new SdrHdl(rR
.TopRight(), SdrHdlKind::UpperRight
)); break;
1234 case 3: pH
.reset(new SdrHdl(rR
.LeftCenter(), SdrHdlKind::Left
)); break;
1235 case 4: pH
.reset(new SdrHdl(rR
.RightCenter(), SdrHdlKind::Right
)); break;
1236 case 5: pH
.reset(new SdrHdl(rR
.BottomLeft(), SdrHdlKind::LowerLeft
)); break;
1237 case 6: pH
.reset(new SdrHdl(rR
.BottomCenter(),SdrHdlKind::Lower
)); break;
1238 case 7: pH
.reset(new SdrHdl(rR
.BottomRight(), SdrHdlKind::LowerRight
)); break;
1240 rHdlList
.AddHdl(std::move(pH
));
1244 void SdrObject::AddToPlusHdlList(SdrHdlList
&, SdrHdl
&) const
1248 void SdrObject::addCropHandles(SdrHdlList
& /*rTarget*/) const
1250 // Default implementation, does nothing. Overloaded in
1251 // SdrGrafObj and SwVirtFlyDrawObj
1254 tools::Rectangle
SdrObject::ImpDragCalcRect(const SdrDragStat
& rDrag
) const
1256 tools::Rectangle
aTmpRect(GetSnapRect());
1257 tools::Rectangle
aRect(aTmpRect
);
1258 const SdrHdl
* pHdl
=rDrag
.GetHdl();
1259 SdrHdlKind eHdl
=pHdl
==nullptr ? SdrHdlKind::Move
: pHdl
->GetKind();
1260 bool bEcke
=(eHdl
==SdrHdlKind::UpperLeft
|| eHdl
==SdrHdlKind::UpperRight
|| eHdl
==SdrHdlKind::LowerLeft
|| eHdl
==SdrHdlKind::LowerRight
);
1261 bool bOrtho
=rDrag
.GetView()!=nullptr && rDrag
.GetView()->IsOrtho();
1262 bool bBigOrtho
=bEcke
&& bOrtho
&& rDrag
.GetView()->IsBigOrtho();
1263 Point
aPos(rDrag
.GetNow());
1264 bool bLft
=(eHdl
==SdrHdlKind::UpperLeft
|| eHdl
==SdrHdlKind::Left
|| eHdl
==SdrHdlKind::LowerLeft
);
1265 bool bRgt
=(eHdl
==SdrHdlKind::UpperRight
|| eHdl
==SdrHdlKind::Right
|| eHdl
==SdrHdlKind::LowerRight
);
1266 bool bTop
=(eHdl
==SdrHdlKind::UpperRight
|| eHdl
==SdrHdlKind::Upper
|| eHdl
==SdrHdlKind::UpperLeft
);
1267 bool bBtm
=(eHdl
==SdrHdlKind::LowerRight
|| eHdl
==SdrHdlKind::Lower
|| eHdl
==SdrHdlKind::LowerLeft
);
1268 if (bLft
) aTmpRect
.SetLeft(aPos
.X() );
1269 if (bRgt
) aTmpRect
.SetRight(aPos
.X() );
1270 if (bTop
) aTmpRect
.SetTop(aPos
.Y() );
1271 if (bBtm
) aTmpRect
.SetBottom(aPos
.Y() );
1272 if (bOrtho
) { // Ortho
1273 tools::Long nWdt0
=aRect
.Right() -aRect
.Left();
1274 tools::Long nHgt0
=aRect
.Bottom()-aRect
.Top();
1275 tools::Long nXMul
=aTmpRect
.Right() -aTmpRect
.Left();
1276 tools::Long nYMul
=aTmpRect
.Bottom()-aTmpRect
.Top();
1277 tools::Long nXDiv
=nWdt0
;
1278 tools::Long nYDiv
=nHgt0
;
1279 bool bXNeg
=(nXMul
<0)!=(nXDiv
<0);
1280 bool bYNeg
=(nYMul
<0)!=(nYDiv
<0);
1281 nXMul
=std::abs(nXMul
);
1282 nYMul
=std::abs(nYMul
);
1283 nXDiv
=std::abs(nXDiv
);
1284 nYDiv
=std::abs(nYDiv
);
1285 Fraction
aXFact(nXMul
,nXDiv
); // fractions for canceling
1286 Fraction
aYFact(nYMul
,nYDiv
); // and for comparing
1287 nXMul
=aXFact
.GetNumerator();
1288 nYMul
=aYFact
.GetNumerator();
1289 nXDiv
=aXFact
.GetDenominator();
1290 nYDiv
=aYFact
.GetDenominator();
1291 if (bEcke
) { // corner point handles
1292 bool bUseX
=(aXFact
<aYFact
) != bBigOrtho
;
1294 tools::Long nNeed
=tools::Long(BigInt(nHgt0
)*BigInt(nXMul
)/BigInt(nXDiv
));
1295 if (bYNeg
) nNeed
=-nNeed
;
1296 if (bTop
) aTmpRect
.SetTop(aTmpRect
.Bottom()-nNeed
);
1297 if (bBtm
) aTmpRect
.SetBottom(aTmpRect
.Top()+nNeed
);
1299 tools::Long nNeed
=tools::Long(BigInt(nWdt0
)*BigInt(nYMul
)/BigInt(nYDiv
));
1300 if (bXNeg
) nNeed
=-nNeed
;
1301 if (bLft
) aTmpRect
.SetLeft(aTmpRect
.Right()-nNeed
);
1302 if (bRgt
) aTmpRect
.SetRight(aTmpRect
.Left()+nNeed
);
1304 } else { // apex handles
1305 if ((bLft
|| bRgt
) && nXDiv
!=0) {
1306 tools::Long nHgt0b
=aRect
.Bottom()-aRect
.Top();
1307 tools::Long nNeed
=tools::Long(BigInt(nHgt0b
)*BigInt(nXMul
)/BigInt(nXDiv
));
1308 aTmpRect
.AdjustTop( -((nNeed
-nHgt0b
)/2) );
1309 aTmpRect
.SetBottom(aTmpRect
.Top()+nNeed
);
1311 if ((bTop
|| bBtm
) && nYDiv
!=0) {
1312 tools::Long nWdt0b
=aRect
.Right()-aRect
.Left();
1313 tools::Long nNeed
=tools::Long(BigInt(nWdt0b
)*BigInt(nYMul
)/BigInt(nYDiv
));
1314 aTmpRect
.AdjustLeft( -((nNeed
-nWdt0b
)/2) );
1315 aTmpRect
.SetRight(aTmpRect
.Left()+nNeed
);
1319 aTmpRect
.Normalize();
1324 bool SdrObject::hasSpecialDrag() const
1329 bool SdrObject::supportsFullDrag() const
1334 rtl::Reference
<SdrObject
> SdrObject::getFullDragClone() const
1336 // default uses simple clone
1337 return CloneSdrObject(getSdrModelFromSdrObject());
1340 bool SdrObject::beginSpecialDrag(SdrDragStat
& rDrag
) const
1342 const SdrHdl
* pHdl
= rDrag
.GetHdl();
1344 SdrHdlKind eHdl
= (pHdl
== nullptr) ? SdrHdlKind::Move
: pHdl
->GetKind();
1346 return eHdl
==SdrHdlKind::UpperLeft
|| eHdl
==SdrHdlKind::Upper
|| eHdl
==SdrHdlKind::UpperRight
||
1347 eHdl
==SdrHdlKind::Left
|| eHdl
==SdrHdlKind::Right
|| eHdl
==SdrHdlKind::LowerLeft
||
1348 eHdl
==SdrHdlKind::Lower
|| eHdl
==SdrHdlKind::LowerRight
;
1351 bool SdrObject::applySpecialDrag(SdrDragStat
& rDrag
)
1353 tools::Rectangle
aNewRect(ImpDragCalcRect(rDrag
));
1355 if(aNewRect
!= GetSnapRect())
1357 NbcSetSnapRect(aNewRect
);
1363 OUString
SdrObject::getSpecialDragComment(const SdrDragStat
& /*rDrag*/) const
1368 basegfx::B2DPolyPolygon
SdrObject::getSpecialDragPoly(const SdrDragStat
& /*rDrag*/) const
1370 // default has nothing to add
1371 return basegfx::B2DPolyPolygon();
1376 bool SdrObject::BegCreate(SdrDragStat
& rStat
)
1378 rStat
.SetOrtho4Possible();
1379 tools::Rectangle
aRect1(rStat
.GetStart(), rStat
.GetNow());
1381 rStat
.SetActionRect(aRect1
);
1382 setOutRectangle(aRect1
);
1386 bool SdrObject::MovCreate(SdrDragStat
& rStat
)
1388 tools::Rectangle aRectangle
;
1389 rStat
.TakeCreateRect(aRectangle
);
1390 rStat
.SetActionRect(aRectangle
);
1391 aRectangle
.Normalize();
1392 setOutRectangle(aRectangle
);
1396 bool SdrObject::EndCreate(SdrDragStat
& rStat
, SdrCreateCmd eCmd
)
1398 tools::Rectangle aRectangle
;
1399 rStat
.TakeCreateRect(aRectangle
);
1400 aRectangle
.Normalize();
1401 setOutRectangle(aRectangle
);
1403 return (eCmd
==SdrCreateCmd::ForceEnd
|| rStat
.GetPointCount()>=2);
1406 void SdrObject::BrkCreate(SdrDragStat
& /*rStat*/)
1410 bool SdrObject::BckCreate(SdrDragStat
& /*rStat*/)
1415 basegfx::B2DPolyPolygon
SdrObject::TakeCreatePoly(const SdrDragStat
& rDrag
) const
1417 tools::Rectangle aRect1
;
1418 rDrag
.TakeCreateRect(aRect1
);
1421 basegfx::B2DPolyPolygon aRetval
;
1422 aRetval
.append(basegfx::utils::createPolygonFromRect(vcl::unotools::b2DRectangleFromRectangle(aRect1
)));
1426 PointerStyle
SdrObject::GetCreatePointer() const
1428 return PointerStyle::Cross
;
1432 void SdrObject::NbcMove(const Size
& rSize
)
1434 moveOutRectangle(rSize
.Width(), rSize
.Height());
1435 SetBoundAndSnapRectsDirty();
1438 void SdrObject::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
1440 bool bXMirr
=(xFact
.GetNumerator()<0) != (xFact
.GetDenominator()<0);
1441 bool bYMirr
=(yFact
.GetNumerator()<0) != (yFact
.GetDenominator()<0);
1442 if (bXMirr
|| bYMirr
) {
1443 Point
aRef1(GetSnapRect().Center());
1447 NbcMirrorGluePoints(aRef1
,aRef2
);
1452 NbcMirrorGluePoints(aRef1
,aRef2
);
1455 auto aRectangle
= getOutRectangle();
1456 ResizeRect(aRectangle
, rRef
, xFact
, yFact
);
1457 setOutRectangle(aRectangle
);
1459 SetBoundAndSnapRectsDirty();
1462 void SdrObject::NbcRotate(const Point
& rRef
, Degree100 nAngle
)
1466 double a
= toRadians(nAngle
);
1467 NbcRotate( rRef
, nAngle
, sin( a
), cos( a
) );
1473 tools::Rectangle
lclMirrorRectangle(tools::Rectangle
const& rRectangle
, Point
const& rRef1
, Point
const& rRef2
)
1475 tools::Rectangle
aRectangle(rRectangle
);
1476 aRectangle
.Move(-rRef1
.X(),-rRef1
.Y());
1477 tools::Rectangle
R(aRectangle
);
1478 tools::Long dx
=rRef2
.X()-rRef1
.X();
1479 tools::Long dy
=rRef2
.Y()-rRef1
.Y();
1480 if (dx
==0) { // vertical axis
1481 aRectangle
.SetLeft(-R
.Right() );
1482 aRectangle
.SetRight(-R
.Left() );
1483 } else if (dy
==0) { // horizontal axis
1484 aRectangle
.SetTop(-R
.Bottom() );
1485 aRectangle
.SetBottom(-R
.Top() );
1486 } else if (dx
==dy
) { // 45deg axis
1487 aRectangle
.SetLeft(R
.Top() );
1488 aRectangle
.SetRight(R
.Bottom() );
1489 aRectangle
.SetTop(R
.Left() );
1490 aRectangle
.SetBottom(R
.Right() );
1491 } else if (dx
==-dy
) { // 45deg axis
1492 aRectangle
.SetLeft(-R
.Bottom() );
1493 aRectangle
.SetRight(-R
.Top() );
1494 aRectangle
.SetTop(-R
.Right() );
1495 aRectangle
.SetBottom(-R
.Left() );
1497 aRectangle
.Move(rRef1
.X(),rRef1
.Y());
1498 aRectangle
.Normalize(); // just in case
1502 } // end anonymous namespace
1504 void SdrObject::NbcMirror(const Point
& rRef1
, const Point
& rRef2
)
1506 SetGlueReallyAbsolute(true);
1508 tools::Rectangle aRectangle
= getOutRectangle();
1509 aRectangle
= lclMirrorRectangle(aRectangle
, rRef1
, rRef2
);
1510 setOutRectangle(aRectangle
);
1512 SetBoundAndSnapRectsDirty();
1513 NbcMirrorGluePoints(rRef1
,rRef2
);
1514 SetGlueReallyAbsolute(false);
1517 void SdrObject::NbcShear(const Point
& rRef
, Degree100
/*nAngle*/, double tn
, bool bVShear
)
1519 SetGlueReallyAbsolute(true);
1520 NbcShearGluePoints(rRef
,tn
,bVShear
);
1521 SetGlueReallyAbsolute(false);
1524 void SdrObject::Move(const Size
& rSiz
)
1526 if (rSiz
.Width()!=0 || rSiz
.Height()!=0) {
1527 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1530 BroadcastObjectChange();
1531 SendUserCall(SdrUserCallType::MoveOnly
,aBoundRect0
);
1535 void SdrObject::NbcCrop(const basegfx::B2DPoint
& /*aRef*/, double /*fxFact*/, double /*fyFact*/)
1537 // Default: does nothing. Real behaviour in SwVirtFlyDrawObj and SdrDragCrop::EndSdrDrag.
1538 // Where SwVirtFlyDrawObj is the only real user of it to do something local
1541 void SdrObject::Resize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
, bool bUnsetRelative
)
1543 if (xFact
.GetNumerator() == xFact
.GetDenominator() && yFact
.GetNumerator() == yFact
.GetDenominator())
1548 mpImpl
->mnRelativeWidth
.reset();
1549 mpImpl
->meRelativeWidthRelation
= text::RelOrientation::PAGE_FRAME
;
1550 mpImpl
->meRelativeHeightRelation
= text::RelOrientation::PAGE_FRAME
;
1551 mpImpl
->mnRelativeHeight
.reset();
1553 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1554 NbcResize(rRef
,xFact
,yFact
);
1556 BroadcastObjectChange();
1557 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1560 void SdrObject::Crop(const basegfx::B2DPoint
& rRef
, double fxFact
, double fyFact
)
1562 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1563 NbcCrop(rRef
, fxFact
, fyFact
);
1565 BroadcastObjectChange();
1566 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1569 void SdrObject::Rotate(const Point
& rRef
, Degree100 nAngle
, double sn
, double cs
)
1572 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1573 NbcRotate(rRef
,nAngle
,sn
,cs
);
1575 BroadcastObjectChange();
1576 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1580 void SdrObject::Mirror(const Point
& rRef1
, const Point
& rRef2
)
1582 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1583 NbcMirror(rRef1
,rRef2
);
1585 BroadcastObjectChange();
1586 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1589 void SdrObject::Shear(const Point
& rRef
, Degree100 nAngle
, double tn
, bool bVShear
)
1592 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1593 NbcShear(rRef
,nAngle
,tn
,bVShear
);
1595 BroadcastObjectChange();
1596 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1600 void SdrObject::NbcSetRelativePos(const Point
& rPnt
)
1602 Point
aRelPos0(GetSnapRect().TopLeft()-m_aAnchor
);
1603 Size
aSiz(rPnt
.X()-aRelPos0
.X(),rPnt
.Y()-aRelPos0
.Y());
1604 NbcMove(aSiz
); // This also calls SetRectsDirty()
1607 void SdrObject::SetRelativePos(const Point
& rPnt
)
1609 if (rPnt
!=GetRelativePos()) {
1610 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1611 NbcSetRelativePos(rPnt
);
1613 BroadcastObjectChange();
1614 SendUserCall(SdrUserCallType::MoveOnly
,aBoundRect0
);
1618 Point
SdrObject::GetRelativePos() const
1620 return GetSnapRect().TopLeft()-m_aAnchor
;
1623 void SdrObject::ImpSetAnchorPos(const Point
& rPnt
)
1628 void SdrObject::NbcSetAnchorPos(const Point
& rPnt
)
1630 Size
aSiz(rPnt
.X()-m_aAnchor
.X(),rPnt
.Y()-m_aAnchor
.Y());
1632 NbcMove(aSiz
); // This also calls SetRectsDirty()
1635 void SdrObject::SetAnchorPos(const Point
& rPnt
)
1637 if (rPnt
!=m_aAnchor
) {
1638 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1639 NbcSetAnchorPos(rPnt
);
1641 BroadcastObjectChange();
1642 SendUserCall(SdrUserCallType::MoveOnly
,aBoundRect0
);
1646 const Point
& SdrObject::GetAnchorPos() const
1651 void SdrObject::RecalcSnapRect()
1655 const tools::Rectangle
& SdrObject::GetSnapRect() const
1657 return getOutRectangle();
1660 void SdrObject::NbcSetSnapRect(const tools::Rectangle
& rRect
)
1662 setOutRectangle(rRect
);
1665 const tools::Rectangle
& SdrObject::GetLogicRect() const
1667 return GetSnapRect();
1670 void SdrObject::NbcSetLogicRect(const tools::Rectangle
& rRect
)
1672 NbcSetSnapRect(rRect
);
1675 void SdrObject::AdjustToMaxRect( const tools::Rectangle
& rMaxRect
, bool /* bShrinkOnly = false */ )
1677 SetLogicRect( rMaxRect
);
1680 void SdrObject::SetSnapRect(const tools::Rectangle
& rRect
)
1682 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1683 NbcSetSnapRect(rRect
);
1685 BroadcastObjectChange();
1686 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1689 void SdrObject::SetLogicRect(const tools::Rectangle
& rRect
)
1691 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1692 NbcSetLogicRect(rRect
);
1694 BroadcastObjectChange();
1695 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1698 Degree100
SdrObject::GetRotateAngle() const
1703 Degree100
SdrObject::GetShearAngle(bool /*bVertical*/) const
1708 sal_uInt32
SdrObject::GetSnapPointCount() const
1710 return GetPointCount();
1713 Point
SdrObject::GetSnapPoint(sal_uInt32 i
) const
1718 bool SdrObject::IsPolyObj() const
1723 sal_uInt32
SdrObject::GetPointCount() const
1728 Point
SdrObject::GetPoint(sal_uInt32
/*i*/) const
1733 void SdrObject::SetPoint(const Point
& rPnt
, sal_uInt32 i
)
1735 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1736 NbcSetPoint(rPnt
, i
);
1738 BroadcastObjectChange();
1739 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1742 void SdrObject::NbcSetPoint(const Point
& /*rPnt*/, sal_uInt32
/*i*/)
1746 bool SdrObject::HasTextEdit() const
1751 bool SdrObject::Equals(const SdrObject
& rOtherObj
) const
1753 return (m_aAnchor
.X() == rOtherObj
.m_aAnchor
.X() && m_aAnchor
.Y() == rOtherObj
.m_aAnchor
.Y() &&
1754 m_nOrdNum
== rOtherObj
.m_nOrdNum
&& mnNavigationPosition
== rOtherObj
.mnNavigationPosition
&&
1755 mbSupportTextIndentingOnLineWidthChange
== rOtherObj
.mbSupportTextIndentingOnLineWidthChange
&&
1756 mbLineIsOutsideGeometry
== rOtherObj
.mbLineIsOutsideGeometry
&& m_bMarkProt
== rOtherObj
.m_bMarkProt
&&
1757 m_bIs3DObj
== rOtherObj
.m_bIs3DObj
&& m_bIsEdge
== rOtherObj
.m_bIsEdge
&& m_bClosedObj
== rOtherObj
.m_bClosedObj
&&
1758 m_bNotVisibleAsMaster
== rOtherObj
.m_bNotVisibleAsMaster
&& m_bEmptyPresObj
== rOtherObj
.m_bEmptyPresObj
&&
1759 mbVisible
== rOtherObj
.mbVisible
&& m_bNoPrint
== rOtherObj
.m_bNoPrint
&& m_bSizProt
== rOtherObj
.m_bSizProt
&&
1760 m_bMovProt
== rOtherObj
.m_bMovProt
&& m_bVirtObj
== rOtherObj
.m_bVirtObj
&&
1761 mnLayerID
== rOtherObj
.mnLayerID
&& GetMergedItemSet().Equals(rOtherObj
.GetMergedItemSet(), false) );
1764 void SdrObject::dumpAsXml(xmlTextWriterPtr pWriter
) const
1766 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SdrObject"));
1767 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
1768 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
1769 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("name"), "%s", BAD_CAST(GetName().toUtf8().getStr()));
1770 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("title"), "%s", BAD_CAST(GetTitle().toUtf8().getStr()));
1771 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("description"), "%s", BAD_CAST(GetDescription().toUtf8().getStr()));
1772 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("nOrdNum"), "%" SAL_PRIuUINT32
, GetOrdNumDirect());
1773 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("aOutRect"), BAD_CAST(getOutRectangle().toString().getStr()));
1777 m_pGrabBagItem
->dumpAsXml(pWriter
);
1782 mpProperties
->dumpAsXml(pWriter
);
1785 if (const OutlinerParaObject
* pOutliner
= GetOutlinerParaObject())
1786 pOutliner
->dumpAsXml(pWriter
);
1788 (void)xmlTextWriterEndElement(pWriter
);
1791 void SdrObject::SetOutlinerParaObject(std::optional
<OutlinerParaObject
> pTextObject
)
1793 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1794 NbcSetOutlinerParaObject(std::move(pTextObject
));
1796 BroadcastObjectChange();
1797 if (GetCurrentBoundRect()!=aBoundRect0
) {
1798 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1801 if (!getSdrModelFromSdrObject().IsUndoEnabled())
1804 // Don't do this during import.
1805 SdrObject
* pTopGroupObj
= nullptr;
1806 if (getParentSdrObjectFromSdrObject())
1808 pTopGroupObj
= getParentSdrObjectFromSdrObject();
1809 while (pTopGroupObj
->getParentSdrObjectFromSdrObject())
1811 pTopGroupObj
= pTopGroupObj
->getParentSdrObjectFromSdrObject();
1816 // A shape was modified, which is in a group shape. Empty the group shape's grab-bag,
1817 // which potentially contains the old text of the shapes in case of diagrams.
1818 pTopGroupObj
->SetGrabBagItem(uno::Any(uno::Sequence
<beans::PropertyValue
>()));
1822 void SdrObject::NbcSetOutlinerParaObject(std::optional
<OutlinerParaObject
> /*pTextObject*/)
1826 OutlinerParaObject
* SdrObject::GetOutlinerParaObject() const
1831 void SdrObject::NbcReformatText()
1835 void SdrObject::BurnInStyleSheetAttributes()
1837 GetProperties().ForceStyleToHardAttributes();
1840 bool SdrObject::HasMacro() const
1845 SdrObject
* SdrObject::CheckMacroHit(const SdrObjMacroHitRec
& rRec
) const
1849 return SdrObjectPrimitiveHit(*this, rRec
.aPos
, {static_cast<double>(rRec
.nTol
), static_cast<double>(rRec
.nTol
)}, *rRec
.pPageView
, rRec
.pVisiLayer
, false);
1855 PointerStyle
SdrObject::GetMacroPointer(const SdrObjMacroHitRec
&) const
1857 return PointerStyle::RefHand
;
1860 void SdrObject::PaintMacro(OutputDevice
& rOut
, const tools::Rectangle
& , const SdrObjMacroHitRec
& ) const
1862 const RasterOp
eRop(rOut
.GetRasterOp());
1863 const basegfx::B2DPolyPolygon
aPolyPolygon(TakeXorPoly());
1865 rOut
.SetLineColor(COL_BLACK
);
1866 rOut
.SetFillColor();
1867 rOut
.SetRasterOp(RasterOp::Invert
);
1869 for(auto const& rPolygon
: aPolyPolygon
)
1871 rOut
.DrawPolyLine(rPolygon
);
1874 rOut
.SetRasterOp(eRop
);
1877 bool SdrObject::DoMacro(const SdrObjMacroHitRec
&)
1882 bool SdrObject::IsMacroHit(const SdrObjMacroHitRec
& rRec
) const
1884 return CheckMacroHit(rRec
) != nullptr;
1888 std::unique_ptr
<SdrObjGeoData
> SdrObject::NewGeoData() const
1890 return std::make_unique
<SdrObjGeoData
>();
1893 void SdrObject::SaveGeoData(SdrObjGeoData
& rGeo
) const
1895 rGeo
.aBoundRect
=GetCurrentBoundRect();
1896 rGeo
.aAnchor
=m_aAnchor
;
1897 rGeo
.bMovProt
=m_bMovProt
;
1898 rGeo
.bSizProt
=m_bSizProt
;
1899 rGeo
.bNoPrint
=m_bNoPrint
;
1900 rGeo
.mbVisible
=mbVisible
;
1901 rGeo
.bClosedObj
=m_bClosedObj
;
1902 rGeo
.mnLayerID
= mnLayerID
;
1904 // user-defined gluepoints
1905 if (m_pPlusData
!=nullptr && m_pPlusData
->pGluePoints
!=nullptr) {
1906 if (rGeo
.pGPL
!=nullptr) {
1907 *rGeo
.pGPL
=*m_pPlusData
->pGluePoints
;
1909 rGeo
.pGPL
.reset( new SdrGluePointList(*m_pPlusData
->pGluePoints
) );
1916 void SdrObject::RestoreGeoData(const SdrObjGeoData
& rGeo
)
1918 SetBoundAndSnapRectsDirty();
1919 setOutRectangle(rGeo
.aBoundRect
);
1920 m_aAnchor
=rGeo
.aAnchor
;
1921 m_bMovProt
=rGeo
.bMovProt
;
1922 m_bSizProt
=rGeo
.bSizProt
;
1923 m_bNoPrint
=rGeo
.bNoPrint
;
1924 mbVisible
=rGeo
.mbVisible
;
1925 m_bClosedObj
=rGeo
.bClosedObj
;
1926 mnLayerID
= rGeo
.mnLayerID
;
1928 // user-defined gluepoints
1929 if (rGeo
.pGPL
!=nullptr) {
1931 if (m_pPlusData
->pGluePoints
!=nullptr) {
1932 *m_pPlusData
->pGluePoints
=*rGeo
.pGPL
;
1934 m_pPlusData
->pGluePoints
.reset(new SdrGluePointList(*rGeo
.pGPL
));
1937 if (m_pPlusData
!=nullptr && m_pPlusData
->pGluePoints
!=nullptr) {
1938 m_pPlusData
->pGluePoints
.reset();
1943 std::unique_ptr
<SdrObjGeoData
> SdrObject::GetGeoData() const
1945 std::unique_ptr
<SdrObjGeoData
> pGeo
= NewGeoData();
1950 void SdrObject::SetGeoData(const SdrObjGeoData
& rGeo
)
1952 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1953 RestoreGeoData(rGeo
);
1955 BroadcastObjectChange();
1956 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1962 const SfxItemSet
& SdrObject::GetObjectItemSet() const
1964 return GetProperties().GetObjectItemSet();
1967 const SfxItemSet
& SdrObject::GetMergedItemSet() const
1969 return GetProperties().GetMergedItemSet();
1972 void SdrObject::SetObjectItem(const SfxPoolItem
& rItem
)
1974 GetProperties().SetObjectItem(rItem
);
1977 void SdrObject::SetMergedItem(const SfxPoolItem
& rItem
)
1979 GetProperties().SetMergedItem(rItem
);
1982 void SdrObject::ClearMergedItem(const sal_uInt16 nWhich
)
1984 GetProperties().ClearMergedItem(nWhich
);
1987 void SdrObject::SetObjectItemSet(const SfxItemSet
& rSet
)
1989 GetProperties().SetObjectItemSet(rSet
);
1992 void SdrObject::SetMergedItemSet(const SfxItemSet
& rSet
, bool bClearAllItems
)
1994 GetProperties().SetMergedItemSet(rSet
, bClearAllItems
);
1997 const SfxPoolItem
& SdrObject::GetObjectItem(const sal_uInt16 nWhich
) const
1999 return GetObjectItemSet().Get(nWhich
);
2002 const SfxPoolItem
& SdrObject::GetMergedItem(const sal_uInt16 nWhich
) const
2004 return GetMergedItemSet().Get(nWhich
);
2007 void SdrObject::SetMergedItemSetAndBroadcast(const SfxItemSet
& rSet
, bool bClearAllItems
)
2009 GetProperties().SetMergedItemSetAndBroadcast(rSet
, bClearAllItems
);
2012 void SdrObject::ApplyNotPersistAttr(const SfxItemSet
& rAttr
)
2014 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
2015 NbcApplyNotPersistAttr(rAttr
);
2017 BroadcastObjectChange();
2018 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
2021 void SdrObject::NbcApplyNotPersistAttr(const SfxItemSet
& rAttr
)
2023 const tools::Rectangle
& rSnap
=GetSnapRect();
2024 const tools::Rectangle
& rLogic
=GetLogicRect();
2025 Point
aRef1(rSnap
.Center());
2027 if (const SdrTransformRef1XItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_TRANSFORMREF1X
))
2029 aRef1
.setX(pPoolItem
->GetValue() );
2031 if (const SdrTransformRef1YItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_TRANSFORMREF1Y
))
2033 aRef1
.setY(pPoolItem
->GetValue() );
2036 tools::Rectangle
aNewSnap(rSnap
);
2037 if (const SdrMoveXItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_MOVEX
))
2039 tools::Long n
= pPoolItem
->GetValue();
2042 if (const SdrMoveYItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_MOVEY
))
2044 tools::Long n
= pPoolItem
->GetValue();
2047 if (const SdrOnePositionXItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_ONEPOSITIONX
))
2049 tools::Long n
= pPoolItem
->GetValue();
2050 aNewSnap
.Move(n
-aNewSnap
.Left(),0);
2052 if (const SdrOnePositionYItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_ONEPOSITIONY
))
2054 tools::Long n
= pPoolItem
->GetValue();
2055 aNewSnap
.Move(0,n
-aNewSnap
.Top());
2057 if (const SdrOneSizeWidthItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_ONESIZEWIDTH
))
2059 tools::Long n
= pPoolItem
->GetValue();
2060 aNewSnap
.SetRight(aNewSnap
.Left()+n
);
2062 if (const SdrOneSizeHeightItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_ONESIZEHEIGHT
))
2064 tools::Long n
= pPoolItem
->GetValue();
2065 aNewSnap
.SetBottom(aNewSnap
.Top()+n
);
2067 if (aNewSnap
!=rSnap
) {
2068 if (aNewSnap
.GetSize()==rSnap
.GetSize()) {
2069 NbcMove(Size(aNewSnap
.Left()-rSnap
.Left(),aNewSnap
.Top()-rSnap
.Top()));
2071 NbcSetSnapRect(aNewSnap
);
2075 if (const SdrShearAngleItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_SHEARANGLE
))
2077 Degree100 n
= pPoolItem
->GetValue();
2080 double nTan
= tan(toRadians(n
));
2081 NbcShear(aRef1
,n
,nTan
,false);
2084 if (const SdrAngleItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_ROTATEANGLE
))
2086 Degree100 n
= pPoolItem
->GetValue();
2087 n
-=GetRotateAngle();
2092 if (const SdrRotateOneItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_ROTATEONE
))
2094 Degree100 n
= pPoolItem
->GetValue();
2097 if (const SdrHorzShearOneItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_HORZSHEARONE
))
2099 Degree100 n
= pPoolItem
->GetValue();
2100 double nTan
= tan(toRadians(n
));
2101 NbcShear(aRef1
,n
,nTan
,false);
2103 if (const SdrVertShearOneItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_VERTSHEARONE
))
2105 Degree100 n
= pPoolItem
->GetValue();
2106 double nTan
= tan(toRadians(n
));
2107 NbcShear(aRef1
,n
,nTan
,true);
2110 if (const SdrYesNoItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_OBJMOVEPROTECT
))
2112 bool b
= pPoolItem
->GetValue();
2115 if (const SdrYesNoItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_OBJSIZEPROTECT
))
2117 bool b
= pPoolItem
->GetValue();
2118 SetResizeProtect(b
);
2121 /* move protect always sets size protect */
2122 if( IsMoveProtect() )
2123 SetResizeProtect( true );
2125 if (const SdrObjPrintableItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_OBJPRINTABLE
))
2127 bool b
= pPoolItem
->GetValue();
2131 if (const SdrObjVisibleItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_OBJVISIBLE
))
2133 bool b
= pPoolItem
->GetValue();
2137 SdrLayerID nLayer
=SDRLAYER_NOTFOUND
;
2138 if (const SdrLayerIdItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_LAYERID
))
2140 nLayer
= pPoolItem
->GetValue();
2142 if (const SdrLayerNameItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_LAYERNAME
))
2144 OUString aLayerName
= pPoolItem
->GetValue();
2145 const SdrLayerAdmin
& rLayAd(nullptr != getSdrPageFromSdrObject()
2146 ? getSdrPageFromSdrObject()->GetLayerAdmin()
2147 : getSdrModelFromSdrObject().GetLayerAdmin());
2148 const SdrLayer
* pLayer
= rLayAd
.GetLayer(aLayerName
);
2150 if(nullptr != pLayer
)
2152 nLayer
=pLayer
->GetID();
2155 if (nLayer
!=SDRLAYER_NOTFOUND
) {
2156 NbcSetLayer(nLayer
);
2159 if (const SfxStringItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_OBJECTNAME
))
2161 OUString aName
= pPoolItem
->GetValue();
2164 tools::Rectangle
aNewLogic(rLogic
);
2165 if (const SdrLogicSizeWidthItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_LOGICSIZEWIDTH
))
2167 tools::Long n
= pPoolItem
->GetValue();
2168 aNewLogic
.SetRight(aNewLogic
.Left()+n
);
2170 if (const SdrLogicSizeHeightItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_LOGICSIZEHEIGHT
))
2172 tools::Long n
= pPoolItem
->GetValue();
2173 aNewLogic
.SetBottom(aNewLogic
.Top()+n
);
2175 if (aNewLogic
!=rLogic
) {
2176 NbcSetLogicRect(aNewLogic
);
2178 Fraction
aResizeX(1,1);
2179 Fraction
aResizeY(1,1);
2180 if (const SdrResizeXOneItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_RESIZEXONE
))
2182 aResizeX
*= pPoolItem
->GetValue();
2184 if (const SdrResizeYOneItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_RESIZEYONE
))
2186 aResizeY
*= pPoolItem
->GetValue();
2188 if (aResizeX
!=Fraction(1,1) || aResizeY
!=Fraction(1,1)) {
2189 NbcResize(aRef1
,aResizeX
,aResizeY
);
2193 void SdrObject::TakeNotPersistAttr(SfxItemSet
& rAttr
) const
2195 const tools::Rectangle
& rSnap
=GetSnapRect();
2196 const tools::Rectangle
& rLogic
=GetLogicRect();
2197 rAttr
.Put(SdrYesNoItem(SDRATTR_OBJMOVEPROTECT
, IsMoveProtect()));
2198 rAttr
.Put(SdrYesNoItem(SDRATTR_OBJSIZEPROTECT
, IsResizeProtect()));
2199 rAttr
.Put(SdrObjPrintableItem(IsPrintable()));
2200 rAttr
.Put(SdrObjVisibleItem(IsVisible()));
2201 rAttr
.Put(SdrAngleItem(SDRATTR_ROTATEANGLE
, GetRotateAngle()));
2202 rAttr
.Put(SdrShearAngleItem(GetShearAngle()));
2203 rAttr
.Put(SdrOneSizeWidthItem(rSnap
.GetWidth()-1));
2204 rAttr
.Put(SdrOneSizeHeightItem(rSnap
.GetHeight()-1));
2205 rAttr
.Put(SdrOnePositionXItem(rSnap
.Left()));
2206 rAttr
.Put(SdrOnePositionYItem(rSnap
.Top()));
2207 if (rLogic
.GetWidth()!=rSnap
.GetWidth()) {
2208 rAttr
.Put(SdrLogicSizeWidthItem(rLogic
.GetWidth()-1));
2210 if (rLogic
.GetHeight()!=rSnap
.GetHeight()) {
2211 rAttr
.Put(SdrLogicSizeHeightItem(rLogic
.GetHeight()-1));
2213 OUString
aName(GetName());
2215 if (!aName
.isEmpty())
2217 rAttr
.Put(SfxStringItem(SDRATTR_OBJECTNAME
, aName
));
2220 rAttr
.Put(SdrLayerIdItem(GetLayer()));
2221 const SdrLayerAdmin
& rLayAd(nullptr != getSdrPageFromSdrObject()
2222 ? getSdrPageFromSdrObject()->GetLayerAdmin()
2223 : getSdrModelFromSdrObject().GetLayerAdmin());
2224 const SdrLayer
* pLayer
= rLayAd
.GetLayerPerID(GetLayer());
2225 if(nullptr != pLayer
)
2227 rAttr
.Put(SdrLayerNameItem(pLayer
->GetName()));
2229 Point
aRef1(rSnap
.Center());
2230 Point
aRef2(aRef1
); aRef2
.AdjustY( 1 );
2231 rAttr
.Put(SdrTransformRef1XItem(aRef1
.X()));
2232 rAttr
.Put(SdrTransformRef1YItem(aRef1
.Y()));
2233 rAttr
.Put(SdrTransformRef2XItem(aRef2
.X()));
2234 rAttr
.Put(SdrTransformRef2YItem(aRef2
.Y()));
2237 SfxStyleSheet
* SdrObject::GetStyleSheet() const
2239 return GetProperties().GetStyleSheet();
2242 void SdrObject::SetStyleSheet(SfxStyleSheet
* pNewStyleSheet
, bool bDontRemoveHardAttr
)
2244 tools::Rectangle aBoundRect0
;
2247 aBoundRect0
= GetLastBoundRect();
2249 InternalSetStyleSheet(pNewStyleSheet
, bDontRemoveHardAttr
, true);
2251 BroadcastObjectChange();
2252 SendUserCall(SdrUserCallType::ChangeAttr
, aBoundRect0
);
2255 void SdrObject::NbcSetStyleSheet(SfxStyleSheet
* pNewStyleSheet
, bool bDontRemoveHardAttr
)
2257 InternalSetStyleSheet(pNewStyleSheet
, bDontRemoveHardAttr
, false);
2260 void SdrObject::InternalSetStyleSheet(SfxStyleSheet
* pNewStyleSheet
, bool bDontRemoveHardAttr
, bool bBroadcast
)
2262 GetProperties().SetStyleSheet(pNewStyleSheet
, bDontRemoveHardAttr
, bBroadcast
);
2265 // Broadcasting while setting attributes is managed by the AttrObj.
2268 SdrGluePoint
SdrObject::GetVertexGluePoint(sal_uInt16 nPosNum
) const
2270 // #i41936# Use SnapRect for default GluePoints
2271 const tools::Rectangle
aR(GetSnapRect());
2276 case 0 : aPt
= aR
.TopCenter(); break;
2277 case 1 : aPt
= aR
.RightCenter(); break;
2278 case 2 : aPt
= aR
.BottomCenter(); break;
2279 case 3 : aPt
= aR
.LeftCenter(); break;
2283 SdrGluePoint
aGP(aPt
);
2284 aGP
.SetPercent(false);
2289 SdrGluePoint
SdrObject::GetCornerGluePoint(sal_uInt16 nPosNum
) const
2291 tools::Rectangle
aR(GetCurrentBoundRect());
2294 case 0 : aPt
=aR
.TopLeft(); break;
2295 case 1 : aPt
=aR
.TopRight(); break;
2296 case 2 : aPt
=aR
.BottomRight(); break;
2297 case 3 : aPt
=aR
.BottomLeft(); break;
2299 aPt
-=GetSnapRect().Center();
2300 SdrGluePoint
aGP(aPt
);
2301 aGP
.SetPercent(false);
2305 const SdrGluePointList
* SdrObject::GetGluePointList() const
2307 if (m_pPlusData
!=nullptr) return m_pPlusData
->pGluePoints
.get();
2312 SdrGluePointList
* SdrObject::ForceGluePointList()
2315 if (m_pPlusData
->pGluePoints
==nullptr) {
2316 m_pPlusData
->pGluePoints
.reset(new SdrGluePointList
);
2318 return m_pPlusData
->pGluePoints
.get();
2321 void SdrObject::SetGlueReallyAbsolute(bool bOn
)
2323 // First a const call to see whether there are any gluepoints.
2324 // Force const call!
2325 if (GetGluePointList()!=nullptr) {
2326 SdrGluePointList
* pGPL
=ForceGluePointList();
2327 pGPL
->SetReallyAbsolute(bOn
,*this);
2331 void SdrObject::NbcRotateGluePoints(const Point
& rRef
, Degree100 nAngle
, double sn
, double cs
)
2333 // First a const call to see whether there are any gluepoints.
2334 // Force const call!
2335 if (GetGluePointList()!=nullptr) {
2336 SdrGluePointList
* pGPL
=ForceGluePointList();
2337 pGPL
->Rotate(rRef
,nAngle
,sn
,cs
,this);
2341 void SdrObject::NbcMirrorGluePoints(const Point
& rRef1
, const Point
& rRef2
)
2343 // First a const call to see whether there are any gluepoints.
2344 // Force const call!
2345 if (GetGluePointList()!=nullptr) {
2346 SdrGluePointList
* pGPL
=ForceGluePointList();
2347 pGPL
->Mirror(rRef1
,rRef2
,this);
2351 void SdrObject::NbcShearGluePoints(const Point
& rRef
, double tn
, bool bVShear
)
2353 // First a const call to see whether there are any gluepoints.
2354 // Force const call!
2355 if (GetGluePointList()!=nullptr) {
2356 SdrGluePointList
* pGPL
=ForceGluePointList();
2357 pGPL
->Shear(rRef
,tn
,bVShear
,this);
2361 void SdrObject::ConnectToNode(bool /*bTail1*/, SdrObject
* /*pObj*/)
2365 void SdrObject::DisconnectFromNode(bool /*bTail1*/)
2369 SdrObject
* SdrObject::GetConnectedNode(bool /*bTail1*/) const
2375 static void extractLineContourFromPrimitive2DSequence(
2376 const drawinglayer::primitive2d::Primitive2DContainer
& rxSequence
,
2377 basegfx::B2DPolygonVector
& rExtractedHairlines
,
2378 basegfx::B2DPolyPolygonVector
& rExtractedLineFills
)
2380 rExtractedHairlines
.clear();
2381 rExtractedLineFills
.clear();
2383 if(rxSequence
.empty())
2386 // use neutral ViewInformation
2387 const drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
2389 // create extractor, process and get result
2390 drawinglayer::processor2d::LineGeometryExtractor2D
aExtractor(aViewInformation2D
);
2391 aExtractor
.process(rxSequence
);
2393 // copy line results
2394 rExtractedHairlines
= aExtractor
.getExtractedHairlines();
2397 rExtractedLineFills
= aExtractor
.getExtractedLineFills();
2401 rtl::Reference
<SdrObject
> SdrObject::ImpConvertToContourObj(bool bForceLineDash
)
2403 rtl::Reference
<SdrObject
> pRetval
;
2405 if(LineGeometryUsageIsNecessary())
2407 basegfx::B2DPolyPolygon aMergedLineFillPolyPolygon
;
2408 basegfx::B2DPolyPolygon aMergedHairlinePolyPolygon
;
2409 drawinglayer::primitive2d::Primitive2DContainer xSequence
;
2410 GetViewContact().getViewIndependentPrimitive2DContainer(xSequence
);
2412 if(!xSequence
.empty())
2414 basegfx::B2DPolygonVector aExtractedHairlines
;
2415 basegfx::B2DPolyPolygonVector aExtractedLineFills
;
2417 extractLineContourFromPrimitive2DSequence(xSequence
, aExtractedHairlines
, aExtractedLineFills
);
2419 // for SdrObject creation, just copy all to a single Hairline-PolyPolygon
2420 for(const basegfx::B2DPolygon
& rExtractedHairline
: aExtractedHairlines
)
2422 aMergedHairlinePolyPolygon
.append(rExtractedHairline
);
2425 // check for fill rsults
2426 if (!aExtractedLineFills
.empty() && !utl::ConfigManager::IsFuzzing())
2428 // merge to a single tools::PolyPolygon (OR)
2429 aMergedLineFillPolyPolygon
= basegfx::utils::mergeToSinglePolyPolygon(std::move(aExtractedLineFills
));
2433 if(aMergedLineFillPolyPolygon
.count() || (bForceLineDash
&& aMergedHairlinePolyPolygon
.count()))
2435 SfxItemSet
aSet(GetMergedItemSet());
2436 drawing::FillStyle eOldFillStyle
= aSet
.Get(XATTR_FILLSTYLE
).GetValue();
2437 rtl::Reference
<SdrPathObj
> aLinePolygonPart
;
2438 rtl::Reference
<SdrPathObj
> aLineHairlinePart
;
2439 bool bBuildGroup(false);
2441 if(aMergedLineFillPolyPolygon
.count())
2443 // create SdrObject for filled line geometry
2444 aLinePolygonPart
= new SdrPathObj(
2445 getSdrModelFromSdrObject(),
2446 SdrObjKind::PathFill
,
2447 std::move(aMergedLineFillPolyPolygon
));
2449 // correct item properties
2450 aSet
.Put(XLineWidthItem(0));
2451 aSet
.Put(XLineStyleItem(drawing::LineStyle_NONE
));
2452 Color aColorLine
= aSet
.Get(XATTR_LINECOLOR
).GetColorValue();
2453 sal_uInt16 nTransLine
= aSet
.Get(XATTR_LINETRANSPARENCE
).GetValue();
2454 aSet
.Put(XFillColorItem(OUString(), aColorLine
));
2455 aSet
.Put(XFillStyleItem(drawing::FillStyle_SOLID
));
2456 aSet
.Put(XFillTransparenceItem(nTransLine
));
2458 aLinePolygonPart
->SetMergedItemSet(aSet
);
2461 if(aMergedHairlinePolyPolygon
.count())
2463 // create SdrObject for hairline geometry
2464 // OBJ_PATHLINE is necessary here, not OBJ_PATHFILL. This is intended
2465 // to get a non-filled object. If the poly is closed, the PathObj takes care for
2466 // the correct closed state.
2467 aLineHairlinePart
= new SdrPathObj(
2468 getSdrModelFromSdrObject(),
2469 SdrObjKind::PathLine
,
2470 std::move(aMergedHairlinePolyPolygon
));
2472 aSet
.Put(XLineWidthItem(0));
2473 aSet
.Put(XFillStyleItem(drawing::FillStyle_NONE
));
2474 aSet
.Put(XLineStyleItem(drawing::LineStyle_SOLID
));
2476 // it is also necessary to switch off line start and ends here
2477 aSet
.Put(XLineStartWidthItem(0));
2478 aSet
.Put(XLineEndWidthItem(0));
2480 aLineHairlinePart
->SetMergedItemSet(aSet
);
2482 if(aLinePolygonPart
)
2488 // check if original geometry should be added (e.g. filled and closed)
2489 bool bAddOriginalGeometry(false);
2490 SdrPathObj
* pPath
= dynamic_cast<SdrPathObj
*>(this);
2492 if(pPath
&& pPath
->IsClosed())
2494 if(eOldFillStyle
!= drawing::FillStyle_NONE
)
2496 bAddOriginalGeometry
= true;
2500 // do we need a group?
2501 if(bBuildGroup
|| bAddOriginalGeometry
)
2503 rtl::Reference
<SdrObject
> pGroup
= new SdrObjGroup(getSdrModelFromSdrObject());
2505 if(bAddOriginalGeometry
)
2507 // Add a clone of the original geometry.
2509 aSet
.Put(GetMergedItemSet());
2510 aSet
.Put(XLineStyleItem(drawing::LineStyle_NONE
));
2511 aSet
.Put(XLineWidthItem(0));
2513 rtl::Reference
<SdrObject
> pClone(CloneSdrObject(getSdrModelFromSdrObject()));
2514 pClone
->SetMergedItemSet(aSet
);
2516 pGroup
->GetSubList()->NbcInsertObject(pClone
.get());
2519 if(aLinePolygonPart
)
2521 pGroup
->GetSubList()->NbcInsertObject(aLinePolygonPart
.get());
2524 if(aLineHairlinePart
)
2526 pGroup
->GetSubList()->NbcInsertObject(aLineHairlinePart
.get());
2533 if(aLinePolygonPart
)
2535 pRetval
= aLinePolygonPart
;
2537 else if(aLineHairlinePart
)
2539 pRetval
= aLineHairlinePart
;
2547 // due to current method usage, create and return a clone when nothing has changed
2548 pRetval
= CloneSdrObject(getSdrModelFromSdrObject());
2555 void SdrObject::SetMarkProtect(bool bProt
)
2557 m_bMarkProt
= bProt
;
2561 void SdrObject::SetEmptyPresObj(bool bEpt
)
2563 m_bEmptyPresObj
= bEpt
;
2567 void SdrObject::SetNotVisibleAsMaster(bool bFlg
)
2569 m_bNotVisibleAsMaster
=bFlg
;
2573 // convert this path object to contour object, even when it is a group
2574 rtl::Reference
<SdrObject
> SdrObject::ConvertToContourObj(SdrObject
* pRet1
, bool bForceLineDash
) const
2576 rtl::Reference
<SdrObject
> pRet
= pRet1
;
2577 if(dynamic_cast<const SdrObjGroup
*>( pRet
.get()) != nullptr)
2579 SdrObjList
* pObjList2
= pRet
->GetSubList();
2580 rtl::Reference
<SdrObject
> pGroup
= new SdrObjGroup(getSdrModelFromSdrObject());
2582 for (const rtl::Reference
<SdrObject
>& pIterObj
: *pObjList2
)
2583 pGroup
->GetSubList()->NbcInsertObject(ConvertToContourObj(pIterObj
.get(), bForceLineDash
).get());
2589 if (SdrPathObj
*pPathObj
= dynamic_cast<SdrPathObj
*>(pRet
.get()))
2591 // bezier geometry got created, even for straight edges since the given
2592 // object is a result of DoConvertToPolyObj. For conversion to contour
2593 // this is not really needed and can be reduced again AFAP
2594 pPathObj
->SetPathPoly(basegfx::utils::simplifyCurveSegments(pPathObj
->GetPathPoly()));
2597 pRet
= pRet
->ImpConvertToContourObj(bForceLineDash
);
2600 // #i73441# preserve LayerID
2601 if(pRet
&& pRet
->GetLayer() != GetLayer())
2603 pRet
->SetLayer(GetLayer());
2610 rtl::Reference
<SdrObject
> SdrObject::ConvertToPolyObj(bool bBezier
, bool bLineToArea
) const
2612 rtl::Reference
<SdrObject
> pRet
= DoConvertToPolyObj(bBezier
, true);
2614 if(pRet
&& bLineToArea
)
2616 pRet
= ConvertToContourObj(pRet
.get());
2619 // #i73441# preserve LayerID
2620 if(pRet
&& pRet
->GetLayer() != GetLayer())
2622 pRet
->SetLayer(GetLayer());
2629 rtl::Reference
<SdrObject
> SdrObject::DoConvertToPolyObj(bool /*bBezier*/, bool /*bAddText*/) const
2635 void SdrObject::InsertedStateChange()
2637 const bool bIsInserted(nullptr != getParentSdrObjListFromSdrObject());
2638 const tools::Rectangle
aBoundRect0(GetLastBoundRect());
2642 SendUserCall(SdrUserCallType::Inserted
, aBoundRect0
);
2646 SendUserCall(SdrUserCallType::Removed
, aBoundRect0
);
2649 if(nullptr != m_pPlusData
&& nullptr != m_pPlusData
->pBroadcast
)
2651 SdrHint
aHint(bIsInserted
? SdrHintKind::ObjectInserted
: SdrHintKind::ObjectRemoved
, *this);
2652 m_pPlusData
->pBroadcast
->Broadcast(aHint
);
2656 void SdrObject::SetMoveProtect(bool bProt
)
2658 if(IsMoveProtect() != bProt
)
2660 // #i77187# secured and simplified
2663 BroadcastObjectChange();
2667 void SdrObject::SetResizeProtect(bool bProt
)
2669 if(IsResizeProtect() != bProt
)
2671 // #i77187# secured and simplified
2674 BroadcastObjectChange();
2678 bool SdrObject::IsPrintable() const
2683 void SdrObject::SetPrintable(bool bPrn
)
2685 if( bPrn
== m_bNoPrint
)
2691 SdrHint
aHint(SdrHintKind::ObjectChange
, *this);
2692 getSdrModelFromSdrObject().Broadcast(aHint
);
2697 bool SdrObject::IsVisible() const
2702 void SdrObject::SetVisible(bool bVisible
)
2704 if( bVisible
!= mbVisible
)
2706 mbVisible
= bVisible
;
2710 SdrHint
aHint(SdrHintKind::ObjectChange
, *this);
2711 getSdrModelFromSdrObject().Broadcast(aHint
);
2717 sal_uInt16
SdrObject::GetUserDataCount() const
2719 if (m_pPlusData
==nullptr || m_pPlusData
->pUserDataList
==nullptr) return 0;
2720 return m_pPlusData
->pUserDataList
->GetUserDataCount();
2723 SdrObjUserData
* SdrObject::GetUserData(sal_uInt16 nNum
) const
2725 if (m_pPlusData
==nullptr || m_pPlusData
->pUserDataList
==nullptr) return nullptr;
2726 return &m_pPlusData
->pUserDataList
->GetUserData(nNum
);
2729 void SdrObject::AppendUserData(std::unique_ptr
<SdrObjUserData
> pData
)
2733 OSL_FAIL("SdrObject::AppendUserData(): pData is NULL pointer.");
2738 if (!m_pPlusData
->pUserDataList
)
2739 m_pPlusData
->pUserDataList
.reset( new SdrObjUserDataList
);
2741 m_pPlusData
->pUserDataList
->AppendUserData(std::move(pData
));
2744 void SdrObject::DeleteUserData(sal_uInt16 nNum
)
2746 sal_uInt16 nCount
=GetUserDataCount();
2748 m_pPlusData
->pUserDataList
->DeleteUserData(nNum
);
2750 m_pPlusData
->pUserDataList
.reset();
2753 OSL_FAIL("SdrObject::DeleteUserData(): Invalid Index.");
2757 void SdrObject::SetUserCall(SdrObjUserCall
* pUser
)
2759 m_pUserCall
= pUser
;
2763 void SdrObject::SendUserCall(SdrUserCallType eUserCall
, const tools::Rectangle
& rBoundRect
) const
2765 SdrObject
* pGroup(getParentSdrObjectFromSdrObject());
2769 m_pUserCall
->Changed( *this, eUserCall
, rBoundRect
);
2772 if(nullptr != pGroup
&& pGroup
->GetUserCall())
2774 // broadcast to group
2775 SdrUserCallType eChildUserType
= SdrUserCallType::ChildChangeAttr
;
2779 case SdrUserCallType::MoveOnly
:
2780 eChildUserType
= SdrUserCallType::ChildMoveOnly
;
2783 case SdrUserCallType::Resize
:
2784 eChildUserType
= SdrUserCallType::ChildResize
;
2787 case SdrUserCallType::ChangeAttr
:
2788 eChildUserType
= SdrUserCallType::ChildChangeAttr
;
2791 case SdrUserCallType::Delete
:
2792 eChildUserType
= SdrUserCallType::ChildDelete
;
2795 case SdrUserCallType::Inserted
:
2796 eChildUserType
= SdrUserCallType::ChildInserted
;
2799 case SdrUserCallType::Removed
:
2800 eChildUserType
= SdrUserCallType::ChildRemoved
;
2806 pGroup
->GetUserCall()->Changed( *this, eChildUserType
, rBoundRect
);
2809 // notify our UNO shape listeners
2810 switch ( eUserCall
)
2812 case SdrUserCallType::Resize
:
2813 notifyShapePropertyChange( "Size" );
2814 [[fallthrough
]]; // RESIZE might also imply a change of the position
2815 case SdrUserCallType::MoveOnly
:
2816 notifyShapePropertyChange( "Position" );
2819 // not interested in
2824 void SdrObject::setUnoShape( const uno::Reference
< drawing::XShape
>& _rxUnoShape
)
2826 const uno::Reference
< uno::XInterface
>& xOldUnoShape( maWeakUnoShape
);
2827 // the UNO shape would be gutted by the following code; return early
2828 if ( _rxUnoShape
== xOldUnoShape
)
2830 if ( !xOldUnoShape
.is() )
2832 // make sure there is no stale impl. pointer if the UNO
2833 // shape was destroyed meanwhile (remember we only hold weak
2834 // reference to it!)
2835 mpSvxShape
= nullptr;
2840 if ( xOldUnoShape
.is() )
2842 // Remove yourself from the current UNO shape. Its destructor
2843 // will reset our UNO shape otherwise.
2844 mpSvxShape
->InvalidateSdrObject();
2847 maWeakUnoShape
= _rxUnoShape
;
2848 mpSvxShape
= comphelper::getFromUnoTunnel
<SvxShape
>( _rxUnoShape
);
2851 /** only for internal use! */
2852 SvxShape
* SdrObject::getSvxShape()
2854 DBG_TESTSOLARMUTEX();
2855 // retrieving the impl pointer and subsequently using it is not thread-safe, of course, so it needs to be
2856 // guarded by the SolarMutex
2858 uno::Reference
< uno::XInterface
> xShape( maWeakUnoShape
);
2859 //#113608#, make sure mpSvxShape is always synchronized with maWeakUnoShape
2860 if ( mpSvxShape
&& !xShape
)
2861 mpSvxShape
= nullptr;
2866 css::uno::Reference
< css::drawing::XShape
> SdrObject::getUnoShape()
2868 // try weak reference first
2869 uno::Reference
< css::drawing::XShape
> xShape
= maWeakUnoShape
;
2873 // try to access SdrPage from this SdrObject. This will only exist if the SdrObject is
2874 // inserted in a SdrObjList (page/group/3dScene)
2875 SdrPage
* pPageCandidate(getSdrPageFromSdrObject());
2877 // tdf#12152, tdf#120728
2879 // With the paradigm change to only get a SdrPage for a SdrObject when the SdrObject
2880 // is *inserted*, the functionality for creating 1:1 associated UNO API implementation
2881 // SvxShapes was partially broken: The used ::CreateShape relies on the SvxPage being
2882 // derived and the CreateShape method overloaded, implementing additional SdrInventor
2885 // The fallback to use SvxDrawPage::CreateShapeByTypeAndInventor is a trap: It's only
2886 // a static fallback that handles the SdrInventor types SdrInventor::E3d and
2887 // SdrInventor::Default. Due to that, e.g. the ReportDesigner broke in various conditions.
2889 // That again has to do with the ReportDesigner being implemented using the UNO API
2890 // aspects of SdrObjects early during their construction, not just after these are
2891 // inserted to a SdrPage - but that is not illegal or wrong, the SdrObject exists already.
2893 // As a current solution, use the (now always available) SdrModel and any of the
2894 // existing SdrPages. The only important thing is to get a SdrPage where ::CreateShape is
2895 // overloaded and implemented as needed.
2897 // Note for the future:
2898 // In a more ideal world there would be only one factory method for creating SdrObjects (not
2899 // ::CreateShape and ::CreateShapeByTypeAndInventor). This also would not be placed at
2900 // SdrPage/SvxPage at all, but at the Model where it belongs - where else would you expect
2901 // objects for the current Model to be constructed? To have this at the Page only would make
2902 // sense if different shapes would need to be constructed for different Pages in the same Model
2903 // - this is never the case.
2904 // At that Model extended functionality for that factory (or overloads and implementations)
2905 // should be placed. But to be realistic, migrating the factories to Model now is too much
2906 // work - maybe over time when melting SdrObject/SvxObject one day...
2908 // More Note (added by noel grandin)
2909 // Except that sd/ is being naughty and doing all kinds of magic during CreateShape that
2910 // requires knowing which page the object is being created for. Fixing that would require
2911 // moving a bunch of nasty logic from object creation time, to the point in time when
2912 // it is actually added to a page.
2913 if(nullptr == pPageCandidate
)
2915 // If not inserted, alternatively access a SdrPage using the SdrModel. There is
2916 // no reason not to create and return a UNO API XShape when the SdrObject is not
2917 // inserted - it may be in construction. Main paradigm is that it exists.
2918 if(0 != getSdrModelFromSdrObject().GetPageCount())
2920 // Take 1st SdrPage. That may be e.g. a special page (in SD), but the
2921 // to-be-used method ::CreateShape will be correctly overloaded in
2923 pPageCandidate
= getSdrModelFromSdrObject().GetPage(0);
2927 if(nullptr != pPageCandidate
)
2929 uno::Reference
< uno::XInterface
> xPage(pPageCandidate
->getUnoPage());
2932 SvxDrawPage
* pDrawPage
= comphelper::getFromUnoTunnel
<SvxDrawPage
>(xPage
);
2936 xShape
= pDrawPage
->CreateShape( this );
2938 setUnoShape( xShape
);
2944 // Fallback to static base functionality. CAUTION: This will only support
2945 // the most basic stuff like SdrInventor::E3d and SdrInventor::Default. All
2946 // the other SdrInventor enum entries are from overloads and are *not accessible*
2947 // using this fallback (!) - what a bad trap
2948 rtl::Reference
<SvxShape
> xNewShape
= SvxDrawPage::CreateShapeByTypeAndInventor( GetObjIdentifier(), GetObjInventor(), this );
2949 mpSvxShape
= xNewShape
.get();
2950 maWeakUnoShape
= xShape
= mpSvxShape
;
2956 void SdrObject::notifyShapePropertyChange( const OUString
& rPropName
) const
2958 DBG_TESTSOLARMUTEX();
2960 SvxShape
* pSvxShape
= const_cast< SdrObject
* >( this )->getSvxShape();
2962 return pSvxShape
->notifyPropertyChange( rPropName
);
2965 // transformation interface for StarOfficeAPI. This implements support for
2966 // homogeneous 3x3 matrices containing the transformation of the SdrObject. At the
2967 // moment it contains a shearX, rotation and translation, but for setting all linear
2968 // transforms like Scale, ShearX, ShearY, Rotate and Translate are supported.
2971 // gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon
2972 // with the base geometry and returns TRUE. Otherwise it returns FALSE.
2973 bool SdrObject::TRGetBaseGeometry(basegfx::B2DHomMatrix
& rMatrix
, basegfx::B2DPolyPolygon
& /*rPolyPolygon*/) const
2975 // any kind of SdrObject, just use SnapRect
2976 tools::Rectangle
aRectangle(GetSnapRect());
2978 // convert to transformation values
2979 basegfx::B2DTuple
aScale(aRectangle
.GetWidth(), aRectangle
.GetHeight());
2980 basegfx::B2DTuple
aTranslate(aRectangle
.Left(), aRectangle
.Top());
2982 // position maybe relative to anchorpos, convert
2983 if(getSdrModelFromSdrObject().IsWriter())
2985 if(GetAnchorPos().X() || GetAnchorPos().Y())
2987 aTranslate
-= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
2992 rMatrix
= basegfx::utils::createScaleTranslateB2DHomMatrix(aScale
, aTranslate
);
2997 // sets the base geometry of the object using infos contained in the homogeneous 3x3 matrix.
2998 // If it's an SdrPathObj it will use the provided geometry information. The Polygon has
2999 // to use (0,0) as upper left and will be scaled to the given size in the matrix.
3000 void SdrObject::TRSetBaseGeometry(const basegfx::B2DHomMatrix
& rMatrix
, const basegfx::B2DPolyPolygon
& /*rPolyPolygon*/)
3003 basegfx::B2DTuple aScale
;
3004 basegfx::B2DTuple aTranslate
;
3005 double fRotate
, fShearX
;
3006 rMatrix
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
3008 // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
3009 // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
3010 if(basegfx::fTools::less(aScale
.getX(), 0.0) && basegfx::fTools::less(aScale
.getY(), 0.0))
3012 aScale
.setX(fabs(aScale
.getX()));
3013 aScale
.setY(fabs(aScale
.getY()));
3016 // if anchor is used, make position relative to it
3017 if(getSdrModelFromSdrObject().IsWriter())
3019 if(GetAnchorPos().X() || GetAnchorPos().Y())
3021 aTranslate
+= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
3026 Point
aPoint(FRound(aTranslate
.getX()), FRound(aTranslate
.getY()));
3027 tools::Rectangle
aBaseRect(aPoint
, Size(FRound(aScale
.getX()), FRound(aScale
.getY())));
3030 SetSnapRect(aBaseRect
);
3033 // Give info if object is in destruction
3034 bool SdrObject::IsInDestruction() const
3036 return getSdrModelFromSdrObject().IsInDestruction();
3039 // return if fill is != drawing::FillStyle_NONE
3040 bool SdrObject::HasFillStyle() const
3042 return GetObjectItem(XATTR_FILLSTYLE
).GetValue() != drawing::FillStyle_NONE
;
3045 bool SdrObject::HasLineStyle() const
3047 return GetObjectItem(XATTR_LINESTYLE
).GetValue() != drawing::LineStyle_NONE
;
3052 // on import of OLE object from MS documents the BLIP size might be retrieved,
3053 // the following four methods are used to control it;
3054 // usually this data makes no sense after the import is finished, since the object
3058 void SdrObject::SetBLIPSizeRectangle( const tools::Rectangle
& aRect
)
3060 maBLIPSizeRectangle
= aRect
;
3063 void SdrObject::SetContextWritingMode( const sal_Int16
/*_nContextWritingMode*/ )
3065 // this base class does not support different writing modes, so ignore the call
3068 void SdrObject::SetDoNotInsertIntoPageAutomatically(const bool bSet
)
3070 mbDoNotInsertIntoPageAutomatically
= bSet
;
3075 bool SdrObject::HasText() const
3080 bool SdrObject::IsTextBox() const
3085 void SdrObject::MakeNameUnique()
3087 if (GetName().isEmpty())
3090 if (const E3dScene
* pE3dObj
= DynCastE3dScene(this))
3092 SdrObjList
* pObjList
= pE3dObj
->GetSubList();
3095 SdrObject
* pObj0
= pObjList
->GetObj(0);
3097 aName
= pObj0
->TakeObjNameSingul();
3101 aName
= TakeObjNameSingul();
3102 SetName(aName
+ " 1");
3105 std::unordered_set
<OUString
> aNameSet
;
3106 MakeNameUnique(aNameSet
);
3109 void SdrObject::MakeNameUnique(std::unordered_set
<OUString
>& rNameSet
)
3111 if (GetName().isEmpty())
3114 if (rNameSet
.empty())
3118 for (sal_uInt16
nPage(0); nPage
< mrSdrModelFromSdrObject
.GetPageCount(); ++nPage
)
3120 pPage
= mrSdrModelFromSdrObject
.GetPage(nPage
);
3121 SdrObjListIter
aIter(pPage
, SdrIterMode::DeepWithGroups
);
3122 while (aIter
.IsMore())
3124 pObj
= aIter
.Next();
3126 rNameSet
.insert(pObj
->GetName());
3131 OUString
sName(GetName().trim());
3132 OUString
sRootName(sName
);
3134 if (!sName
.isEmpty() && rtl::isAsciiDigit(sName
[sName
.getLength() - 1]))
3136 sal_Int32
nPos(sName
.getLength() - 1);
3137 while (nPos
> 0 && rtl::isAsciiDigit(sName
[--nPos
]));
3138 sRootName
= o3tl::trim(sName
.subView(0, nPos
+ 1));
3141 for (sal_uInt32 n
= 1; rNameSet
.find(sName
) != rNameSet
.end(); n
++)
3142 sName
= sRootName
+ " " + OUString::number(n
);
3143 rNameSet
.insert(sName
);
3148 void SdrObject::ForceMetricToItemPoolMetric(basegfx::B2DPolyPolygon
& rPolyPolygon
) const noexcept
3150 MapUnit
eMapUnit(getSdrModelFromSdrObject().GetItemPool().GetMetric(0));
3151 if(eMapUnit
== MapUnit::Map100thMM
)
3154 if (const auto eTo
= MapToO3tlLength(eMapUnit
); eTo
!= o3tl::Length::invalid
)
3156 const double fConvert(o3tl::convert(1.0, o3tl::Length::mm100
, eTo
));
3157 rPolyPolygon
.transform(basegfx::utils::createScaleB2DHomMatrix(fConvert
, fConvert
));
3161 OSL_FAIL("Missing unit translation to PoolMetric!");
3165 const tools::Rectangle
& SdrObject::getOutRectangle() const
3170 void SdrObject::setOutRectangleConst(tools::Rectangle
const& rRectangle
) const
3172 m_aOutRect
= rRectangle
;
3175 void SdrObject::setOutRectangle(tools::Rectangle
const& rRectangle
)
3177 m_aOutRect
= rRectangle
;
3180 void SdrObject::resetOutRectangle()
3182 m_aOutRect
= tools::Rectangle();
3185 void SdrObject::moveOutRectangle(sal_Int32 nXDelta
, sal_Int32 nYDelta
)
3187 m_aOutRect
.Move(nXDelta
, nYDelta
);
3190 E3dScene
* DynCastE3dScene(SdrObject
* pObj
)
3192 if( pObj
&& pObj
->GetObjInventor() == SdrInventor::E3d
&& pObj
->GetObjIdentifier() == SdrObjKind::E3D_Scene
)
3193 return static_cast<E3dScene
*>(pObj
);
3197 E3dObject
* DynCastE3dObject(SdrObject
* pObj
)
3199 if( pObj
&& pObj
->GetObjInventor() == SdrInventor::E3d
)
3200 return static_cast<E3dObject
*>(pObj
);
3204 SdrTextObj
* DynCastSdrTextObj(SdrObject
* pObj
)
3206 // SdrTextObj has a lot of subclasses, with lots of SdrObjKind identifiers, so use a virtual method
3208 if( pObj
&& pObj
->IsSdrTextObj() )
3209 return static_cast<SdrTextObj
*>(pObj
);
3213 rtl::Reference
<SdrObject
> SdrObjFactory::CreateObjectFromFactory(SdrModel
& rSdrModel
, SdrInventor nInventor
, SdrObjKind nObjIdentifier
)
3215 SdrObjCreatorParams aParams
{ nInventor
, nObjIdentifier
, rSdrModel
};
3216 for (const auto & i
: ImpGetUserMakeObjHdl()) {
3217 rtl::Reference
<SdrObject
> pObj
= i
.Call(aParams
);
3228 // SdrObject subclass, which represents an empty object of a
3229 // certain type (kind).
3230 template <SdrObjKind OBJECT_KIND
, SdrInventor OBJECT_INVENTOR
>
3231 class EmptyObject final
: public SdrObject
3234 virtual ~EmptyObject() override
3238 EmptyObject(SdrModel
& rSdrModel
)
3239 : SdrObject(rSdrModel
)
3243 EmptyObject(SdrModel
& rSdrModel
, EmptyObject
const& rSource
)
3244 : SdrObject(rSdrModel
, rSource
)
3248 rtl::Reference
<SdrObject
> CloneSdrObject(SdrModel
& rTargetModel
) const override
3250 return new EmptyObject(rTargetModel
, *this);
3253 virtual std::unique_ptr
<sdr::properties::BaseProperties
> CreateObjectSpecificProperties() override
3255 return std::make_unique
<sdr::properties::EmptyProperties
>(*this);
3258 SdrInventor
GetObjInventor() const override
3260 return OBJECT_INVENTOR
;
3263 SdrObjKind
GetObjIdentifier() const override
3268 void NbcRotate(const Point
& /*rRef*/, Degree100
/*nAngle*/, double /*sinAngle*/, double /*cosAngle*/) override
3270 assert(false); // should not be called for this kind of objects
3274 } // end anonymous namespace
3276 rtl::Reference
<SdrObject
> SdrObjFactory::MakeNewObject(
3277 SdrModel
& rSdrModel
,
3278 SdrInventor nInventor
,
3279 SdrObjKind nIdentifier
,
3280 const tools::Rectangle
* pSnapRect
)
3282 rtl::Reference
<SdrObject
> pObj
;
3283 bool bSetSnapRect(nullptr != pSnapRect
);
3285 if (nInventor
== SdrInventor::Default
)
3287 switch (nIdentifier
)
3289 case SdrObjKind::Measure
:
3291 if(nullptr != pSnapRect
)
3293 pObj
= new SdrMeasureObj(
3295 pSnapRect
->TopLeft(),
3296 pSnapRect
->BottomRight());
3300 pObj
= new SdrMeasureObj(rSdrModel
);
3304 case SdrObjKind::Line
:
3306 if(nullptr != pSnapRect
)
3308 basegfx::B2DPolygon aPoly
;
3317 pSnapRect
->Bottom()));
3318 pObj
= new SdrPathObj(
3321 basegfx::B2DPolyPolygon(aPoly
));
3325 pObj
= new SdrPathObj(
3331 case SdrObjKind::Text
:
3332 case SdrObjKind::TitleText
:
3333 case SdrObjKind::OutlineText
:
3335 if(nullptr != pSnapRect
)
3337 pObj
= new SdrRectObj(
3341 bSetSnapRect
= false;
3345 pObj
= new SdrRectObj(
3351 case SdrObjKind::CircleOrEllipse
:
3352 case SdrObjKind::CircleSection
:
3353 case SdrObjKind::CircleArc
:
3354 case SdrObjKind::CircleCut
:
3356 SdrCircKind eCircKind
= ToSdrCircKind(nIdentifier
);
3357 if(nullptr != pSnapRect
)
3359 pObj
= new SdrCircObj(rSdrModel
, eCircKind
, *pSnapRect
);
3360 bSetSnapRect
= false;
3364 pObj
= new SdrCircObj(rSdrModel
, eCircKind
);
3368 case SdrObjKind::NONE
: pObj
= nullptr; break;
3369 case SdrObjKind::Group
: pObj
=new SdrObjGroup(rSdrModel
); break;
3370 case SdrObjKind::Polygon
: pObj
=new SdrPathObj(rSdrModel
, SdrObjKind::Polygon
); break;
3371 case SdrObjKind::PolyLine
: pObj
=new SdrPathObj(rSdrModel
, SdrObjKind::PolyLine
); break;
3372 case SdrObjKind::PathLine
: pObj
=new SdrPathObj(rSdrModel
, SdrObjKind::PathLine
); break;
3373 case SdrObjKind::PathFill
: pObj
=new SdrPathObj(rSdrModel
, SdrObjKind::PathFill
); break;
3374 case SdrObjKind::FreehandLine
: pObj
=new SdrPathObj(rSdrModel
, SdrObjKind::FreehandLine
); break;
3375 case SdrObjKind::FreehandFill
: pObj
=new SdrPathObj(rSdrModel
, SdrObjKind::FreehandFill
); break;
3376 case SdrObjKind::PathPoly
: pObj
=new SdrPathObj(rSdrModel
, SdrObjKind::Polygon
); break;
3377 case SdrObjKind::PathPolyLine
: pObj
=new SdrPathObj(rSdrModel
, SdrObjKind::PolyLine
); break;
3378 case SdrObjKind::Edge
: pObj
=new SdrEdgeObj(rSdrModel
); break;
3379 case SdrObjKind::Rectangle
: pObj
=new SdrRectObj(rSdrModel
); break;
3380 case SdrObjKind::Graphic
: pObj
=new SdrGrafObj(rSdrModel
); break;
3381 case SdrObjKind::OLE2
: pObj
=new SdrOle2Obj(rSdrModel
); break;
3382 case SdrObjKind::OLEPluginFrame
: pObj
=new SdrOle2Obj(rSdrModel
, true); break;
3383 case SdrObjKind::Caption
: pObj
=new SdrCaptionObj(rSdrModel
); break;
3384 case SdrObjKind::Page
: pObj
=new SdrPageObj(rSdrModel
); break;
3385 case SdrObjKind::UNO
: pObj
=new SdrUnoObj(rSdrModel
, OUString()); break;
3386 case SdrObjKind::CustomShape
: pObj
=new SdrObjCustomShape(rSdrModel
); break;
3387 #if HAVE_FEATURE_AVMEDIA
3388 case SdrObjKind::Media
: pObj
=new SdrMediaObj(rSdrModel
); break;
3390 case SdrObjKind::Table
: pObj
=new sdr::table::SdrTableObj(rSdrModel
); break;
3391 case SdrObjKind::NewFrame
: // used for frame creation in writer
3392 pObj
= new EmptyObject
<SdrObjKind::NewFrame
, SdrInventor::Default
>(rSdrModel
);
3401 pObj
= CreateObjectFromFactory(rSdrModel
, nInventor
, nIdentifier
);
3406 // Well, if no one wants it...
3410 if(bSetSnapRect
&& nullptr != pSnapRect
)
3412 pObj
->NbcSetSnapRect(*pSnapRect
);
3418 void SdrObjFactory::InsertMakeObjectHdl(Link
<SdrObjCreatorParams
, rtl::Reference
<SdrObject
>> const & rLink
)
3420 std::vector
<Link
<SdrObjCreatorParams
, rtl::Reference
<SdrObject
>>>& rLL
=ImpGetUserMakeObjHdl();
3421 auto it
= std::find(rLL
.begin(), rLL
.end(), rLink
);
3422 if (it
!= rLL
.end()) {
3423 OSL_FAIL("SdrObjFactory::InsertMakeObjectHdl(): Link already in place.");
3425 rLL
.push_back(rLink
);
3429 void SdrObjFactory::RemoveMakeObjectHdl(Link
<SdrObjCreatorParams
, rtl::Reference
<SdrObject
>> const & rLink
)
3431 std::vector
<Link
<SdrObjCreatorParams
, rtl::Reference
<SdrObject
>>>& rLL
=ImpGetUserMakeObjHdl();
3432 auto it
= std::find(rLL
.begin(), rLL
.end(), rLink
);
3433 if (it
!= rLL
.end())
3439 ISdrObjectFilter::~ISdrObjectFilter()
3444 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */