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