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/shapepropertynotifier.hxx>
55 #include <svx/svdotable.hxx>
57 #include <svx/sdr/contact/displayinfo.hxx>
58 #include <sdr/contact/objectcontactofobjlistpainter.hxx>
59 #include <svx/sdr/contact/viewcontactofsdrobj.hxx>
60 #include <sdr/properties/emptyproperties.hxx>
61 #include <svx/sdrhittesthelper.hxx>
62 #include <svx/sdrobjectuser.hxx>
63 #include <svx/sdrobjectfilter.hxx>
64 #include <svx/svddrag.hxx>
65 #include <svx/svdetc.hxx>
66 #include <svx/svdhdl.hxx>
67 #include <svx/svditer.hxx>
68 #include <svx/svdmodel.hxx>
69 #include <svx/svdoashp.hxx>
70 #include <svx/svdocapt.hxx>
71 #include <svx/svdocirc.hxx>
72 #include <svx/svdoedge.hxx>
73 #include <svx/svdograf.hxx>
74 #include <svx/svdogrp.hxx>
75 #include <svx/svdomeas.hxx>
76 #include <svx/svdomedia.hxx>
77 #include <svx/svdoole2.hxx>
78 #include <svx/svdopage.hxx>
79 #include <svx/svdopath.hxx>
80 #include <svx/svdorect.hxx>
81 #include <svx/svdotext.hxx>
82 #include <svx/svdouno.hxx>
83 #include <svx/svdovirt.hxx>
84 #include <svx/svdpage.hxx>
85 #include <svx/svdpool.hxx>
86 #include <svx/strings.hrc>
87 #include <svx/dialmgr.hxx>
88 #include <svx/svdtrans.hxx>
89 #include <svx/svdundo.hxx>
90 #include <svx/svdview.hxx>
91 #include <sxlayitm.hxx>
92 #include <sxlogitm.hxx>
93 #include <sxmovitm.hxx>
94 #include <sxoneitm.hxx>
95 #include <sxopitm.hxx>
96 #include <sxreoitm.hxx>
97 #include <sxrooitm.hxx>
98 #include <sxsaitm.hxx>
99 #include <sxsoitm.hxx>
100 #include <sxtraitm.hxx>
101 #include <svx/unopage.hxx>
102 #include <svx/unoshape.hxx>
103 #include <svx/xfillit0.hxx>
104 #include <svx/xflclit.hxx>
105 #include <svx/xfltrit.hxx>
106 #include <svx/xlineit0.hxx>
107 #include <svx/xlnclit.hxx>
108 #include <svx/xlnedwit.hxx>
109 #include <svx/xlnstwit.hxx>
110 #include <svx/xlntrit.hxx>
111 #include <svx/xlnwtit.hxx>
112 #include <svx/svdglue.hxx>
113 #include <svx/svdsob.hxx>
114 #include <svdobjplusdata.hxx>
115 #include <svdobjuserdatalist.hxx>
117 #include <unordered_set>
120 #include <libxml/xmlwriter.h>
123 #include <svx/scene3d.hxx>
124 #include <rtl/character.hxx>
125 #include <tools/UnitConversion.hxx>
126 #include <o3tl/string_view.hxx>
128 using namespace ::com::sun::star
;
131 SdrObjUserCall::~SdrObjUserCall()
135 void SdrObjUserCall::Changed(const SdrObject
& /*rObj*/, SdrUserCallType
/*eType*/, const tools::Rectangle
& /*rOldBoundRect*/)
139 void const* SdrObjUserCall::GetPDFAnchorStructureElementKey(SdrObject
const&)
144 SdrObjMacroHitRec::SdrObjMacroHitRec() :
150 SdrObjUserData::SdrObjUserData(SdrInventor nInv
, sal_uInt16 nId
) :
154 SdrObjUserData::SdrObjUserData(const SdrObjUserData
& rData
) :
155 nInventor(rData
.nInventor
),
156 nIdentifier(rData
.nIdentifier
) {}
158 SdrObjUserData::~SdrObjUserData() {}
160 SdrObjGeoData::SdrObjGeoData():
170 SdrObjGeoData::~SdrObjGeoData()
174 SdrObjTransformInfoRec::SdrObjTransformInfoRec() :
176 bResizeFreeAllowed(true),
177 bResizePropAllowed(true),
178 bRotateFreeAllowed(true),
179 bRotate90Allowed(true),
180 bMirrorFreeAllowed(true),
181 bMirror45Allowed(true),
182 bMirror90Allowed(true),
183 bTransparenceAllowed(true),
185 bEdgeRadiusAllowed(true),
186 bNoOrthoDesired(true),
188 bCanConvToPath(true),
189 bCanConvToPoly(true),
190 bCanConvToContour(false),
191 bCanConvToPathLineToArea(true),
192 bCanConvToPolyLineToArea(true) {}
194 struct SdrObject::Impl
196 sdr::ObjectUserVector maObjectUsers
;
197 std::optional
<double> mnRelativeWidth
;
198 std::optional
<double> mnRelativeHeight
;
199 sal_Int16 meRelativeWidthRelation
;
200 sal_Int16 meRelativeHeightRelation
;
203 meRelativeWidthRelation(text::RelOrientation::PAGE_FRAME
),
204 meRelativeHeightRelation(text::RelOrientation::PAGE_FRAME
) {}
207 const std::shared_ptr
< svx::diagram::IDiagramHelper
>& SdrObject::getDiagramHelper() const
209 static std::shared_ptr
< svx::diagram::IDiagramHelper
> aEmpty
;
213 // BaseProperties section
215 std::unique_ptr
<sdr::properties::BaseProperties
> SdrObject::CreateObjectSpecificProperties()
217 return std::make_unique
<sdr::properties::EmptyProperties
>(*this);
220 sdr::properties::BaseProperties
& SdrObject::GetProperties() const
224 // CAUTION(!) Do *not* call this during SdrObject construction,
225 // that will lead to wrong type-casts (dependent on constructor-level)
226 // and thus eventually create the wrong sdr::properties (!). Is there
227 // a way to check if on the stack is a SdrObject-constructor (?)
228 const_cast< SdrObject
* >(this)->mpProperties
=
229 const_cast< SdrObject
* >(this)->CreateObjectSpecificProperties();
232 return *mpProperties
;
236 // ObjectUser section
238 void SdrObject::AddObjectUser(sdr::ObjectUser
& rNewUser
)
240 mpImpl
->maObjectUsers
.push_back(&rNewUser
);
243 void SdrObject::RemoveObjectUser(sdr::ObjectUser
& rOldUser
)
245 const sdr::ObjectUserVector::iterator aFindResult
=
246 std::find(mpImpl
->maObjectUsers
.begin(), mpImpl
->maObjectUsers
.end(), &rOldUser
);
247 if (aFindResult
!= mpImpl
->maObjectUsers
.end())
249 mpImpl
->maObjectUsers
.erase(aFindResult
);
254 // DrawContact section
256 std::unique_ptr
<sdr::contact::ViewContact
> SdrObject::CreateObjectSpecificViewContact()
258 return std::make_unique
<sdr::contact::ViewContactOfSdrObj
>(*this);
261 sdr::contact::ViewContact
& SdrObject::GetViewContact() const
265 const_cast< SdrObject
* >(this)->mpViewContact
=
266 const_cast< SdrObject
* >(this)->CreateObjectSpecificViewContact();
269 return *mpViewContact
;
272 // DrawContact support: Methods for handling Object changes
273 void SdrObject::ActionChanged() const
275 // Do necessary ViewContact actions
276 GetViewContact().ActionChanged();
279 SdrPage
* SdrObject::getSdrPageFromSdrObject() const
281 if (SdrObjList
* pParentList
= getParentSdrObjListFromSdrObject())
283 return pParentList
->getSdrPageFromSdrObjList();
289 SdrModel
& SdrObject::getSdrModelFromSdrObject() const
291 return mrSdrModelFromSdrObject
;
294 void SdrObject::setParentOfSdrObject(SdrObjList
* pNewObjList
)
296 assert(!pNewObjList
|| mpParentOfSdrObject
!= pNewObjList
);
297 if(mpParentOfSdrObject
== pNewObjList
)
299 // we need to be removed from the old parent before we are attached to the new parent
300 assert(bool(mpParentOfSdrObject
) != bool(pNewObjList
) && "may only transition empty->full or full->empty");
302 // remember current page
303 SdrPage
* pOldPage(getSdrPageFromSdrObject());
306 mpParentOfSdrObject
= pNewObjList
;
309 SdrPage
* pNewPage(getSdrPageFromSdrObject());
311 // broadcast page change over objects if needed
312 if(pOldPage
!= pNewPage
)
314 handlePageChange(pOldPage
, pNewPage
);
318 SdrObjList
* SdrObject::getParentSdrObjListFromSdrObject() const
320 return mpParentOfSdrObject
;
323 SdrObjList
* SdrObject::getChildrenOfSdrObject() const
325 // default has no children
329 void SdrObject::SetBoundRectDirty()
335 // SdrObjectLifetimeWatchDog:
336 void impAddIncarnatedSdrObjectToSdrModel(SdrObject
& rSdrObject
, SdrModel
& rSdrModel
)
338 rSdrModel
.maAllIncarnatedObjects
.insert(&rSdrObject
);
340 void impRemoveIncarnatedSdrObjectToSdrModel(SdrObject
& rSdrObject
, SdrModel
& rSdrModel
)
342 if(!rSdrModel
.maAllIncarnatedObjects
.erase(&rSdrObject
))
344 assert(false && "SdrObject::~SdrObject: Destructed incarnation of SdrObject not member of this SdrModel (!)");
349 SdrObject::SdrObject(SdrModel
& rSdrModel
)
350 : mpFillGeometryDefiningShape(nullptr)
351 ,mrSdrModelFromSdrObject(rSdrModel
)
352 ,m_pUserCall(nullptr)
354 ,mpParentOfSdrObject(nullptr)
356 ,mnNavigationPosition(SAL_MAX_UINT32
)
358 ,mpSvxShape( nullptr )
359 ,mbDoNotInsertIntoPageAutomatically(false)
362 m_bSnapRectDirty
=true;
366 m_bEmptyPresObj
=false;
367 m_bNotVisibleAsMaster
=false;
372 mbLineIsOutsideGeometry
= false;
375 mbSupportTextIndentingOnLineWidthChange
= false;
382 // SdrObjectLifetimeWatchDog:
383 impAddIncarnatedSdrObjectToSdrModel(*this, getSdrModelFromSdrObject());
387 SdrObject::SdrObject(SdrModel
& rSdrModel
, SdrObject
const & rSource
)
388 : mpFillGeometryDefiningShape(nullptr)
389 ,mrSdrModelFromSdrObject(rSdrModel
)
390 ,m_pUserCall(nullptr)
392 ,mpParentOfSdrObject(nullptr)
394 ,mnNavigationPosition(SAL_MAX_UINT32
)
396 ,mpSvxShape( nullptr )
397 ,mbDoNotInsertIntoPageAutomatically(false)
400 m_bSnapRectDirty
=true;
404 m_bEmptyPresObj
=false;
405 m_bNotVisibleAsMaster
=false;
410 mbLineIsOutsideGeometry
= false;
413 mbSupportTextIndentingOnLineWidthChange
= false;
420 mpProperties
.reset();
421 mpViewContact
.reset();
423 // The CloneSdrObject() method uses the local copy constructor from the individual
424 // sdr::properties::BaseProperties class. Since the target class maybe for another
425 // draw object, an SdrObject needs to be provided, as in the normal constructor.
426 mpProperties
= rSource
.GetProperties().Clone(*this);
428 setOutRectangle(rSource
.getOutRectangle());
429 mnLayerID
= rSource
.mnLayerID
;
430 m_aAnchor
=rSource
.m_aAnchor
;
431 m_bVirtObj
=rSource
.m_bVirtObj
;
432 m_bSizProt
=rSource
.m_bSizProt
;
433 m_bMovProt
=rSource
.m_bMovProt
;
434 m_bNoPrint
=rSource
.m_bNoPrint
;
435 mbVisible
=rSource
.mbVisible
;
436 m_bMarkProt
=rSource
.m_bMarkProt
;
437 m_bEmptyPresObj
=rSource
.m_bEmptyPresObj
;
438 m_bNotVisibleAsMaster
=rSource
.m_bNotVisibleAsMaster
;
439 m_bSnapRectDirty
=true;
441 if (rSource
.m_pPlusData
!=nullptr) {
442 m_pPlusData
.reset(rSource
.m_pPlusData
->Clone(this));
444 if (m_pPlusData
!=nullptr && m_pPlusData
->pBroadcast
!=nullptr) {
445 m_pPlusData
->pBroadcast
.reset(); // broadcaster isn't copied
448 m_pGrabBagItem
.reset();
449 if (rSource
.m_pGrabBagItem
!=nullptr)
450 m_pGrabBagItem
.reset(rSource
.m_pGrabBagItem
->Clone());
452 // SdrObjectLifetimeWatchDog:
453 impAddIncarnatedSdrObjectToSdrModel(*this, getSdrModelFromSdrObject());
457 SdrObject::~SdrObject()
460 // see logic in SdrObject::release
461 assert(m_refCount
== -1);
463 // Tell all the registered ObjectUsers that the page is in destruction.
464 // And clear the vector. This means that user do not need to call RemoveObjectUser()
465 // when they get called from ObjectInDestruction().
466 sdr::ObjectUserVector aList
;
467 aList
.swap(mpImpl
->maObjectUsers
);
468 for(sdr::ObjectUser
* pObjectUser
: aList
)
470 DBG_ASSERT(pObjectUser
, "SdrObject::~SdrObject: corrupt ObjectUser list (!)");
471 pObjectUser
->ObjectInDestruction(*this);
475 SendUserCall(SdrUserCallType::Delete
, GetLastBoundRect());
476 o3tl::reset_preserve_ptr_during(m_pPlusData
);
478 m_pGrabBagItem
.reset();
479 mpProperties
.reset();
480 mpViewContact
.reset();
482 // SdrObjectLifetimeWatchDog:
483 impRemoveIncarnatedSdrObjectToSdrModel(*this, getSdrModelFromSdrObject());
487 void SdrObject::acquire() noexcept
490 assert(m_refCount
!= -1);
492 osl_atomic_increment( &m_refCount
);
495 void SdrObject::release() noexcept
497 oslInterlockedCount x
= osl_atomic_decrement( &m_refCount
);
500 disposeWeakConnectionPoint();
502 // make sure it doesn't accidentally come back to life, see assert in acquire()
503 osl_atomic_decrement( &m_refCount
);
509 void SdrObject::SetBoundAndSnapRectsDirty(bool bNotMyself
, bool bRecursive
)
514 m_bSnapRectDirty
=true;
517 if (bRecursive
&& nullptr != getParentSdrObjListFromSdrObject())
519 getParentSdrObjListFromSdrObject()->SetSdrObjListRectsDirty();
523 void SdrObject::handlePageChange(SdrPage
*, SdrPage
* )
528 // global static ItemPool for not-yet-inserted items
529 static rtl::Reference
<SdrItemPool
> mpGlobalItemPool
;
531 /** If we let the libc runtime clean us up, we trigger a crash */
534 class TerminateListener
: public ::cppu::WeakImplHelper
< css::frame::XTerminateListener
>
536 void SAL_CALL
queryTermination( const lang::EventObject
& ) override
538 void SAL_CALL
notifyTermination( const lang::EventObject
& ) override
540 mpGlobalItemPool
.clear();
542 virtual void SAL_CALL
disposing( const ::css::lang::EventObject
& ) override
547 // init global static itempool
548 SdrItemPool
& SdrObject::GetGlobalDrawObjectItemPool()
550 if(!mpGlobalItemPool
)
552 mpGlobalItemPool
= new SdrItemPool();
553 rtl::Reference
<SfxItemPool
> pGlobalOutlPool
= EditEngine::CreatePool();
554 mpGlobalItemPool
->SetSecondaryPool(pGlobalOutlPool
.get());
555 mpGlobalItemPool
->SetDefaultMetric(SdrEngineDefaults::GetMapUnit());
556 mpGlobalItemPool
->FreezeIdRanges();
557 if (utl::ConfigManager::IsFuzzing())
558 mpGlobalItemPool
->acquire();
561 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create(comphelper::getProcessComponentContext());
562 uno::Reference
< frame::XTerminateListener
> xListener( new TerminateListener
);
563 xDesktop
->addTerminateListener( xListener
);
567 return *mpGlobalItemPool
;
570 void SdrObject::SetRelativeWidth( double nValue
)
572 mpImpl
->mnRelativeWidth
= nValue
;
575 void SdrObject::SetRelativeWidthRelation( sal_Int16 eValue
)
577 mpImpl
->meRelativeWidthRelation
= eValue
;
580 void SdrObject::SetRelativeHeight( double nValue
)
582 mpImpl
->mnRelativeHeight
= nValue
;
585 void SdrObject::SetRelativeHeightRelation( sal_Int16 eValue
)
587 mpImpl
->meRelativeHeightRelation
= eValue
;
590 const double* SdrObject::GetRelativeWidth( ) const
592 if (!mpImpl
->mnRelativeWidth
)
595 return &*mpImpl
->mnRelativeWidth
;
598 sal_Int16
SdrObject::GetRelativeWidthRelation() const
600 return mpImpl
->meRelativeWidthRelation
;
603 const double* SdrObject::GetRelativeHeight( ) const
605 if (!mpImpl
->mnRelativeHeight
)
608 return &*mpImpl
->mnRelativeHeight
;
611 sal_Int16
SdrObject::GetRelativeHeightRelation() const
613 return mpImpl
->meRelativeHeightRelation
;
616 SfxItemPool
& SdrObject::GetObjectItemPool() const
618 return getSdrModelFromSdrObject().GetItemPool();
621 SdrInventor
SdrObject::GetObjInventor() const
623 return SdrInventor::Default
;
626 SdrObjKind
SdrObject::GetObjIdentifier() const
628 return SdrObjKind::NONE
;
631 void SdrObject::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
633 rInfo
.bRotateFreeAllowed
=false;
634 rInfo
.bMirrorFreeAllowed
=false;
635 rInfo
.bTransparenceAllowed
= false;
636 rInfo
.bShearAllowed
=false;
637 rInfo
.bEdgeRadiusAllowed
=false;
638 rInfo
.bCanConvToPath
=false;
639 rInfo
.bCanConvToPoly
=false;
640 rInfo
.bCanConvToContour
= false;
641 rInfo
.bCanConvToPathLineToArea
=false;
642 rInfo
.bCanConvToPolyLineToArea
=false;
645 SdrLayerID
SdrObject::GetLayer() const
650 bool SdrObject::isVisibleOnAnyOfTheseLayers(const SdrLayerIDSet
& rSet
) const
652 if (rSet
.IsSet(GetLayer()))
654 SdrObjList
* pOL
=GetSubList();
657 const size_t nObjCount
= pOL
->GetObjCount();
658 for (size_t nObjNum
= 0; nObjNum
<nObjCount
; ++nObjNum
)
659 if (pOL
->GetObj(nObjNum
)->isVisibleOnAnyOfTheseLayers(rSet
))
664 void SdrObject::NbcSetLayer(SdrLayerID nLayer
)
669 void SdrObject::SetLayer(SdrLayerID nLayer
)
673 BroadcastObjectChange();
676 void SdrObject::AddListener(SfxListener
& rListener
)
679 if (m_pPlusData
->pBroadcast
==nullptr) m_pPlusData
->pBroadcast
.reset(new SfxBroadcaster
);
681 // SdrEdgeObj may be connected to same SdrObject on both ends so allow it
683 SdrEdgeObj
const*const pEdge(dynamic_cast<SdrEdgeObj
const*>(&rListener
));
684 rListener
.StartListening(*m_pPlusData
->pBroadcast
, pEdge
? DuplicateHandling::Allow
: DuplicateHandling::Unexpected
);
687 void SdrObject::RemoveListener(SfxListener
& rListener
)
689 if (m_pPlusData
!=nullptr && m_pPlusData
->pBroadcast
!=nullptr) {
690 rListener
.EndListening(*m_pPlusData
->pBroadcast
);
691 if (!m_pPlusData
->pBroadcast
->HasListeners()) {
692 m_pPlusData
->pBroadcast
.reset();
697 const SfxBroadcaster
* SdrObject::GetBroadcaster() const
699 return m_pPlusData
!=nullptr ? m_pPlusData
->pBroadcast
.get() : nullptr;
702 void SdrObject::AddReference(SdrVirtObj
& rVrtObj
)
704 AddListener(rVrtObj
);
707 void SdrObject::DelReference(SdrVirtObj
& rVrtObj
)
709 RemoveListener(rVrtObj
);
712 bool SdrObject::IsGroupObject() const
714 return GetSubList()!=nullptr;
717 SdrObjList
* SdrObject::GetSubList() const
722 SdrObject
* SdrObject::getParentSdrObjectFromSdrObject() const
724 SdrObjList
* pParent(getParentSdrObjListFromSdrObject());
726 if(nullptr == pParent
)
731 return pParent
->getSdrObjectFromSdrObjList();
734 void SdrObject::SetName(const OUString
& rStr
, const bool bSetChanged
)
736 if (!rStr
.isEmpty() && !m_pPlusData
)
741 if(!(m_pPlusData
&& m_pPlusData
->aObjName
!= rStr
))
744 // Undo/Redo for setting object's name (#i73249#)
746 if ( getSdrModelFromSdrObject().IsUndoEnabled() )
749 std::unique_ptr
<SdrUndoAction
> pUndoAction
=
750 SdrUndoFactory::CreateUndoObjectStrAttr(
752 SdrUndoObjStrAttr::ObjStrAttrType::Name
,
755 getSdrModelFromSdrObject().BegUndo( pUndoAction
->GetComment() );
756 getSdrModelFromSdrObject().AddUndo( std::move(pUndoAction
) );
758 m_pPlusData
->aObjName
= rStr
;
759 // Undo/Redo for setting object's name (#i73249#)
762 getSdrModelFromSdrObject().EndUndo();
767 BroadcastObjectChange();
771 const OUString
& SdrObject::GetName() const
773 static const OUString EMPTY
= u
"";
777 return m_pPlusData
->aObjName
;
783 void SdrObject::SetTitle(const OUString
& rStr
)
785 if (!rStr
.isEmpty() && !m_pPlusData
)
790 if(!(m_pPlusData
&& m_pPlusData
->aObjTitle
!= rStr
))
793 // Undo/Redo for setting object's title (#i73249#)
795 if ( getSdrModelFromSdrObject().IsUndoEnabled() )
798 std::unique_ptr
<SdrUndoAction
> pUndoAction
=
799 SdrUndoFactory::CreateUndoObjectStrAttr(
801 SdrUndoObjStrAttr::ObjStrAttrType::Title
,
804 getSdrModelFromSdrObject().BegUndo( pUndoAction
->GetComment() );
805 getSdrModelFromSdrObject().AddUndo( std::move(pUndoAction
) );
807 m_pPlusData
->aObjTitle
= rStr
;
808 // Undo/Redo for setting object's title (#i73249#)
811 getSdrModelFromSdrObject().EndUndo();
814 BroadcastObjectChange();
817 OUString
SdrObject::GetTitle() const
821 return m_pPlusData
->aObjTitle
;
827 void SdrObject::SetDescription(const OUString
& rStr
)
829 if (!rStr
.isEmpty() && !m_pPlusData
)
834 if(!(m_pPlusData
&& m_pPlusData
->aObjDescription
!= rStr
))
837 // Undo/Redo for setting object's description (#i73249#)
839 if ( getSdrModelFromSdrObject().IsUndoEnabled() )
842 std::unique_ptr
<SdrUndoAction
> pUndoAction
=
843 SdrUndoFactory::CreateUndoObjectStrAttr(
845 SdrUndoObjStrAttr::ObjStrAttrType::Description
,
848 getSdrModelFromSdrObject().BegUndo( pUndoAction
->GetComment() );
849 getSdrModelFromSdrObject().AddUndo( std::move(pUndoAction
) );
851 m_pPlusData
->aObjDescription
= rStr
;
852 // Undo/Redo for setting object's description (#i73249#)
855 getSdrModelFromSdrObject().EndUndo();
858 BroadcastObjectChange();
861 OUString
SdrObject::GetDescription() const
865 return m_pPlusData
->aObjDescription
;
871 void SdrObject::SetDecorative(bool const isDecorative
)
875 if (m_pPlusData
->isDecorative
== isDecorative
)
880 if (getSdrModelFromSdrObject().IsUndoEnabled())
882 std::unique_ptr
<SdrUndoAction
> pUndoAction(
883 SdrUndoFactory::CreateUndoObjectDecorative(
884 *this, m_pPlusData
->isDecorative
));
885 getSdrModelFromSdrObject().BegUndo(pUndoAction
->GetComment());
886 getSdrModelFromSdrObject().AddUndo(std::move(pUndoAction
));
889 m_pPlusData
->isDecorative
= isDecorative
;
891 if (getSdrModelFromSdrObject().IsUndoEnabled())
893 getSdrModelFromSdrObject().EndUndo();
897 BroadcastObjectChange();
900 bool SdrObject::IsDecorative() const
902 return m_pPlusData
== nullptr ? false : m_pPlusData
->isDecorative
;
905 sal_uInt32
SdrObject::GetOrdNum() const
907 if (SdrObjList
* pParentList
= getParentSdrObjListFromSdrObject())
909 if (pParentList
->IsObjOrdNumsDirty())
911 pParentList
->RecalcObjOrdNums();
913 } else const_cast<SdrObject
*>(this)->m_nOrdNum
=0;
917 void SdrObject::SetOrdNum(sal_uInt32 nNum
)
922 void SdrObject::GetGrabBagItem(css::uno::Any
& rVal
) const
924 if (m_pGrabBagItem
!= nullptr)
925 m_pGrabBagItem
->QueryValue(rVal
);
927 rVal
<<= uno::Sequence
<beans::PropertyValue
>();
930 void SdrObject::SetGrabBagItem(const css::uno::Any
& rVal
)
932 if (m_pGrabBagItem
== nullptr)
933 m_pGrabBagItem
.reset(new SfxGrabBagItem
);
935 m_pGrabBagItem
->PutValue(rVal
, 0);
938 BroadcastObjectChange();
941 sal_uInt32
SdrObject::GetNavigationPosition() const
943 if (nullptr != getParentSdrObjListFromSdrObject() && getParentSdrObjListFromSdrObject()->RecalcNavigationPositions())
945 return mnNavigationPosition
;
952 void SdrObject::SetNavigationPosition (const sal_uInt32 nNewPosition
)
954 mnNavigationPosition
= nNewPosition
;
958 // To make clearer that this method may trigger RecalcBoundRect and thus may be
959 // expensive and sometimes problematic (inside a bigger object change you will get
960 // non-useful BoundRects sometimes) I rename that method from GetBoundRect() to
961 // GetCurrentBoundRect().
962 const tools::Rectangle
& SdrObject::GetCurrentBoundRect() const
964 auto const& rRectangle
= getOutRectangle();
965 if (rRectangle
.IsEmpty())
967 const_cast< SdrObject
* >(this)->RecalcBoundRect();
973 // To have a possibility to get the last calculated BoundRect e.g for producing
974 // the first rectangle for repaints (old and new need to be used) without forcing
975 // a RecalcBoundRect (which may be problematical and expensive sometimes) I add here
976 // a new method for accessing the last BoundRect.
977 const tools::Rectangle
& SdrObject::GetLastBoundRect() const
979 return getOutRectangle();
982 void SdrObject::RecalcBoundRect()
984 // #i101680# suppress BoundRect calculations on import(s)
985 if ((getSdrModelFromSdrObject().isLocked()) || utl::ConfigManager::IsFuzzing())
988 auto const& rRectangle
= getOutRectangle();
990 // central new method which will calculate the BoundRect using primitive geometry
991 if (!rRectangle
.IsEmpty())
994 // Use view-independent data - we do not want any connections
995 // to e.g. GridOffset in SdrObject-level
996 drawinglayer::primitive2d::Primitive2DContainer xPrimitives
;
997 GetViewContact().getViewIndependentPrimitive2DContainer(xPrimitives
);
999 if (xPrimitives
.empty())
1002 // use neutral ViewInformation and get the range of the primitives
1003 const drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
1004 const basegfx::B2DRange
aRange(xPrimitives
.getB2DRange(aViewInformation2D
));
1006 if (!aRange
.isEmpty())
1008 tools::Rectangle
aNewRectangle(
1009 tools::Long(floor(aRange
.getMinX())),
1010 tools::Long(floor(aRange
.getMinY())),
1011 tools::Long(ceil(aRange
.getMaxX())),
1012 tools::Long(ceil(aRange
.getMaxY())));
1013 setOutRectangle(aNewRectangle
);
1018 void SdrObject::BroadcastObjectChange() const
1020 if ((getSdrModelFromSdrObject().isLocked()) || utl::ConfigManager::IsFuzzing())
1023 bool bPlusDataBroadcast(m_pPlusData
&& m_pPlusData
->pBroadcast
);
1024 bool bObjectChange(IsInserted());
1026 if(!(bPlusDataBroadcast
|| bObjectChange
))
1029 SdrHint
aHint(SdrHintKind::ObjectChange
, *this);
1031 if(bPlusDataBroadcast
)
1033 m_pPlusData
->pBroadcast
->Broadcast(aHint
);
1038 getSdrModelFromSdrObject().Broadcast(aHint
);
1042 void SdrObject::SetChanged()
1044 // For testing purposes, use the new ViewContact for change
1045 // notification now.
1048 // TTTT Need to check meaning/usage of IsInserted in one
1049 // of the next changes. It should not mean to have a SdrModel
1050 // set (this is guaranteed now), but should be connected to
1051 // being added to a SdrPage (?)
1052 // TTTT tdf#120066 Indeed - This triggers e.g. by CustomShape
1053 // geometry-presenting SdrObjects that are in a SdrObjGroup,
1054 // but the SdrObjGroup is *by purpose* not inserted.
1055 // Need to check deeper and maybe identify all ::IsInserted()
1056 // calls by rename and let the compiler work...
1057 if(nullptr != getSdrPageFromSdrObject())
1059 getSdrModelFromSdrObject().SetChanged();
1063 // tooling for painting a single object to an OutputDevice.
1064 void SdrObject::SingleObjectPainter(OutputDevice
& rOut
) const
1066 sdr::contact::SdrObjectVector aObjectVector
;
1067 aObjectVector
.push_back(const_cast< SdrObject
* >(this));
1069 sdr::contact::ObjectContactOfObjListPainter
aPainter(rOut
, std::move(aObjectVector
), getSdrPageFromSdrObject());
1070 sdr::contact::DisplayInfo aDisplayInfo
;
1072 aPainter
.ProcessDisplay(aDisplayInfo
);
1075 bool SdrObject::LineGeometryUsageIsNecessary() const
1077 drawing::LineStyle eXLS
= GetMergedItem(XATTR_LINESTYLE
).GetValue();
1078 return (eXLS
!= drawing::LineStyle_NONE
);
1081 bool SdrObject::HasLimitedRotation() const
1083 // RotGrfFlyFrame: Default is false, support full rotation
1087 OUString
SdrObject::TakeObjNameSingul() const
1089 OUString
sName(SvxResId(STR_ObjNameSingulNONE
));
1091 OUString
aName(GetName());
1092 if (!aName
.isEmpty())
1093 sName
+= " '" + aName
+ "'";
1097 OUString
SdrObject::TakeObjNamePlural() const
1099 return SvxResId(STR_ObjNamePluralNONE
);
1102 OUString
SdrObject::ImpGetDescriptionStr(TranslateId pStrCacheID
) const
1104 OUString aStr
= SvxResId(pStrCacheID
);
1105 sal_Int32 nPos
= aStr
.indexOf("%1");
1108 // Replace '%1' with the object name.
1109 OUString
aObjName(TakeObjNameSingul());
1110 aStr
= aStr
.replaceAt(nPos
, 2, aObjName
);
1113 nPos
= aStr
.indexOf("%2");
1115 // Replace '%2' with the passed value.
1116 aStr
= aStr
.replaceAt(nPos
, 2, u
"0");
1120 void SdrObject::ImpForcePlusData()
1123 m_pPlusData
.reset( new SdrObjPlusData
);
1126 OUString
SdrObject::GetMetrStr(tools::Long nVal
) const
1128 return getSdrModelFromSdrObject().GetMetricString(nVal
);
1131 basegfx::B2DPolyPolygon
SdrObject::TakeXorPoly() const
1133 basegfx::B2DPolyPolygon aRetval
;
1134 const tools::Rectangle
aR(GetCurrentBoundRect());
1135 aRetval
.append(basegfx::utils::createPolygonFromRect(vcl::unotools::b2DRectangleFromRectangle(aR
)));
1140 basegfx::B2DPolyPolygon
SdrObject::TakeContour() const
1142 basegfx::B2DPolyPolygon aRetval
;
1144 // create cloned object without text, but with drawing::LineStyle_SOLID,
1145 // COL_BLACK as line color and drawing::FillStyle_NONE
1146 rtl::Reference
<SdrObject
> pClone(CloneSdrObject(getSdrModelFromSdrObject()));
1150 const SdrTextObj
* pTextObj
= DynCastSdrTextObj(this);
1154 // no text and no text animation
1155 pClone
->SetMergedItem(SdrTextAniKindItem(SdrTextAniKind::NONE
));
1156 pClone
->SetOutlinerParaObject(std::nullopt
);
1159 const SdrEdgeObj
* pEdgeObj
= dynamic_cast< const SdrEdgeObj
* >(this);
1163 // create connections if connector, will be cleaned up when
1164 // deleting the connector again
1165 SdrObject
* pLeft
= pEdgeObj
->GetConnectedNode(true);
1166 SdrObject
* pRight
= pEdgeObj
->GetConnectedNode(false);
1170 pClone
->ConnectToNode(true, pLeft
);
1175 pClone
->ConnectToNode(false, pRight
);
1179 SfxItemSet
aNewSet(GetObjectItemPool());
1181 // #i101980# ignore LineWidth; that's what the old implementation
1182 // did. With line width, the result may be huge due to fat/thick
1183 // line decompositions
1184 aNewSet
.Put(XLineWidthItem(0));
1186 // solid black lines and no fill
1187 aNewSet
.Put(XLineStyleItem(drawing::LineStyle_SOLID
));
1188 aNewSet
.Put(XLineColorItem(OUString(), COL_BLACK
));
1189 aNewSet
.Put(XFillStyleItem(drawing::FillStyle_NONE
));
1190 pClone
->SetMergedItemSet(aNewSet
);
1192 // get sequence from clone
1193 const sdr::contact::ViewContact
& rVC(pClone
->GetViewContact());
1194 drawinglayer::primitive2d::Primitive2DContainer xSequence
;
1195 rVC
.getViewIndependentPrimitive2DContainer(xSequence
);
1197 if(!xSequence
.empty())
1199 // use neutral ViewInformation
1200 const drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
1202 // create extractor, process and get result (with hairlines as opened polygons)
1203 drawinglayer::processor2d::ContourExtractor2D
aExtractor(aViewInformation2D
, false);
1204 aExtractor
.process(xSequence
);
1205 const basegfx::B2DPolyPolygonVector
& rResult(aExtractor
.getExtractedContour());
1206 const sal_uInt32
nSize(rResult
.size());
1208 // when count is one, it is implied that the object has only its normal
1209 // contour anyways and TakeContour() is to return an empty PolyPolygon
1210 // (see old implementation for historical reasons)
1213 // the topology for contour is correctly a vector of PolyPolygons; for
1214 // historical reasons cut it back to a single tools::PolyPolygon here
1215 for(sal_uInt32
a(0); a
< nSize
; a
++)
1217 aRetval
.append(rResult
[a
]);
1226 sal_uInt32
SdrObject::GetHdlCount() const
1231 void SdrObject::AddToHdlList(SdrHdlList
& rHdlList
) const
1233 const tools::Rectangle
& rR
=GetSnapRect();
1234 for (sal_uInt32 nHdlNum
=0; nHdlNum
<8; ++nHdlNum
)
1236 std::unique_ptr
<SdrHdl
> pH
;
1238 case 0: pH
.reset(new SdrHdl(rR
.TopLeft(), SdrHdlKind::UpperLeft
)); break;
1239 case 1: pH
.reset(new SdrHdl(rR
.TopCenter(), SdrHdlKind::Upper
)); break;
1240 case 2: pH
.reset(new SdrHdl(rR
.TopRight(), SdrHdlKind::UpperRight
)); break;
1241 case 3: pH
.reset(new SdrHdl(rR
.LeftCenter(), SdrHdlKind::Left
)); break;
1242 case 4: pH
.reset(new SdrHdl(rR
.RightCenter(), SdrHdlKind::Right
)); break;
1243 case 5: pH
.reset(new SdrHdl(rR
.BottomLeft(), SdrHdlKind::LowerLeft
)); break;
1244 case 6: pH
.reset(new SdrHdl(rR
.BottomCenter(),SdrHdlKind::Lower
)); break;
1245 case 7: pH
.reset(new SdrHdl(rR
.BottomRight(), SdrHdlKind::LowerRight
)); break;
1247 rHdlList
.AddHdl(std::move(pH
));
1251 void SdrObject::AddToPlusHdlList(SdrHdlList
&, SdrHdl
&) const
1255 void SdrObject::addCropHandles(SdrHdlList
& /*rTarget*/) const
1257 // Default implementation, does nothing. Overloaded in
1258 // SdrGrafObj and SwVirtFlyDrawObj
1261 tools::Rectangle
SdrObject::ImpDragCalcRect(const SdrDragStat
& rDrag
) const
1263 tools::Rectangle
aTmpRect(GetSnapRect());
1264 tools::Rectangle
aRect(aTmpRect
);
1265 const SdrHdl
* pHdl
=rDrag
.GetHdl();
1266 SdrHdlKind eHdl
=pHdl
==nullptr ? SdrHdlKind::Move
: pHdl
->GetKind();
1267 bool bEcke
=(eHdl
==SdrHdlKind::UpperLeft
|| eHdl
==SdrHdlKind::UpperRight
|| eHdl
==SdrHdlKind::LowerLeft
|| eHdl
==SdrHdlKind::LowerRight
);
1268 bool bOrtho
=rDrag
.GetView()!=nullptr && rDrag
.GetView()->IsOrtho();
1269 bool bBigOrtho
=bEcke
&& bOrtho
&& rDrag
.GetView()->IsBigOrtho();
1270 Point
aPos(rDrag
.GetNow());
1271 bool bLft
=(eHdl
==SdrHdlKind::UpperLeft
|| eHdl
==SdrHdlKind::Left
|| eHdl
==SdrHdlKind::LowerLeft
);
1272 bool bRgt
=(eHdl
==SdrHdlKind::UpperRight
|| eHdl
==SdrHdlKind::Right
|| eHdl
==SdrHdlKind::LowerRight
);
1273 bool bTop
=(eHdl
==SdrHdlKind::UpperRight
|| eHdl
==SdrHdlKind::Upper
|| eHdl
==SdrHdlKind::UpperLeft
);
1274 bool bBtm
=(eHdl
==SdrHdlKind::LowerRight
|| eHdl
==SdrHdlKind::Lower
|| eHdl
==SdrHdlKind::LowerLeft
);
1275 if (bLft
) aTmpRect
.SetLeft(aPos
.X() );
1276 if (bRgt
) aTmpRect
.SetRight(aPos
.X() );
1277 if (bTop
) aTmpRect
.SetTop(aPos
.Y() );
1278 if (bBtm
) aTmpRect
.SetBottom(aPos
.Y() );
1279 if (bOrtho
) { // Ortho
1280 tools::Long nWdt0
=aRect
.Right() -aRect
.Left();
1281 tools::Long nHgt0
=aRect
.Bottom()-aRect
.Top();
1282 tools::Long nXMul
=aTmpRect
.Right() -aTmpRect
.Left();
1283 tools::Long nYMul
=aTmpRect
.Bottom()-aTmpRect
.Top();
1284 tools::Long nXDiv
=nWdt0
;
1285 tools::Long nYDiv
=nHgt0
;
1286 bool bXNeg
=(nXMul
<0)!=(nXDiv
<0);
1287 bool bYNeg
=(nYMul
<0)!=(nYDiv
<0);
1288 nXMul
=std::abs(nXMul
);
1289 nYMul
=std::abs(nYMul
);
1290 nXDiv
=std::abs(nXDiv
);
1291 nYDiv
=std::abs(nYDiv
);
1292 Fraction
aXFact(nXMul
,nXDiv
); // fractions for canceling
1293 Fraction
aYFact(nYMul
,nYDiv
); // and for comparing
1294 nXMul
=aXFact
.GetNumerator();
1295 nYMul
=aYFact
.GetNumerator();
1296 nXDiv
=aXFact
.GetDenominator();
1297 nYDiv
=aYFact
.GetDenominator();
1298 if (bEcke
) { // corner point handles
1299 bool bUseX
=(aXFact
<aYFact
) != bBigOrtho
;
1301 tools::Long nNeed
=tools::Long(BigInt(nHgt0
)*BigInt(nXMul
)/BigInt(nXDiv
));
1302 if (bYNeg
) nNeed
=-nNeed
;
1303 if (bTop
) aTmpRect
.SetTop(aTmpRect
.Bottom()-nNeed
);
1304 if (bBtm
) aTmpRect
.SetBottom(aTmpRect
.Top()+nNeed
);
1306 tools::Long nNeed
=tools::Long(BigInt(nWdt0
)*BigInt(nYMul
)/BigInt(nYDiv
));
1307 if (bXNeg
) nNeed
=-nNeed
;
1308 if (bLft
) aTmpRect
.SetLeft(aTmpRect
.Right()-nNeed
);
1309 if (bRgt
) aTmpRect
.SetRight(aTmpRect
.Left()+nNeed
);
1311 } else { // apex handles
1312 if ((bLft
|| bRgt
) && nXDiv
!=0) {
1313 tools::Long nHgt0b
=aRect
.Bottom()-aRect
.Top();
1314 tools::Long nNeed
=tools::Long(BigInt(nHgt0b
)*BigInt(nXMul
)/BigInt(nXDiv
));
1315 aTmpRect
.AdjustTop( -((nNeed
-nHgt0b
)/2) );
1316 aTmpRect
.SetBottom(aTmpRect
.Top()+nNeed
);
1318 if ((bTop
|| bBtm
) && nYDiv
!=0) {
1319 tools::Long nWdt0b
=aRect
.Right()-aRect
.Left();
1320 tools::Long nNeed
=tools::Long(BigInt(nWdt0b
)*BigInt(nYMul
)/BigInt(nYDiv
));
1321 aTmpRect
.AdjustLeft( -((nNeed
-nWdt0b
)/2) );
1322 aTmpRect
.SetRight(aTmpRect
.Left()+nNeed
);
1326 aTmpRect
.Normalize();
1331 bool SdrObject::hasSpecialDrag() const
1336 bool SdrObject::supportsFullDrag() const
1341 rtl::Reference
<SdrObject
> SdrObject::getFullDragClone() const
1343 // default uses simple clone
1344 return CloneSdrObject(getSdrModelFromSdrObject());
1347 bool SdrObject::beginSpecialDrag(SdrDragStat
& rDrag
) const
1349 const SdrHdl
* pHdl
= rDrag
.GetHdl();
1351 SdrHdlKind eHdl
= (pHdl
== nullptr) ? SdrHdlKind::Move
: pHdl
->GetKind();
1353 return eHdl
==SdrHdlKind::UpperLeft
|| eHdl
==SdrHdlKind::Upper
|| eHdl
==SdrHdlKind::UpperRight
||
1354 eHdl
==SdrHdlKind::Left
|| eHdl
==SdrHdlKind::Right
|| eHdl
==SdrHdlKind::LowerLeft
||
1355 eHdl
==SdrHdlKind::Lower
|| eHdl
==SdrHdlKind::LowerRight
;
1358 bool SdrObject::applySpecialDrag(SdrDragStat
& rDrag
)
1360 tools::Rectangle
aNewRect(ImpDragCalcRect(rDrag
));
1362 if(aNewRect
!= GetSnapRect())
1364 NbcSetSnapRect(aNewRect
);
1370 OUString
SdrObject::getSpecialDragComment(const SdrDragStat
& /*rDrag*/) const
1375 basegfx::B2DPolyPolygon
SdrObject::getSpecialDragPoly(const SdrDragStat
& /*rDrag*/) const
1377 // default has nothing to add
1378 return basegfx::B2DPolyPolygon();
1383 bool SdrObject::BegCreate(SdrDragStat
& rStat
)
1385 rStat
.SetOrtho4Possible();
1386 tools::Rectangle
aRect1(rStat
.GetStart(), rStat
.GetNow());
1388 rStat
.SetActionRect(aRect1
);
1389 setOutRectangle(aRect1
);
1393 bool SdrObject::MovCreate(SdrDragStat
& rStat
)
1395 tools::Rectangle aRectangle
;
1396 rStat
.TakeCreateRect(aRectangle
);
1397 rStat
.SetActionRect(aRectangle
);
1398 aRectangle
.Normalize();
1399 setOutRectangle(aRectangle
);
1403 bool SdrObject::EndCreate(SdrDragStat
& rStat
, SdrCreateCmd eCmd
)
1405 tools::Rectangle aRectangle
;
1406 rStat
.TakeCreateRect(aRectangle
);
1407 aRectangle
.Normalize();
1408 setOutRectangle(aRectangle
);
1410 return (eCmd
==SdrCreateCmd::ForceEnd
|| rStat
.GetPointCount()>=2);
1413 void SdrObject::BrkCreate(SdrDragStat
& /*rStat*/)
1417 bool SdrObject::BckCreate(SdrDragStat
& /*rStat*/)
1422 basegfx::B2DPolyPolygon
SdrObject::TakeCreatePoly(const SdrDragStat
& rDrag
) const
1424 tools::Rectangle aRect1
;
1425 rDrag
.TakeCreateRect(aRect1
);
1428 basegfx::B2DPolyPolygon aRetval
;
1429 aRetval
.append(basegfx::utils::createPolygonFromRect(vcl::unotools::b2DRectangleFromRectangle(aRect1
)));
1433 PointerStyle
SdrObject::GetCreatePointer() const
1435 return PointerStyle::Cross
;
1439 void SdrObject::NbcMove(const Size
& rSize
)
1441 moveOutRectangle(rSize
.Width(), rSize
.Height());
1442 SetBoundAndSnapRectsDirty();
1445 void SdrObject::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
1447 bool bXMirr
=(xFact
.GetNumerator()<0) != (xFact
.GetDenominator()<0);
1448 bool bYMirr
=(yFact
.GetNumerator()<0) != (yFact
.GetDenominator()<0);
1449 if (bXMirr
|| bYMirr
) {
1450 Point
aRef1(GetSnapRect().Center());
1454 NbcMirrorGluePoints(aRef1
,aRef2
);
1459 NbcMirrorGluePoints(aRef1
,aRef2
);
1462 auto aRectangle
= getOutRectangle();
1463 ResizeRect(aRectangle
, rRef
, xFact
, yFact
);
1464 setOutRectangle(aRectangle
);
1466 SetBoundAndSnapRectsDirty();
1469 void SdrObject::NbcRotate(const Point
& rRef
, Degree100 nAngle
)
1473 double a
= toRadians(nAngle
);
1474 NbcRotate( rRef
, nAngle
, sin( a
), cos( a
) );
1480 tools::Rectangle
lclMirrorRectangle(tools::Rectangle
const& rRectangle
, Point
const& rRef1
, Point
const& rRef2
)
1482 tools::Rectangle
aRectangle(rRectangle
);
1483 aRectangle
.Move(-rRef1
.X(),-rRef1
.Y());
1484 tools::Rectangle
R(aRectangle
);
1485 tools::Long dx
=rRef2
.X()-rRef1
.X();
1486 tools::Long dy
=rRef2
.Y()-rRef1
.Y();
1487 if (dx
==0) { // vertical axis
1488 aRectangle
.SetLeft(-R
.Right() );
1489 aRectangle
.SetRight(-R
.Left() );
1490 } else if (dy
==0) { // horizontal axis
1491 aRectangle
.SetTop(-R
.Bottom() );
1492 aRectangle
.SetBottom(-R
.Top() );
1493 } else if (dx
==dy
) { // 45deg axis
1494 aRectangle
.SetLeft(R
.Top() );
1495 aRectangle
.SetRight(R
.Bottom() );
1496 aRectangle
.SetTop(R
.Left() );
1497 aRectangle
.SetBottom(R
.Right() );
1498 } else if (dx
==-dy
) { // 45deg axis
1499 aRectangle
.SetLeft(-R
.Bottom() );
1500 aRectangle
.SetRight(-R
.Top() );
1501 aRectangle
.SetTop(-R
.Right() );
1502 aRectangle
.SetBottom(-R
.Left() );
1504 aRectangle
.Move(rRef1
.X(),rRef1
.Y());
1505 aRectangle
.Normalize(); // just in case
1509 } // end anonymous namespace
1511 void SdrObject::NbcMirror(const Point
& rRef1
, const Point
& rRef2
)
1513 SetGlueReallyAbsolute(true);
1515 tools::Rectangle aRectangle
= getOutRectangle();
1516 aRectangle
= lclMirrorRectangle(aRectangle
, rRef1
, rRef2
);
1517 setOutRectangle(aRectangle
);
1519 SetBoundAndSnapRectsDirty();
1520 NbcMirrorGluePoints(rRef1
,rRef2
);
1521 SetGlueReallyAbsolute(false);
1524 void SdrObject::NbcShear(const Point
& rRef
, Degree100
/*nAngle*/, double tn
, bool bVShear
)
1526 SetGlueReallyAbsolute(true);
1527 NbcShearGluePoints(rRef
,tn
,bVShear
);
1528 SetGlueReallyAbsolute(false);
1531 void SdrObject::Move(const Size
& rSiz
)
1533 if (rSiz
.Width()!=0 || rSiz
.Height()!=0) {
1534 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1537 BroadcastObjectChange();
1538 SendUserCall(SdrUserCallType::MoveOnly
,aBoundRect0
);
1542 void SdrObject::NbcCrop(const basegfx::B2DPoint
& /*aRef*/, double /*fxFact*/, double /*fyFact*/)
1544 // Default: does nothing. Real behaviour in SwVirtFlyDrawObj and SdrDragCrop::EndSdrDrag.
1545 // Where SwVirtFlyDrawObj is the only real user of it to do something local
1548 void SdrObject::Resize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
, bool bUnsetRelative
)
1550 if (xFact
.GetNumerator() == xFact
.GetDenominator() && yFact
.GetNumerator() == yFact
.GetDenominator())
1555 mpImpl
->mnRelativeWidth
.reset();
1556 mpImpl
->meRelativeWidthRelation
= text::RelOrientation::PAGE_FRAME
;
1557 mpImpl
->meRelativeHeightRelation
= text::RelOrientation::PAGE_FRAME
;
1558 mpImpl
->mnRelativeHeight
.reset();
1560 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1561 NbcResize(rRef
,xFact
,yFact
);
1563 BroadcastObjectChange();
1564 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1567 void SdrObject::Crop(const basegfx::B2DPoint
& rRef
, double fxFact
, double fyFact
)
1569 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1570 NbcCrop(rRef
, fxFact
, fyFact
);
1572 BroadcastObjectChange();
1573 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1576 void SdrObject::Rotate(const Point
& rRef
, Degree100 nAngle
, double sn
, double cs
)
1579 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1580 NbcRotate(rRef
,nAngle
,sn
,cs
);
1582 BroadcastObjectChange();
1583 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1587 void SdrObject::Mirror(const Point
& rRef1
, const Point
& rRef2
)
1589 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1590 NbcMirror(rRef1
,rRef2
);
1592 BroadcastObjectChange();
1593 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1596 void SdrObject::Shear(const Point
& rRef
, Degree100 nAngle
, double tn
, bool bVShear
)
1599 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1600 NbcShear(rRef
,nAngle
,tn
,bVShear
);
1602 BroadcastObjectChange();
1603 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1607 void SdrObject::NbcSetRelativePos(const Point
& rPnt
)
1609 Point
aRelPos0(GetSnapRect().TopLeft()-m_aAnchor
);
1610 Size
aSiz(rPnt
.X()-aRelPos0
.X(),rPnt
.Y()-aRelPos0
.Y());
1611 NbcMove(aSiz
); // This also calls SetRectsDirty()
1614 void SdrObject::SetRelativePos(const Point
& rPnt
)
1616 if (rPnt
!=GetRelativePos()) {
1617 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1618 NbcSetRelativePos(rPnt
);
1620 BroadcastObjectChange();
1621 SendUserCall(SdrUserCallType::MoveOnly
,aBoundRect0
);
1625 Point
SdrObject::GetRelativePos() const
1627 return GetSnapRect().TopLeft()-m_aAnchor
;
1630 void SdrObject::ImpSetAnchorPos(const Point
& rPnt
)
1635 void SdrObject::NbcSetAnchorPos(const Point
& rPnt
)
1637 Size
aSiz(rPnt
.X()-m_aAnchor
.X(),rPnt
.Y()-m_aAnchor
.Y());
1639 NbcMove(aSiz
); // This also calls SetRectsDirty()
1642 void SdrObject::SetAnchorPos(const Point
& rPnt
)
1644 if (rPnt
!=m_aAnchor
) {
1645 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1646 NbcSetAnchorPos(rPnt
);
1648 BroadcastObjectChange();
1649 SendUserCall(SdrUserCallType::MoveOnly
,aBoundRect0
);
1653 const Point
& SdrObject::GetAnchorPos() const
1658 void SdrObject::RecalcSnapRect()
1662 const tools::Rectangle
& SdrObject::GetSnapRect() const
1664 return getOutRectangle();
1667 void SdrObject::NbcSetSnapRect(const tools::Rectangle
& rRect
)
1669 setOutRectangle(rRect
);
1672 const tools::Rectangle
& SdrObject::GetLogicRect() const
1674 return GetSnapRect();
1677 void SdrObject::NbcSetLogicRect(const tools::Rectangle
& rRect
)
1679 NbcSetSnapRect(rRect
);
1682 void SdrObject::AdjustToMaxRect( const tools::Rectangle
& rMaxRect
, bool /* bShrinkOnly = false */ )
1684 SetLogicRect( rMaxRect
);
1687 void SdrObject::SetSnapRect(const tools::Rectangle
& rRect
)
1689 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1690 NbcSetSnapRect(rRect
);
1692 BroadcastObjectChange();
1693 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1696 void SdrObject::SetLogicRect(const tools::Rectangle
& rRect
)
1698 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1699 NbcSetLogicRect(rRect
);
1701 BroadcastObjectChange();
1702 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1705 Degree100
SdrObject::GetRotateAngle() const
1710 Degree100
SdrObject::GetShearAngle(bool /*bVertical*/) const
1715 sal_uInt32
SdrObject::GetSnapPointCount() const
1717 return GetPointCount();
1720 Point
SdrObject::GetSnapPoint(sal_uInt32 i
) const
1725 bool SdrObject::IsPolyObj() const
1730 sal_uInt32
SdrObject::GetPointCount() const
1735 Point
SdrObject::GetPoint(sal_uInt32
/*i*/) const
1740 void SdrObject::SetPoint(const Point
& rPnt
, sal_uInt32 i
)
1742 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1743 NbcSetPoint(rPnt
, i
);
1745 BroadcastObjectChange();
1746 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1749 void SdrObject::NbcSetPoint(const Point
& /*rPnt*/, sal_uInt32
/*i*/)
1753 bool SdrObject::HasTextEdit() const
1758 bool SdrObject::Equals(const SdrObject
& rOtherObj
) const
1760 return (m_aAnchor
.X() == rOtherObj
.m_aAnchor
.X() && m_aAnchor
.Y() == rOtherObj
.m_aAnchor
.Y() &&
1761 m_nOrdNum
== rOtherObj
.m_nOrdNum
&& mnNavigationPosition
== rOtherObj
.mnNavigationPosition
&&
1762 mbSupportTextIndentingOnLineWidthChange
== rOtherObj
.mbSupportTextIndentingOnLineWidthChange
&&
1763 mbLineIsOutsideGeometry
== rOtherObj
.mbLineIsOutsideGeometry
&& m_bMarkProt
== rOtherObj
.m_bMarkProt
&&
1764 m_bIs3DObj
== rOtherObj
.m_bIs3DObj
&& m_bIsEdge
== rOtherObj
.m_bIsEdge
&& m_bClosedObj
== rOtherObj
.m_bClosedObj
&&
1765 m_bNotVisibleAsMaster
== rOtherObj
.m_bNotVisibleAsMaster
&& m_bEmptyPresObj
== rOtherObj
.m_bEmptyPresObj
&&
1766 mbVisible
== rOtherObj
.mbVisible
&& m_bNoPrint
== rOtherObj
.m_bNoPrint
&& m_bSizProt
== rOtherObj
.m_bSizProt
&&
1767 m_bMovProt
== rOtherObj
.m_bMovProt
&& m_bVirtObj
== rOtherObj
.m_bVirtObj
&&
1768 mnLayerID
== rOtherObj
.mnLayerID
&& GetMergedItemSet().Equals(rOtherObj
.GetMergedItemSet(), false) );
1771 void SdrObject::dumpAsXml(xmlTextWriterPtr pWriter
) const
1773 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SdrObject"));
1774 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
1775 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
1776 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("name"), "%s", BAD_CAST(GetName().toUtf8().getStr()));
1777 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("title"), "%s", BAD_CAST(GetTitle().toUtf8().getStr()));
1778 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("description"), "%s", BAD_CAST(GetDescription().toUtf8().getStr()));
1779 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("nOrdNum"), "%" SAL_PRIuUINT32
, GetOrdNumDirect());
1780 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("aOutRect"), BAD_CAST(getOutRectangle().toString().getStr()));
1784 m_pGrabBagItem
->dumpAsXml(pWriter
);
1789 mpProperties
->dumpAsXml(pWriter
);
1792 if (const OutlinerParaObject
* pOutliner
= GetOutlinerParaObject())
1793 pOutliner
->dumpAsXml(pWriter
);
1795 (void)xmlTextWriterEndElement(pWriter
);
1798 void SdrObject::SetOutlinerParaObject(std::optional
<OutlinerParaObject
> pTextObject
)
1800 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1801 NbcSetOutlinerParaObject(std::move(pTextObject
));
1803 BroadcastObjectChange();
1804 if (GetCurrentBoundRect()!=aBoundRect0
) {
1805 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1808 if (!getSdrModelFromSdrObject().IsUndoEnabled())
1811 // Don't do this during import.
1812 SdrObject
* pTopGroupObj
= nullptr;
1813 if (getParentSdrObjectFromSdrObject())
1815 pTopGroupObj
= getParentSdrObjectFromSdrObject();
1816 while (pTopGroupObj
->getParentSdrObjectFromSdrObject())
1818 pTopGroupObj
= pTopGroupObj
->getParentSdrObjectFromSdrObject();
1823 // A shape was modified, which is in a group shape. Empty the group shape's grab-bag,
1824 // which potentially contains the old text of the shapes in case of diagrams.
1825 pTopGroupObj
->SetGrabBagItem(uno::Any(uno::Sequence
<beans::PropertyValue
>()));
1829 void SdrObject::NbcSetOutlinerParaObject(std::optional
<OutlinerParaObject
> /*pTextObject*/)
1833 OutlinerParaObject
* SdrObject::GetOutlinerParaObject() const
1838 void SdrObject::NbcReformatText()
1842 void SdrObject::BurnInStyleSheetAttributes()
1844 GetProperties().ForceStyleToHardAttributes();
1847 bool SdrObject::HasMacro() const
1852 SdrObject
* SdrObject::CheckMacroHit(const SdrObjMacroHitRec
& rRec
) const
1856 return SdrObjectPrimitiveHit(*this, rRec
.aPos
, {static_cast<double>(rRec
.nTol
), static_cast<double>(rRec
.nTol
)}, *rRec
.pPageView
, rRec
.pVisiLayer
, false);
1862 PointerStyle
SdrObject::GetMacroPointer(const SdrObjMacroHitRec
&) const
1864 return PointerStyle::RefHand
;
1867 void SdrObject::PaintMacro(OutputDevice
& rOut
, const tools::Rectangle
& , const SdrObjMacroHitRec
& ) const
1869 const RasterOp
eRop(rOut
.GetRasterOp());
1870 const basegfx::B2DPolyPolygon
aPolyPolygon(TakeXorPoly());
1872 rOut
.SetLineColor(COL_BLACK
);
1873 rOut
.SetFillColor();
1874 rOut
.SetRasterOp(RasterOp::Invert
);
1876 for(auto const& rPolygon
: aPolyPolygon
)
1878 rOut
.DrawPolyLine(rPolygon
);
1881 rOut
.SetRasterOp(eRop
);
1884 bool SdrObject::DoMacro(const SdrObjMacroHitRec
&)
1889 bool SdrObject::IsMacroHit(const SdrObjMacroHitRec
& rRec
) const
1891 return CheckMacroHit(rRec
) != nullptr;
1895 std::unique_ptr
<SdrObjGeoData
> SdrObject::NewGeoData() const
1897 return std::make_unique
<SdrObjGeoData
>();
1900 void SdrObject::SaveGeoData(SdrObjGeoData
& rGeo
) const
1902 rGeo
.aBoundRect
=GetCurrentBoundRect();
1903 rGeo
.aAnchor
=m_aAnchor
;
1904 rGeo
.bMovProt
=m_bMovProt
;
1905 rGeo
.bSizProt
=m_bSizProt
;
1906 rGeo
.bNoPrint
=m_bNoPrint
;
1907 rGeo
.mbVisible
=mbVisible
;
1908 rGeo
.bClosedObj
=m_bClosedObj
;
1909 rGeo
.mnLayerID
= mnLayerID
;
1911 // user-defined gluepoints
1912 if (m_pPlusData
!=nullptr && m_pPlusData
->pGluePoints
!=nullptr) {
1913 if (rGeo
.pGPL
!=nullptr) {
1914 *rGeo
.pGPL
=*m_pPlusData
->pGluePoints
;
1916 rGeo
.pGPL
.reset( new SdrGluePointList(*m_pPlusData
->pGluePoints
) );
1923 void SdrObject::RestoreGeoData(const SdrObjGeoData
& rGeo
)
1925 SetBoundAndSnapRectsDirty();
1926 setOutRectangle(rGeo
.aBoundRect
);
1927 m_aAnchor
=rGeo
.aAnchor
;
1928 m_bMovProt
=rGeo
.bMovProt
;
1929 m_bSizProt
=rGeo
.bSizProt
;
1930 m_bNoPrint
=rGeo
.bNoPrint
;
1931 mbVisible
=rGeo
.mbVisible
;
1932 m_bClosedObj
=rGeo
.bClosedObj
;
1933 mnLayerID
= rGeo
.mnLayerID
;
1935 // user-defined gluepoints
1936 if (rGeo
.pGPL
!=nullptr) {
1938 if (m_pPlusData
->pGluePoints
!=nullptr) {
1939 *m_pPlusData
->pGluePoints
=*rGeo
.pGPL
;
1941 m_pPlusData
->pGluePoints
.reset(new SdrGluePointList(*rGeo
.pGPL
));
1944 if (m_pPlusData
!=nullptr && m_pPlusData
->pGluePoints
!=nullptr) {
1945 m_pPlusData
->pGluePoints
.reset();
1950 std::unique_ptr
<SdrObjGeoData
> SdrObject::GetGeoData() const
1952 std::unique_ptr
<SdrObjGeoData
> pGeo
= NewGeoData();
1957 void SdrObject::SetGeoData(const SdrObjGeoData
& rGeo
)
1959 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
1960 RestoreGeoData(rGeo
);
1962 BroadcastObjectChange();
1963 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1969 const SfxItemSet
& SdrObject::GetObjectItemSet() const
1971 return GetProperties().GetObjectItemSet();
1974 const SfxItemSet
& SdrObject::GetMergedItemSet() const
1976 return GetProperties().GetMergedItemSet();
1979 void SdrObject::SetObjectItem(const SfxPoolItem
& rItem
)
1981 GetProperties().SetObjectItem(rItem
);
1984 void SdrObject::SetMergedItem(const SfxPoolItem
& rItem
)
1986 GetProperties().SetMergedItem(rItem
);
1989 void SdrObject::ClearMergedItem(const sal_uInt16 nWhich
)
1991 GetProperties().ClearMergedItem(nWhich
);
1994 void SdrObject::SetObjectItemSet(const SfxItemSet
& rSet
)
1996 GetProperties().SetObjectItemSet(rSet
);
1999 void SdrObject::SetMergedItemSet(const SfxItemSet
& rSet
, bool bClearAllItems
)
2001 GetProperties().SetMergedItemSet(rSet
, bClearAllItems
);
2004 const SfxPoolItem
& SdrObject::GetObjectItem(const sal_uInt16 nWhich
) const
2006 return GetObjectItemSet().Get(nWhich
);
2009 const SfxPoolItem
& SdrObject::GetMergedItem(const sal_uInt16 nWhich
) const
2011 return GetMergedItemSet().Get(nWhich
);
2014 void SdrObject::SetMergedItemSetAndBroadcast(const SfxItemSet
& rSet
, bool bClearAllItems
)
2016 GetProperties().SetMergedItemSetAndBroadcast(rSet
, bClearAllItems
);
2019 void SdrObject::ApplyNotPersistAttr(const SfxItemSet
& rAttr
)
2021 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
2022 NbcApplyNotPersistAttr(rAttr
);
2024 BroadcastObjectChange();
2025 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
2028 void SdrObject::NbcApplyNotPersistAttr(const SfxItemSet
& rAttr
)
2030 const tools::Rectangle
& rSnap
=GetSnapRect();
2031 const tools::Rectangle
& rLogic
=GetLogicRect();
2032 Point
aRef1(rSnap
.Center());
2034 if (const SdrTransformRef1XItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_TRANSFORMREF1X
))
2036 aRef1
.setX(pPoolItem
->GetValue() );
2038 if (const SdrTransformRef1YItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_TRANSFORMREF1Y
))
2040 aRef1
.setY(pPoolItem
->GetValue() );
2043 tools::Rectangle
aNewSnap(rSnap
);
2044 if (const SdrMoveXItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_MOVEX
))
2046 tools::Long n
= pPoolItem
->GetValue();
2049 if (const SdrMoveYItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_MOVEY
))
2051 tools::Long n
= pPoolItem
->GetValue();
2054 if (const SdrOnePositionXItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_ONEPOSITIONX
))
2056 tools::Long n
= pPoolItem
->GetValue();
2057 aNewSnap
.Move(n
-aNewSnap
.Left(),0);
2059 if (const SdrOnePositionYItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_ONEPOSITIONY
))
2061 tools::Long n
= pPoolItem
->GetValue();
2062 aNewSnap
.Move(0,n
-aNewSnap
.Top());
2064 if (const SdrOneSizeWidthItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_ONESIZEWIDTH
))
2066 tools::Long n
= pPoolItem
->GetValue();
2067 aNewSnap
.SetRight(aNewSnap
.Left()+n
);
2069 if (const SdrOneSizeHeightItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_ONESIZEHEIGHT
))
2071 tools::Long n
= pPoolItem
->GetValue();
2072 aNewSnap
.SetBottom(aNewSnap
.Top()+n
);
2074 if (aNewSnap
!=rSnap
) {
2075 if (aNewSnap
.GetSize()==rSnap
.GetSize()) {
2076 NbcMove(Size(aNewSnap
.Left()-rSnap
.Left(),aNewSnap
.Top()-rSnap
.Top()));
2078 NbcSetSnapRect(aNewSnap
);
2082 if (const SdrShearAngleItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_SHEARANGLE
))
2084 Degree100 n
= pPoolItem
->GetValue();
2087 double nTan
= tan(toRadians(n
));
2088 NbcShear(aRef1
,n
,nTan
,false);
2091 if (const SdrAngleItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_ROTATEANGLE
))
2093 Degree100 n
= pPoolItem
->GetValue();
2094 n
-=GetRotateAngle();
2099 if (const SdrRotateOneItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_ROTATEONE
))
2101 Degree100 n
= pPoolItem
->GetValue();
2104 if (const SdrHorzShearOneItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_HORZSHEARONE
))
2106 Degree100 n
= pPoolItem
->GetValue();
2107 double nTan
= tan(toRadians(n
));
2108 NbcShear(aRef1
,n
,nTan
,false);
2110 if (const SdrVertShearOneItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_VERTSHEARONE
))
2112 Degree100 n
= pPoolItem
->GetValue();
2113 double nTan
= tan(toRadians(n
));
2114 NbcShear(aRef1
,n
,nTan
,true);
2117 if (const SdrYesNoItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_OBJMOVEPROTECT
))
2119 bool b
= pPoolItem
->GetValue();
2122 if (const SdrYesNoItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_OBJSIZEPROTECT
))
2124 bool b
= pPoolItem
->GetValue();
2125 SetResizeProtect(b
);
2128 /* move protect always sets size protect */
2129 if( IsMoveProtect() )
2130 SetResizeProtect( true );
2132 if (const SdrObjPrintableItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_OBJPRINTABLE
))
2134 bool b
= pPoolItem
->GetValue();
2138 if (const SdrObjVisibleItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_OBJVISIBLE
))
2140 bool b
= pPoolItem
->GetValue();
2144 SdrLayerID nLayer
=SDRLAYER_NOTFOUND
;
2145 if (const SdrLayerIdItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_LAYERID
))
2147 nLayer
= pPoolItem
->GetValue();
2149 if (const SdrLayerNameItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_LAYERNAME
))
2151 OUString aLayerName
= pPoolItem
->GetValue();
2152 const SdrLayerAdmin
& rLayAd(nullptr != getSdrPageFromSdrObject()
2153 ? getSdrPageFromSdrObject()->GetLayerAdmin()
2154 : getSdrModelFromSdrObject().GetLayerAdmin());
2155 const SdrLayer
* pLayer
= rLayAd
.GetLayer(aLayerName
);
2157 if(nullptr != pLayer
)
2159 nLayer
=pLayer
->GetID();
2162 if (nLayer
!=SDRLAYER_NOTFOUND
) {
2163 NbcSetLayer(nLayer
);
2166 if (const SfxStringItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_OBJECTNAME
))
2168 OUString aName
= pPoolItem
->GetValue();
2171 tools::Rectangle
aNewLogic(rLogic
);
2172 if (const SdrLogicSizeWidthItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_LOGICSIZEWIDTH
))
2174 tools::Long n
= pPoolItem
->GetValue();
2175 aNewLogic
.SetRight(aNewLogic
.Left()+n
);
2177 if (const SdrLogicSizeHeightItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_LOGICSIZEHEIGHT
))
2179 tools::Long n
= pPoolItem
->GetValue();
2180 aNewLogic
.SetBottom(aNewLogic
.Top()+n
);
2182 if (aNewLogic
!=rLogic
) {
2183 NbcSetLogicRect(aNewLogic
);
2185 Fraction
aResizeX(1,1);
2186 Fraction
aResizeY(1,1);
2187 if (const SdrResizeXOneItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_RESIZEXONE
))
2189 aResizeX
*= pPoolItem
->GetValue();
2191 if (const SdrResizeYOneItem
*pPoolItem
= rAttr
.GetItemIfSet(SDRATTR_RESIZEYONE
))
2193 aResizeY
*= pPoolItem
->GetValue();
2195 if (aResizeX
!=Fraction(1,1) || aResizeY
!=Fraction(1,1)) {
2196 NbcResize(aRef1
,aResizeX
,aResizeY
);
2200 void SdrObject::TakeNotPersistAttr(SfxItemSet
& rAttr
) const
2202 const tools::Rectangle
& rSnap
=GetSnapRect();
2203 const tools::Rectangle
& rLogic
=GetLogicRect();
2204 rAttr
.Put(SdrYesNoItem(SDRATTR_OBJMOVEPROTECT
, IsMoveProtect()));
2205 rAttr
.Put(SdrYesNoItem(SDRATTR_OBJSIZEPROTECT
, IsResizeProtect()));
2206 rAttr
.Put(SdrObjPrintableItem(IsPrintable()));
2207 rAttr
.Put(SdrObjVisibleItem(IsVisible()));
2208 rAttr
.Put(SdrAngleItem(SDRATTR_ROTATEANGLE
, GetRotateAngle()));
2209 rAttr
.Put(SdrShearAngleItem(GetShearAngle()));
2210 rAttr
.Put(SdrOneSizeWidthItem(rSnap
.GetWidth()-1));
2211 rAttr
.Put(SdrOneSizeHeightItem(rSnap
.GetHeight()-1));
2212 rAttr
.Put(SdrOnePositionXItem(rSnap
.Left()));
2213 rAttr
.Put(SdrOnePositionYItem(rSnap
.Top()));
2214 if (rLogic
.GetWidth()!=rSnap
.GetWidth()) {
2215 rAttr
.Put(SdrLogicSizeWidthItem(rLogic
.GetWidth()-1));
2217 if (rLogic
.GetHeight()!=rSnap
.GetHeight()) {
2218 rAttr
.Put(SdrLogicSizeHeightItem(rLogic
.GetHeight()-1));
2220 OUString
aName(GetName());
2222 if (!aName
.isEmpty())
2224 rAttr
.Put(SfxStringItem(SDRATTR_OBJECTNAME
, aName
));
2227 rAttr
.Put(SdrLayerIdItem(GetLayer()));
2228 const SdrLayerAdmin
& rLayAd(nullptr != getSdrPageFromSdrObject()
2229 ? getSdrPageFromSdrObject()->GetLayerAdmin()
2230 : getSdrModelFromSdrObject().GetLayerAdmin());
2231 const SdrLayer
* pLayer
= rLayAd
.GetLayerPerID(GetLayer());
2232 if(nullptr != pLayer
)
2234 rAttr
.Put(SdrLayerNameItem(pLayer
->GetName()));
2236 Point
aRef1(rSnap
.Center());
2237 Point
aRef2(aRef1
); aRef2
.AdjustY( 1 );
2238 rAttr
.Put(SdrTransformRef1XItem(aRef1
.X()));
2239 rAttr
.Put(SdrTransformRef1YItem(aRef1
.Y()));
2240 rAttr
.Put(SdrTransformRef2XItem(aRef2
.X()));
2241 rAttr
.Put(SdrTransformRef2YItem(aRef2
.Y()));
2244 SfxStyleSheet
* SdrObject::GetStyleSheet() const
2246 return GetProperties().GetStyleSheet();
2249 void SdrObject::SetStyleSheet(SfxStyleSheet
* pNewStyleSheet
, bool bDontRemoveHardAttr
)
2251 tools::Rectangle aBoundRect0
;
2254 aBoundRect0
= GetLastBoundRect();
2256 InternalSetStyleSheet(pNewStyleSheet
, bDontRemoveHardAttr
, true);
2258 BroadcastObjectChange();
2259 SendUserCall(SdrUserCallType::ChangeAttr
, aBoundRect0
);
2262 void SdrObject::NbcSetStyleSheet(SfxStyleSheet
* pNewStyleSheet
, bool bDontRemoveHardAttr
)
2264 InternalSetStyleSheet(pNewStyleSheet
, bDontRemoveHardAttr
, false);
2267 void SdrObject::InternalSetStyleSheet(SfxStyleSheet
* pNewStyleSheet
, bool bDontRemoveHardAttr
, bool bBroadcast
)
2269 GetProperties().SetStyleSheet(pNewStyleSheet
, bDontRemoveHardAttr
, bBroadcast
);
2272 // Broadcasting while setting attributes is managed by the AttrObj.
2275 SdrGluePoint
SdrObject::GetVertexGluePoint(sal_uInt16 nPosNum
) const
2277 // #i41936# Use SnapRect for default GluePoints
2278 const tools::Rectangle
aR(GetSnapRect());
2283 case 0 : aPt
= aR
.TopCenter(); break;
2284 case 1 : aPt
= aR
.RightCenter(); break;
2285 case 2 : aPt
= aR
.BottomCenter(); break;
2286 case 3 : aPt
= aR
.LeftCenter(); break;
2290 SdrGluePoint
aGP(aPt
);
2291 aGP
.SetPercent(false);
2296 SdrGluePoint
SdrObject::GetCornerGluePoint(sal_uInt16 nPosNum
) const
2298 tools::Rectangle
aR(GetCurrentBoundRect());
2301 case 0 : aPt
=aR
.TopLeft(); break;
2302 case 1 : aPt
=aR
.TopRight(); break;
2303 case 2 : aPt
=aR
.BottomRight(); break;
2304 case 3 : aPt
=aR
.BottomLeft(); break;
2306 aPt
-=GetSnapRect().Center();
2307 SdrGluePoint
aGP(aPt
);
2308 aGP
.SetPercent(false);
2312 const SdrGluePointList
* SdrObject::GetGluePointList() const
2314 if (m_pPlusData
!=nullptr) return m_pPlusData
->pGluePoints
.get();
2319 SdrGluePointList
* SdrObject::ForceGluePointList()
2322 if (m_pPlusData
->pGluePoints
==nullptr) {
2323 m_pPlusData
->pGluePoints
.reset(new SdrGluePointList
);
2325 return m_pPlusData
->pGluePoints
.get();
2328 void SdrObject::SetGlueReallyAbsolute(bool bOn
)
2330 // First a const call to see whether there are any gluepoints.
2331 // Force const call!
2332 if (GetGluePointList()!=nullptr) {
2333 SdrGluePointList
* pGPL
=ForceGluePointList();
2334 pGPL
->SetReallyAbsolute(bOn
,*this);
2338 void SdrObject::NbcRotateGluePoints(const Point
& rRef
, Degree100 nAngle
, double sn
, double cs
)
2340 // First a const call to see whether there are any gluepoints.
2341 // Force const call!
2342 if (GetGluePointList()!=nullptr) {
2343 SdrGluePointList
* pGPL
=ForceGluePointList();
2344 pGPL
->Rotate(rRef
,nAngle
,sn
,cs
,this);
2348 void SdrObject::NbcMirrorGluePoints(const Point
& rRef1
, const Point
& rRef2
)
2350 // First a const call to see whether there are any gluepoints.
2351 // Force const call!
2352 if (GetGluePointList()!=nullptr) {
2353 SdrGluePointList
* pGPL
=ForceGluePointList();
2354 pGPL
->Mirror(rRef1
,rRef2
,this);
2358 void SdrObject::NbcShearGluePoints(const Point
& rRef
, double tn
, bool bVShear
)
2360 // First a const call to see whether there are any gluepoints.
2361 // Force const call!
2362 if (GetGluePointList()!=nullptr) {
2363 SdrGluePointList
* pGPL
=ForceGluePointList();
2364 pGPL
->Shear(rRef
,tn
,bVShear
,this);
2368 void SdrObject::ConnectToNode(bool /*bTail1*/, SdrObject
* /*pObj*/)
2372 void SdrObject::DisconnectFromNode(bool /*bTail1*/)
2376 SdrObject
* SdrObject::GetConnectedNode(bool /*bTail1*/) const
2382 static void extractLineContourFromPrimitive2DSequence(
2383 const drawinglayer::primitive2d::Primitive2DContainer
& rxSequence
,
2384 basegfx::B2DPolygonVector
& rExtractedHairlines
,
2385 basegfx::B2DPolyPolygonVector
& rExtractedLineFills
)
2387 rExtractedHairlines
.clear();
2388 rExtractedLineFills
.clear();
2390 if(rxSequence
.empty())
2393 // use neutral ViewInformation
2394 const drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
2396 // create extractor, process and get result
2397 drawinglayer::processor2d::LineGeometryExtractor2D
aExtractor(aViewInformation2D
);
2398 aExtractor
.process(rxSequence
);
2400 // copy line results
2401 rExtractedHairlines
= aExtractor
.getExtractedHairlines();
2404 rExtractedLineFills
= aExtractor
.getExtractedLineFills();
2408 rtl::Reference
<SdrObject
> SdrObject::ImpConvertToContourObj(bool bForceLineDash
)
2410 rtl::Reference
<SdrObject
> pRetval
;
2412 if(LineGeometryUsageIsNecessary())
2414 basegfx::B2DPolyPolygon aMergedLineFillPolyPolygon
;
2415 basegfx::B2DPolyPolygon aMergedHairlinePolyPolygon
;
2416 drawinglayer::primitive2d::Primitive2DContainer xSequence
;
2417 GetViewContact().getViewIndependentPrimitive2DContainer(xSequence
);
2419 if(!xSequence
.empty())
2421 basegfx::B2DPolygonVector aExtractedHairlines
;
2422 basegfx::B2DPolyPolygonVector aExtractedLineFills
;
2424 extractLineContourFromPrimitive2DSequence(xSequence
, aExtractedHairlines
, aExtractedLineFills
);
2426 // for SdrObject creation, just copy all to a single Hairline-PolyPolygon
2427 for(const basegfx::B2DPolygon
& rExtractedHairline
: aExtractedHairlines
)
2429 aMergedHairlinePolyPolygon
.append(rExtractedHairline
);
2432 // check for fill rsults
2433 if (!aExtractedLineFills
.empty() && !utl::ConfigManager::IsFuzzing())
2435 // merge to a single tools::PolyPolygon (OR)
2436 aMergedLineFillPolyPolygon
= basegfx::utils::mergeToSinglePolyPolygon(std::move(aExtractedLineFills
));
2440 if(aMergedLineFillPolyPolygon
.count() || (bForceLineDash
&& aMergedHairlinePolyPolygon
.count()))
2442 SfxItemSet
aSet(GetMergedItemSet());
2443 drawing::FillStyle eOldFillStyle
= aSet
.Get(XATTR_FILLSTYLE
).GetValue();
2444 rtl::Reference
<SdrPathObj
> aLinePolygonPart
;
2445 rtl::Reference
<SdrPathObj
> aLineHairlinePart
;
2446 bool bBuildGroup(false);
2448 if(aMergedLineFillPolyPolygon
.count())
2450 // create SdrObject for filled line geometry
2451 aLinePolygonPart
= new SdrPathObj(
2452 getSdrModelFromSdrObject(),
2453 SdrObjKind::PathFill
,
2454 std::move(aMergedLineFillPolyPolygon
));
2456 // correct item properties
2457 aSet
.Put(XLineWidthItem(0));
2458 aSet
.Put(XLineStyleItem(drawing::LineStyle_NONE
));
2459 Color aColorLine
= aSet
.Get(XATTR_LINECOLOR
).GetColorValue();
2460 sal_uInt16 nTransLine
= aSet
.Get(XATTR_LINETRANSPARENCE
).GetValue();
2461 aSet
.Put(XFillColorItem(OUString(), aColorLine
));
2462 aSet
.Put(XFillStyleItem(drawing::FillStyle_SOLID
));
2463 aSet
.Put(XFillTransparenceItem(nTransLine
));
2465 aLinePolygonPart
->SetMergedItemSet(aSet
);
2468 if(aMergedHairlinePolyPolygon
.count())
2470 // create SdrObject for hairline geometry
2471 // OBJ_PATHLINE is necessary here, not OBJ_PATHFILL. This is intended
2472 // to get a non-filled object. If the poly is closed, the PathObj takes care for
2473 // the correct closed state.
2474 aLineHairlinePart
= new SdrPathObj(
2475 getSdrModelFromSdrObject(),
2476 SdrObjKind::PathLine
,
2477 std::move(aMergedHairlinePolyPolygon
));
2479 aSet
.Put(XLineWidthItem(0));
2480 aSet
.Put(XFillStyleItem(drawing::FillStyle_NONE
));
2481 aSet
.Put(XLineStyleItem(drawing::LineStyle_SOLID
));
2483 // it is also necessary to switch off line start and ends here
2484 aSet
.Put(XLineStartWidthItem(0));
2485 aSet
.Put(XLineEndWidthItem(0));
2487 aLineHairlinePart
->SetMergedItemSet(aSet
);
2489 if(aLinePolygonPart
)
2495 // check if original geometry should be added (e.g. filled and closed)
2496 bool bAddOriginalGeometry(false);
2497 SdrPathObj
* pPath
= dynamic_cast<SdrPathObj
*>(this);
2499 if(pPath
&& pPath
->IsClosed())
2501 if(eOldFillStyle
!= drawing::FillStyle_NONE
)
2503 bAddOriginalGeometry
= true;
2507 // do we need a group?
2508 if(bBuildGroup
|| bAddOriginalGeometry
)
2510 rtl::Reference
<SdrObject
> pGroup
= new SdrObjGroup(getSdrModelFromSdrObject());
2512 if(bAddOriginalGeometry
)
2514 // Add a clone of the original geometry.
2516 aSet
.Put(GetMergedItemSet());
2517 aSet
.Put(XLineStyleItem(drawing::LineStyle_NONE
));
2518 aSet
.Put(XLineWidthItem(0));
2520 rtl::Reference
<SdrObject
> pClone(CloneSdrObject(getSdrModelFromSdrObject()));
2521 pClone
->SetMergedItemSet(aSet
);
2523 pGroup
->GetSubList()->NbcInsertObject(pClone
.get());
2526 if(aLinePolygonPart
)
2528 pGroup
->GetSubList()->NbcInsertObject(aLinePolygonPart
.get());
2531 if(aLineHairlinePart
)
2533 pGroup
->GetSubList()->NbcInsertObject(aLineHairlinePart
.get());
2540 if(aLinePolygonPart
)
2542 pRetval
= aLinePolygonPart
;
2544 else if(aLineHairlinePart
)
2546 pRetval
= aLineHairlinePart
;
2554 // due to current method usage, create and return a clone when nothing has changed
2555 pRetval
= CloneSdrObject(getSdrModelFromSdrObject());
2562 void SdrObject::SetMarkProtect(bool bProt
)
2564 m_bMarkProt
= bProt
;
2568 void SdrObject::SetEmptyPresObj(bool bEpt
)
2570 m_bEmptyPresObj
= bEpt
;
2574 void SdrObject::SetNotVisibleAsMaster(bool bFlg
)
2576 m_bNotVisibleAsMaster
=bFlg
;
2580 // convert this path object to contour object, even when it is a group
2581 rtl::Reference
<SdrObject
> SdrObject::ConvertToContourObj(SdrObject
* pRet1
, bool bForceLineDash
) const
2583 rtl::Reference
<SdrObject
> pRet
= pRet1
;
2584 if(dynamic_cast<const SdrObjGroup
*>( pRet
.get()) != nullptr)
2586 SdrObjList
* pObjList2
= pRet
->GetSubList();
2587 rtl::Reference
<SdrObject
> pGroup
= new SdrObjGroup(getSdrModelFromSdrObject());
2589 for(size_t a
=0; a
<pObjList2
->GetObjCount(); ++a
)
2591 SdrObject
* pIterObj
= pObjList2
->GetObj(a
);
2592 pGroup
->GetSubList()->NbcInsertObject(ConvertToContourObj(pIterObj
, bForceLineDash
).get());
2599 if (SdrPathObj
*pPathObj
= dynamic_cast<SdrPathObj
*>(pRet
.get()))
2601 // bezier geometry got created, even for straight edges since the given
2602 // object is a result of DoConvertToPolyObj. For conversion to contour
2603 // this is not really needed and can be reduced again AFAP
2604 pPathObj
->SetPathPoly(basegfx::utils::simplifyCurveSegments(pPathObj
->GetPathPoly()));
2607 pRet
= pRet
->ImpConvertToContourObj(bForceLineDash
);
2610 // #i73441# preserve LayerID
2611 if(pRet
&& pRet
->GetLayer() != GetLayer())
2613 pRet
->SetLayer(GetLayer());
2620 rtl::Reference
<SdrObject
> SdrObject::ConvertToPolyObj(bool bBezier
, bool bLineToArea
) const
2622 rtl::Reference
<SdrObject
> pRet
= DoConvertToPolyObj(bBezier
, true);
2624 if(pRet
&& bLineToArea
)
2626 pRet
= ConvertToContourObj(pRet
.get());
2629 // #i73441# preserve LayerID
2630 if(pRet
&& pRet
->GetLayer() != GetLayer())
2632 pRet
->SetLayer(GetLayer());
2639 rtl::Reference
<SdrObject
> SdrObject::DoConvertToPolyObj(bool /*bBezier*/, bool /*bAddText*/) const
2645 void SdrObject::InsertedStateChange()
2647 const bool bIsInserted(nullptr != getParentSdrObjListFromSdrObject());
2648 const tools::Rectangle
aBoundRect0(GetLastBoundRect());
2652 SendUserCall(SdrUserCallType::Inserted
, aBoundRect0
);
2656 SendUserCall(SdrUserCallType::Removed
, aBoundRect0
);
2659 if(nullptr != m_pPlusData
&& nullptr != m_pPlusData
->pBroadcast
)
2661 SdrHint
aHint(bIsInserted
? SdrHintKind::ObjectInserted
: SdrHintKind::ObjectRemoved
, *this);
2662 m_pPlusData
->pBroadcast
->Broadcast(aHint
);
2666 void SdrObject::SetMoveProtect(bool bProt
)
2668 if(IsMoveProtect() != bProt
)
2670 // #i77187# secured and simplified
2673 BroadcastObjectChange();
2677 void SdrObject::SetResizeProtect(bool bProt
)
2679 if(IsResizeProtect() != bProt
)
2681 // #i77187# secured and simplified
2684 BroadcastObjectChange();
2688 void SdrObject::SetPrintable(bool bPrn
)
2690 if( bPrn
== m_bNoPrint
)
2696 SdrHint
aHint(SdrHintKind::ObjectChange
, *this);
2697 getSdrModelFromSdrObject().Broadcast(aHint
);
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( svx::ShapePropertyProviderId::Size
);
2814 [[fallthrough
]]; // RESIZE might also imply a change of the position
2815 case SdrUserCallType::MoveOnly
:
2816 notifyShapePropertyChange( svx::ShapePropertyProviderId::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 svx::ShapePropertyProviderId _eProperty
) const
2958 DBG_TESTSOLARMUTEX();
2960 SvxShape
* pSvxShape
= const_cast< SdrObject
* >( this )->getSvxShape();
2962 return pSvxShape
->notifyPropertyChange( _eProperty
);
2965 void SdrObject::registerProvider( const svx::ShapePropertyProviderId _eProperty
, std::unique_ptr
<svx::PropertyValueProvider
> provider
)
2967 DBG_TESTSOLARMUTEX();
2969 SvxShape
* pSvxShape
= getSvxShape();
2970 return pSvxShape
->registerProvider( _eProperty
, std::move(provider
) );
2973 // transformation interface for StarOfficeAPI. This implements support for
2974 // homogeneous 3x3 matrices containing the transformation of the SdrObject. At the
2975 // moment it contains a shearX, rotation and translation, but for setting all linear
2976 // transforms like Scale, ShearX, ShearY, Rotate and Translate are supported.
2979 // gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon
2980 // with the base geometry and returns TRUE. Otherwise it returns FALSE.
2981 bool SdrObject::TRGetBaseGeometry(basegfx::B2DHomMatrix
& rMatrix
, basegfx::B2DPolyPolygon
& /*rPolyPolygon*/) const
2983 // any kind of SdrObject, just use SnapRect
2984 tools::Rectangle
aRectangle(GetSnapRect());
2986 // convert to transformation values
2987 basegfx::B2DTuple
aScale(aRectangle
.GetWidth(), aRectangle
.GetHeight());
2988 basegfx::B2DTuple
aTranslate(aRectangle
.Left(), aRectangle
.Top());
2990 // position maybe relative to anchorpos, convert
2991 if(getSdrModelFromSdrObject().IsWriter())
2993 if(GetAnchorPos().X() || GetAnchorPos().Y())
2995 aTranslate
-= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
3000 rMatrix
= basegfx::utils::createScaleTranslateB2DHomMatrix(aScale
, aTranslate
);
3005 // sets the base geometry of the object using infos contained in the homogeneous 3x3 matrix.
3006 // If it's an SdrPathObj it will use the provided geometry information. The Polygon has
3007 // to use (0,0) as upper left and will be scaled to the given size in the matrix.
3008 void SdrObject::TRSetBaseGeometry(const basegfx::B2DHomMatrix
& rMatrix
, const basegfx::B2DPolyPolygon
& /*rPolyPolygon*/)
3011 basegfx::B2DTuple aScale
;
3012 basegfx::B2DTuple aTranslate
;
3013 double fRotate
, fShearX
;
3014 rMatrix
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
3016 // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
3017 // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
3018 if(basegfx::fTools::less(aScale
.getX(), 0.0) && basegfx::fTools::less(aScale
.getY(), 0.0))
3020 aScale
.setX(fabs(aScale
.getX()));
3021 aScale
.setY(fabs(aScale
.getY()));
3024 // if anchor is used, make position relative to it
3025 if(getSdrModelFromSdrObject().IsWriter())
3027 if(GetAnchorPos().X() || GetAnchorPos().Y())
3029 aTranslate
+= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
3034 Point
aPoint(FRound(aTranslate
.getX()), FRound(aTranslate
.getY()));
3035 tools::Rectangle
aBaseRect(aPoint
, Size(FRound(aScale
.getX()), FRound(aScale
.getY())));
3038 SetSnapRect(aBaseRect
);
3041 // Give info if object is in destruction
3042 bool SdrObject::IsInDestruction() const
3044 return getSdrModelFromSdrObject().IsInDestruction();
3047 // return if fill is != drawing::FillStyle_NONE
3048 bool SdrObject::HasFillStyle() const
3050 return GetObjectItem(XATTR_FILLSTYLE
).GetValue() != drawing::FillStyle_NONE
;
3053 bool SdrObject::HasLineStyle() const
3055 return GetObjectItem(XATTR_LINESTYLE
).GetValue() != drawing::LineStyle_NONE
;
3060 // on import of OLE object from MS documents the BLIP size might be retrieved,
3061 // the following four methods are used to control it;
3062 // usually this data makes no sense after the import is finished, since the object
3066 void SdrObject::SetBLIPSizeRectangle( const tools::Rectangle
& aRect
)
3068 maBLIPSizeRectangle
= aRect
;
3071 void SdrObject::SetContextWritingMode( const sal_Int16
/*_nContextWritingMode*/ )
3073 // this base class does not support different writing modes, so ignore the call
3076 void SdrObject::SetDoNotInsertIntoPageAutomatically(const bool bSet
)
3078 mbDoNotInsertIntoPageAutomatically
= bSet
;
3083 bool SdrObject::HasText() const
3088 bool SdrObject::IsTextBox() const
3093 void SdrObject::MakeNameUnique()
3095 if (GetName().isEmpty())
3098 if (const E3dScene
* pE3dObj
= DynCastE3dScene(this))
3100 SdrObjList
* pObjList
= pE3dObj
->GetSubList();
3103 SdrObject
* pObj0
= pObjList
->GetObj(0);
3105 aName
= pObj0
->TakeObjNameSingul();
3109 aName
= TakeObjNameSingul();
3110 SetName(aName
+ " 1");
3113 std::unordered_set
<OUString
> aNameSet
;
3114 MakeNameUnique(aNameSet
);
3117 void SdrObject::MakeNameUnique(std::unordered_set
<OUString
>& rNameSet
)
3119 if (GetName().isEmpty())
3122 if (rNameSet
.empty())
3126 for (sal_uInt16
nPage(0); nPage
< mrSdrModelFromSdrObject
.GetPageCount(); ++nPage
)
3128 pPage
= mrSdrModelFromSdrObject
.GetPage(nPage
);
3129 SdrObjListIter
aIter(pPage
, SdrIterMode::DeepWithGroups
);
3130 while (aIter
.IsMore())
3132 pObj
= aIter
.Next();
3134 rNameSet
.insert(pObj
->GetName());
3139 OUString
sName(GetName().trim());
3140 OUString
sRootName(sName
);
3142 if (!sName
.isEmpty() && rtl::isAsciiDigit(sName
[sName
.getLength() - 1]))
3144 sal_Int32
nPos(sName
.getLength() - 1);
3145 while (nPos
> 0 && rtl::isAsciiDigit(sName
[--nPos
]));
3146 sRootName
= o3tl::trim(sName
.subView(0, nPos
+ 1));
3149 for (sal_uInt32 n
= 1; rNameSet
.find(sName
) != rNameSet
.end(); n
++)
3150 sName
= sRootName
+ " " + OUString::number(n
);
3151 rNameSet
.insert(sName
);
3156 void SdrObject::ForceMetricToItemPoolMetric(basegfx::B2DPolyPolygon
& rPolyPolygon
) const noexcept
3158 MapUnit
eMapUnit(getSdrModelFromSdrObject().GetItemPool().GetMetric(0));
3159 if(eMapUnit
== MapUnit::Map100thMM
)
3162 if (const auto eTo
= MapToO3tlLength(eMapUnit
); eTo
!= o3tl::Length::invalid
)
3164 const double fConvert(o3tl::convert(1.0, o3tl::Length::mm100
, eTo
));
3165 rPolyPolygon
.transform(basegfx::utils::createScaleB2DHomMatrix(fConvert
, fConvert
));
3169 OSL_FAIL("Missing unit translation to PoolMetric!");
3173 const tools::Rectangle
& SdrObject::getOutRectangle() const
3178 void SdrObject::setOutRectangleConst(tools::Rectangle
const& rRectangle
) const
3180 m_aOutRect
= rRectangle
;
3183 void SdrObject::setOutRectangle(tools::Rectangle
const& rRectangle
)
3185 m_aOutRect
= rRectangle
;
3188 void SdrObject::resetOutRectangle()
3190 m_aOutRect
= tools::Rectangle();
3193 void SdrObject::moveOutRectangle(sal_Int32 nXDelta
, sal_Int32 nYDelta
)
3195 m_aOutRect
.Move(nXDelta
, nYDelta
);
3198 E3dScene
* DynCastE3dScene(SdrObject
* pObj
)
3200 if( pObj
&& pObj
->GetObjInventor() == SdrInventor::E3d
&& pObj
->GetObjIdentifier() == SdrObjKind::E3D_Scene
)
3201 return static_cast<E3dScene
*>(pObj
);
3205 E3dObject
* DynCastE3dObject(SdrObject
* pObj
)
3207 if( pObj
&& pObj
->GetObjInventor() == SdrInventor::E3d
)
3208 return static_cast<E3dObject
*>(pObj
);
3212 SdrTextObj
* DynCastSdrTextObj(SdrObject
* pObj
)
3214 // SdrTextObj has a lot of subclasses, with lots of SdrObjKind identifiers, so use a virtual method
3216 if( pObj
&& pObj
->IsSdrTextObj() )
3217 return static_cast<SdrTextObj
*>(pObj
);
3221 rtl::Reference
<SdrObject
> SdrObjFactory::CreateObjectFromFactory(SdrModel
& rSdrModel
, SdrInventor nInventor
, SdrObjKind nObjIdentifier
)
3223 SdrObjCreatorParams aParams
{ nInventor
, nObjIdentifier
, rSdrModel
};
3224 for (const auto & i
: ImpGetUserMakeObjHdl()) {
3225 rtl::Reference
<SdrObject
> pObj
= i
.Call(aParams
);
3236 // SdrObject subclass, which represents an empty object of a
3237 // certain type (kind).
3238 template <SdrObjKind OBJECT_KIND
, SdrInventor OBJECT_INVENTOR
>
3239 class EmptyObject final
: public SdrObject
3242 virtual ~EmptyObject() override
3246 EmptyObject(SdrModel
& rSdrModel
)
3247 : SdrObject(rSdrModel
)
3251 EmptyObject(SdrModel
& rSdrModel
, EmptyObject
const& rSource
)
3252 : SdrObject(rSdrModel
, rSource
)
3256 rtl::Reference
<SdrObject
> CloneSdrObject(SdrModel
& rTargetModel
) const override
3258 return new EmptyObject(rTargetModel
, *this);
3261 SdrInventor
GetObjInventor() const override
3263 return OBJECT_INVENTOR
;
3266 SdrObjKind
GetObjIdentifier() const override
3271 void NbcRotate(const Point
& /*rRef*/, Degree100
/*nAngle*/, double /*sinAngle*/, double /*cosAngle*/) override
3273 assert(false); // should not be called for this kind of objects
3277 } // end anonymous namespace
3279 rtl::Reference
<SdrObject
> SdrObjFactory::MakeNewObject(
3280 SdrModel
& rSdrModel
,
3281 SdrInventor nInventor
,
3282 SdrObjKind nIdentifier
,
3283 const tools::Rectangle
* pSnapRect
)
3285 rtl::Reference
<SdrObject
> pObj
;
3286 bool bSetSnapRect(nullptr != pSnapRect
);
3288 if (nInventor
== SdrInventor::Default
)
3290 switch (nIdentifier
)
3292 case SdrObjKind::Measure
:
3294 if(nullptr != pSnapRect
)
3296 pObj
= new SdrMeasureObj(
3298 pSnapRect
->TopLeft(),
3299 pSnapRect
->BottomRight());
3303 pObj
= new SdrMeasureObj(rSdrModel
);
3307 case SdrObjKind::Line
:
3309 if(nullptr != pSnapRect
)
3311 basegfx::B2DPolygon aPoly
;
3320 pSnapRect
->Bottom()));
3321 pObj
= new SdrPathObj(
3324 basegfx::B2DPolyPolygon(aPoly
));
3328 pObj
= new SdrPathObj(
3334 case SdrObjKind::Text
:
3335 case SdrObjKind::TitleText
:
3336 case SdrObjKind::OutlineText
:
3338 if(nullptr != pSnapRect
)
3340 pObj
= new SdrRectObj(
3344 bSetSnapRect
= false;
3348 pObj
= new SdrRectObj(
3354 case SdrObjKind::CircleOrEllipse
:
3355 case SdrObjKind::CircleSection
:
3356 case SdrObjKind::CircleArc
:
3357 case SdrObjKind::CircleCut
:
3359 SdrCircKind eCircKind
= ToSdrCircKind(nIdentifier
);
3360 if(nullptr != pSnapRect
)
3362 pObj
= new SdrCircObj(rSdrModel
, eCircKind
, *pSnapRect
);
3363 bSetSnapRect
= false;
3367 pObj
= new SdrCircObj(rSdrModel
, eCircKind
);
3371 case SdrObjKind::NONE
: pObj
= nullptr; break;
3372 case SdrObjKind::Group
: pObj
=new SdrObjGroup(rSdrModel
); break;
3373 case SdrObjKind::Polygon
: pObj
=new SdrPathObj(rSdrModel
, SdrObjKind::Polygon
); break;
3374 case SdrObjKind::PolyLine
: pObj
=new SdrPathObj(rSdrModel
, SdrObjKind::PolyLine
); break;
3375 case SdrObjKind::PathLine
: pObj
=new SdrPathObj(rSdrModel
, SdrObjKind::PathLine
); break;
3376 case SdrObjKind::PathFill
: pObj
=new SdrPathObj(rSdrModel
, SdrObjKind::PathFill
); break;
3377 case SdrObjKind::FreehandLine
: pObj
=new SdrPathObj(rSdrModel
, SdrObjKind::FreehandLine
); break;
3378 case SdrObjKind::FreehandFill
: pObj
=new SdrPathObj(rSdrModel
, SdrObjKind::FreehandFill
); break;
3379 case SdrObjKind::PathPoly
: pObj
=new SdrPathObj(rSdrModel
, SdrObjKind::Polygon
); break;
3380 case SdrObjKind::PathPolyLine
: pObj
=new SdrPathObj(rSdrModel
, SdrObjKind::PolyLine
); break;
3381 case SdrObjKind::Edge
: pObj
=new SdrEdgeObj(rSdrModel
); break;
3382 case SdrObjKind::Rectangle
: pObj
=new SdrRectObj(rSdrModel
); break;
3383 case SdrObjKind::Graphic
: pObj
=new SdrGrafObj(rSdrModel
); break;
3384 case SdrObjKind::OLE2
: pObj
=new SdrOle2Obj(rSdrModel
); break;
3385 case SdrObjKind::OLEPluginFrame
: pObj
=new SdrOle2Obj(rSdrModel
, true); break;
3386 case SdrObjKind::Caption
: pObj
=new SdrCaptionObj(rSdrModel
); break;
3387 case SdrObjKind::Page
: pObj
=new SdrPageObj(rSdrModel
); break;
3388 case SdrObjKind::UNO
: pObj
=new SdrUnoObj(rSdrModel
, OUString()); break;
3389 case SdrObjKind::CustomShape
: pObj
=new SdrObjCustomShape(rSdrModel
); break;
3390 #if HAVE_FEATURE_AVMEDIA
3391 case SdrObjKind::Media
: pObj
=new SdrMediaObj(rSdrModel
); break;
3393 case SdrObjKind::Table
: pObj
=new sdr::table::SdrTableObj(rSdrModel
); break;
3394 case SdrObjKind::NewFrame
: // used for frame creation in writer
3395 pObj
= new EmptyObject
<SdrObjKind::NewFrame
, SdrInventor::Default
>(rSdrModel
);
3404 pObj
= CreateObjectFromFactory(rSdrModel
, nInventor
, nIdentifier
);
3409 // Well, if no one wants it...
3413 if(bSetSnapRect
&& nullptr != pSnapRect
)
3415 pObj
->NbcSetSnapRect(*pSnapRect
);
3421 void SdrObjFactory::InsertMakeObjectHdl(Link
<SdrObjCreatorParams
, rtl::Reference
<SdrObject
>> const & rLink
)
3423 std::vector
<Link
<SdrObjCreatorParams
, rtl::Reference
<SdrObject
>>>& rLL
=ImpGetUserMakeObjHdl();
3424 auto it
= std::find(rLL
.begin(), rLL
.end(), rLink
);
3425 if (it
!= rLL
.end()) {
3426 OSL_FAIL("SdrObjFactory::InsertMakeObjectHdl(): Link already in place.");
3428 rLL
.push_back(rLink
);
3432 void SdrObjFactory::RemoveMakeObjectHdl(Link
<SdrObjCreatorParams
, rtl::Reference
<SdrObject
>> const & rLink
)
3434 std::vector
<Link
<SdrObjCreatorParams
, rtl::Reference
<SdrObject
>>>& rLL
=ImpGetUserMakeObjHdl();
3435 auto it
= std::find(rLL
.begin(), rLL
.end(), rLink
);
3436 if (it
!= rLL
.end())
3442 ISdrObjectFilter::~ISdrObjectFilter()
3447 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */