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