1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
23 #include <unordered_set>
25 #include <svx/svdpage.hxx>
26 #include <svx/unoshape.hxx>
27 #include <svx/unopage.hxx>
29 #include <o3tl/safeint.hxx>
32 #include <tools/debug.hxx>
33 #include <comphelper/diagnose_ex.hxx>
34 #include <comphelper/lok.hxx>
36 #include <sfx2/viewsh.hxx>
37 #include <svtools/colorcfg.hxx>
38 #include <svx/svdetc.hxx>
39 #include <svx/svdobj.hxx>
40 #include <svx/svdogrp.hxx>
41 #include <svx/svdoedge.hxx>
42 #include <svx/svdoole2.hxx>
43 #include <svx/svditer.hxx>
44 #include <svx/svdmodel.hxx>
45 #include <svx/svdlayer.hxx>
46 #include <svx/svdpagv.hxx>
47 #include <svx/svdundo.hxx>
48 #include <svx/xfillit0.hxx>
49 #include <svx/ColorSets.hxx>
51 #include <sdr/contact/viewcontactofsdrpage.hxx>
52 #include <svx/sdr/contact/viewobjectcontact.hxx>
53 #include <svx/sdr/contact/displayinfo.hxx>
55 #include <clonelist.hxx>
56 #include <svl/hint.hxx>
57 #include <rtl/strbuf.hxx>
58 #include <libxml/xmlwriter.h>
59 #include <docmodel/theme/Theme.hxx>
61 #include <com/sun/star/lang/IllegalArgumentException.hpp>
63 using namespace ::com::sun::star
;
65 //////////////////////////////////////////////////////////////////////////////
67 SdrObjList::SdrObjList()
68 : mbObjOrdNumsDirty(false),
70 mbIsNavigationOrderDirty(false)
74 void SdrObjList::impClearSdrObjList(bool bBroadcast
)
76 SdrModel
* pSdrModelFromRemovedSdrObject(nullptr);
78 while(!maList
.empty())
80 // remove last object from list
81 rtl::Reference
<SdrObject
> pObj(maList
.back());
82 RemoveObjectFromContainer(maList
.size()-1);
84 // flushViewObjectContacts() is done since SdrObject::Free is not guaranteed
85 // to delete the object and thus refresh visualisations
86 pObj
->GetViewContact().flushViewObjectContacts();
90 if(nullptr == pSdrModelFromRemovedSdrObject
)
92 pSdrModelFromRemovedSdrObject
= &pObj
->getSdrModelFromSdrObject();
95 // sent remove hint (after removal, see RemoveObject())
96 // TTTT SdrPage not needed, can be accessed using SdrObject
97 SdrHint
aHint(SdrHintKind::ObjectRemoved
, *pObj
, getSdrPageFromSdrObjList());
98 pObj
->getSdrModelFromSdrObject().Broadcast(aHint
);
100 pObj
->setParentOfSdrObject(nullptr);
103 if(bBroadcast
&& nullptr != pSdrModelFromRemovedSdrObject
)
105 pSdrModelFromRemovedSdrObject
->SetChanged();
109 void SdrObjList::ClearSdrObjList()
111 // clear SdrObjects with broadcasting
112 impClearSdrObjList(true);
115 SdrObjList::~SdrObjList()
117 // Clear SdrObjects without broadcasting.
118 for (auto& rxObj
: maList
)
119 rxObj
->setParentOfSdrObject(nullptr);
122 SdrPage
* SdrObjList::getSdrPageFromSdrObjList() const
124 // default is no page and returns zero
128 SdrObject
* SdrObjList::getSdrObjectFromSdrObjList() const
130 // default is no SdrObject (SdrObjGroup)
134 void SdrObjList::CopyObjects(const SdrObjList
& rSrcList
)
136 CloneList aCloneList
;
138 // clear SdrObjects with broadcasting
141 mbObjOrdNumsDirty
= false;
142 mbRectsDirty
= false;
144 size_t nCloneErrCnt(0);
147 if(nullptr == getSdrObjectFromSdrObjList() && nullptr == getSdrPageFromSdrObjList())
149 OSL_ENSURE(false, "SdrObjList which is not part of SdrPage or SdrObject (!)");
153 SdrModel
& rTargetSdrModel(nullptr == getSdrObjectFromSdrObjList()
154 ? getSdrPageFromSdrObjList()->getSdrModelFromSdrPage()
155 : getSdrObjectFromSdrObjList()->getSdrModelFromSdrObject());
157 for (const rtl::Reference
<SdrObject
>& pSO
: rSrcList
)
159 rtl::Reference
<SdrObject
> pDO(pSO
->CloneSdrObject(rTargetSdrModel
));
163 NbcInsertObject(pDO
.get(), SAL_MAX_SIZE
);
164 aCloneList
.AddPair(pSO
.get(), pDO
.get());
174 // Wires up the connections
175 aCloneList
.CopyConnections();
177 if (nCloneErrCnt
!= 0)
179 OStringBuffer
aStr("SdrObjList::operator=(): Error when cloning ");
181 if(nCloneErrCnt
== 1)
183 aStr
.append("a drawing object.");
187 aStr
.append(OString::number(static_cast<sal_Int32
>(nCloneErrCnt
))
188 + " drawing objects.");
191 OSL_FAIL(aStr
.getStr());
196 void SdrObjList::RecalcObjOrdNums()
199 for (const rtl::Reference
<SdrObject
>& pObj
: maList
)
200 pObj
->SetOrdNum(no
++);
201 mbObjOrdNumsDirty
=false;
204 void SdrObjList::RecalcRects()
206 maSdrObjListOutRect
=tools::Rectangle();
207 maSdrObjListSnapRect
=maSdrObjListOutRect
;
208 for (auto it
= begin(), itEnd
= end(); it
!= itEnd
; ++it
) {
209 SdrObject
* pObj
= it
->get();
211 maSdrObjListOutRect
=pObj
->GetCurrentBoundRect();
212 maSdrObjListSnapRect
=pObj
->GetSnapRect();
214 maSdrObjListOutRect
.Union(pObj
->GetCurrentBoundRect());
215 maSdrObjListSnapRect
.Union(pObj
->GetSnapRect());
220 void SdrObjList::SetSdrObjListRectsDirty()
223 SdrObject
* pParentSdrObject(getSdrObjectFromSdrObjList());
225 if(nullptr != pParentSdrObject
)
227 pParentSdrObject
->SetBoundAndSnapRectsDirty();
231 void SdrObjList::impChildInserted(SdrObject
const & rChild
)
233 sdr::contact::ViewContact
* pParent
= rChild
.GetViewContact().GetParentContact();
237 pParent
->ActionChildInserted(rChild
.GetViewContact());
241 void SdrObjList::NbcInsertObject(SdrObject
* pObj
, size_t nPos
)
243 DBG_ASSERT(pObj
!=nullptr,"SdrObjList::NbcInsertObject(NULL)");
247 DBG_ASSERT(!pObj
->IsInserted(),"The object already has the status Inserted.");
248 const size_t nCount
= GetObjCount();
249 if (nPos
>nCount
) nPos
=nCount
;
250 InsertObjectIntoContainer(*pObj
,nPos
);
252 if (nPos
<nCount
) mbObjOrdNumsDirty
=true;
253 pObj
->SetOrdNum(nPos
);
254 pObj
->setParentOfSdrObject(this);
256 // Inform the parent about change to allow invalidations at
257 // evtl. existing parent visualisations
258 impChildInserted(*pObj
);
263 pObj
->InsertedStateChange(); // calls the UserCall (among others)
266 void SdrObjList::InsertObjectThenMakeNameUnique(SdrObject
* pObj
)
268 std::unordered_set
<rtl::OUString
> aNameSet
;
269 InsertObjectThenMakeNameUnique(pObj
, aNameSet
);
272 void SdrObjList::InsertObjectThenMakeNameUnique(SdrObject
* pObj
, std::unordered_set
<OUString
>& rNameSet
, size_t nPos
)
274 InsertObject(pObj
, nPos
);
275 if (pObj
->GetName().isEmpty())
278 pObj
->MakeNameUnique(rNameSet
);
279 SdrObjList
* pSdrObjList
= pObj
->GetSubList(); // group
283 SdrObjListIter
aIter(pSdrObjList
, SdrIterMode::DeepWithGroups
);
284 while (aIter
.IsMore())
286 pListObj
= aIter
.Next();
287 pListObj
->MakeNameUnique(rNameSet
);
292 void SdrObjList::InsertObject(SdrObject
* pObj
, size_t nPos
)
294 DBG_ASSERT(pObj
!=nullptr,"SdrObjList::InsertObject(NULL)");
299 // if anchor is used, reset it before grouping
300 if(getSdrObjectFromSdrObjList())
302 const Point
& rAnchorPos
= pObj
->GetAnchorPos();
303 if(rAnchorPos
.X() || rAnchorPos
.Y())
304 pObj
->NbcSetAnchorPos(Point());
307 // do insert to new group
308 NbcInsertObject(pObj
, nPos
);
310 // In case the object is inserted into a group and doesn't overlap with
311 // the group's other members, it needs an own repaint.
312 SdrObject
* pParentSdrObject(getSdrObjectFromSdrObjList());
317 pParentSdrObject
->ActionChanged();
320 // TODO: We need a different broadcast here!
321 // Repaint from object number ... (heads-up: GroupObj)
322 if(pObj
->getSdrPageFromSdrObject() && !pObj
->getSdrModelFromSdrObject().isLocked())
324 SdrHint
aHint(SdrHintKind::ObjectInserted
, *pObj
);
325 pObj
->getSdrModelFromSdrObject().Broadcast(aHint
);
328 pObj
->getSdrModelFromSdrObject().SetChanged();
331 rtl::Reference
<SdrObject
> SdrObjList::NbcRemoveObject(size_t nObjNum
)
333 if (nObjNum
>= maList
.size())
335 OSL_ASSERT(nObjNum
<maList
.size());
339 const size_t nCount
= GetObjCount();
340 rtl::Reference
<SdrObject
> pObj
=maList
[nObjNum
];
341 RemoveObjectFromContainer(nObjNum
);
343 DBG_ASSERT(pObj
!=nullptr,"Could not find object to remove.");
346 // flushViewObjectContacts() clears the VOC's and those invalidate
347 pObj
->GetViewContact().flushViewObjectContacts();
349 DBG_ASSERT(pObj
->IsInserted(),"The object does not have the status Inserted.");
351 // tdf#121022 Do first remove from SdrObjList - InsertedStateChange
352 // relies now on IsInserted which uses getParentSdrObjListFromSdrObject
353 pObj
->setParentOfSdrObject(nullptr);
355 // calls UserCall, among other
356 pObj
->InsertedStateChange();
358 if (!mbObjOrdNumsDirty
)
360 // optimizing for the case that the last object has to be removed
361 if (nObjNum
+1!=nCount
) {
362 mbObjOrdNumsDirty
=true;
365 SetSdrObjListRectsDirty();
370 rtl::Reference
<SdrObject
> SdrObjList::RemoveObject(size_t nObjNum
)
372 if (nObjNum
>= maList
.size())
374 OSL_ASSERT(nObjNum
<maList
.size());
378 const size_t nCount
= GetObjCount();
379 rtl::Reference
<SdrObject
> pObj
=maList
[nObjNum
];
380 RemoveObjectFromContainer(nObjNum
);
382 DBG_ASSERT(pObj
!=nullptr,"Object to remove not found.");
385 // flushViewObjectContacts() clears the VOC's and those invalidate
386 pObj
->GetViewContact().flushViewObjectContacts();
387 DBG_ASSERT(pObj
->IsInserted(),"The object does not have the status Inserted.");
389 // TODO: We need a different broadcast here.
390 if (pObj
->getSdrPageFromSdrObject()!=nullptr)
392 SdrHint
aHint(SdrHintKind::ObjectRemoved
, *pObj
);
393 pObj
->getSdrModelFromSdrObject().Broadcast(aHint
);
396 pObj
->getSdrModelFromSdrObject().SetChanged();
398 // tdf#121022 Do first remove from SdrObjList - InsertedStateChange
399 // relies now on IsInserted which uses getParentSdrObjListFromSdrObject
400 pObj
->setParentOfSdrObject(nullptr);
402 // calls, among other things, the UserCall
403 pObj
->InsertedStateChange();
405 if (!mbObjOrdNumsDirty
)
407 // optimization for the case that the last object is removed
408 if (nObjNum
+1!=nCount
) {
409 mbObjOrdNumsDirty
=true;
413 SetSdrObjListRectsDirty();
414 SdrObject
* pParentSdrObject(getSdrObjectFromSdrObjList());
416 if(pParentSdrObject
&& !GetObjCount())
418 // empty group created; it needs to be repainted since it's
419 // visualization changes
420 pParentSdrObject
->ActionChanged();
426 rtl::Reference
<SdrObject
> SdrObjList::ReplaceObject(SdrObject
* pNewObj
, size_t nObjNum
)
428 if (nObjNum
>= maList
.size())
430 OSL_ASSERT(nObjNum
<maList
.size());
433 if (pNewObj
== nullptr)
435 OSL_ASSERT(pNewObj
!=nullptr);
439 rtl::Reference
<SdrObject
> pObj
=maList
[nObjNum
];
440 DBG_ASSERT(pObj
!=nullptr,"SdrObjList::ReplaceObject: Could not find object to remove.");
442 DBG_ASSERT(pObj
->IsInserted(),"SdrObjList::ReplaceObject: the object does not have status Inserted.");
444 // TODO: We need a different broadcast here.
445 if (pObj
->getSdrPageFromSdrObject()!=nullptr)
447 SdrHint
aHint(SdrHintKind::ObjectRemoved
, *pObj
);
448 pObj
->getSdrModelFromSdrObject().Broadcast(aHint
);
451 // Change parent and replace in SdrObjList
452 pObj
->setParentOfSdrObject(nullptr);
453 ReplaceObjectInContainer(*pNewObj
,nObjNum
);
455 // tdf#121022 InsertedStateChange uses the parent
456 // to detect if pObj is inserted or not, so have to call
457 // it *after* changing these settings, else an obviously wrong
458 // 'SdrUserCallType::Inserted' would be sent
459 pObj
->InsertedStateChange();
461 // flushViewObjectContacts() clears the VOC's and those
462 // trigger the evtl. needed invalidate(s)
463 pObj
->GetViewContact().flushViewObjectContacts();
465 // Setup data at new SdrObject - it already *is* inserted to
466 // the SdrObjList due to 'ReplaceObjectInContainer' above
467 pNewObj
->SetOrdNum(nObjNum
);
468 pNewObj
->setParentOfSdrObject(this);
470 // Inform the parent about change to allow invalidations at
471 // evtl. existing parent visualisations, but also react on
472 // newly inserted SdrObjects (as e.g. GraphCtrlUserCall does)
473 impChildInserted(*pNewObj
);
475 pNewObj
->InsertedStateChange();
477 // TODO: We need a different broadcast here.
478 if (pNewObj
->getSdrPageFromSdrObject()!=nullptr) {
479 SdrHint
aHint(SdrHintKind::ObjectInserted
, *pNewObj
);
480 pNewObj
->getSdrModelFromSdrObject().Broadcast(aHint
);
483 pNewObj
->getSdrModelFromSdrObject().SetChanged();
485 SetSdrObjListRectsDirty();
490 SdrObject
* SdrObjList::SetObjectOrdNum(size_t nOldObjNum
, size_t nNewObjNum
)
492 if (nOldObjNum
>= maList
.size() || nNewObjNum
>= maList
.size())
494 OSL_ASSERT(nOldObjNum
<maList
.size());
495 OSL_ASSERT(nNewObjNum
<maList
.size());
499 rtl::Reference
<SdrObject
> pObj
=maList
[nOldObjNum
];
500 if (nOldObjNum
==nNewObjNum
) return pObj
.get();
501 DBG_ASSERT(pObj
!=nullptr,"SdrObjList::SetObjectOrdNum: Object not found.");
503 DBG_ASSERT(pObj
->IsInserted(),"SdrObjList::SetObjectOrdNum: the object does not have status Inserted.");
504 RemoveObjectFromContainer(nOldObjNum
);
505 InsertObjectIntoContainer(*pObj
,nNewObjNum
);
507 // No need to delete visualisation data since same object
508 // gets inserted again. Also a single ActionChanged is enough
509 pObj
->ActionChanged();
511 pObj
->SetOrdNum(nNewObjNum
);
512 mbObjOrdNumsDirty
=true;
514 // TODO: We need a different broadcast here.
515 if (pObj
->getSdrPageFromSdrObject()!=nullptr)
516 pObj
->getSdrModelFromSdrObject().Broadcast(SdrHint(SdrHintKind::ObjectChange
, *pObj
));
517 pObj
->getSdrModelFromSdrObject().SetChanged();
522 void SdrObjList::SetExistingObjectOrdNum(SdrObject
* pObj
, size_t nNewObjNum
)
524 assert(std::find(maList
.begin(), maList
.end(), pObj
) != maList
.end() && "This method requires that the child object already be inserted");
525 assert(pObj
->IsInserted() && "SdrObjList::SetObjectOrdNum: the object does not have status Inserted.");
527 // I am deliberately bypassing getOrdNum() because I don't want to unnecessarily
528 // trigger RecalcObjOrdNums()
529 const sal_uInt32 nOldOrdNum
= pObj
->m_nOrdNum
;
530 if (!mbObjOrdNumsDirty
&& nOldOrdNum
== nNewObjNum
)
533 // Update the navigation positions.
534 if (HasObjectNavigationOrder())
536 unotools::WeakReference
<SdrObject
> aReference (pObj
);
537 auto iObject
= ::std::find(
538 mxNavigationOrder
->begin(),
539 mxNavigationOrder
->end(),
541 mxNavigationOrder
->erase(iObject
);
542 mbIsNavigationOrderDirty
= true;
543 // The new object does not have a user defined position so append it
545 pObj
->SetNavigationPosition(mxNavigationOrder
->size());
546 mxNavigationOrder
->push_back(pObj
);
548 if (nOldOrdNum
< maList
.size() && maList
[nOldOrdNum
] == pObj
)
549 maList
.erase(maList
.begin()+nOldOrdNum
);
552 auto it
= std::find(maList
.begin(), maList
.end(), pObj
);
555 // Insert object into object list. Because the insert() method requires
556 // a valid iterator as insertion position, we have to use push_back() to
557 // insert at the end of the list.
558 if (nNewObjNum
>= maList
.size())
559 maList
.push_back(pObj
);
561 maList
.insert(maList
.begin()+nNewObjNum
, pObj
);
563 mbObjOrdNumsDirty
=true;
565 // No need to delete visualisation data since same object
566 // gets inserted again. Also a single ActionChanged is enough
567 pObj
->ActionChanged();
569 pObj
->SetOrdNum(nNewObjNum
);
570 mbObjOrdNumsDirty
=true;
572 // TODO: We need a different broadcast here.
573 if (pObj
->getSdrPageFromSdrObject()!=nullptr)
574 pObj
->getSdrModelFromSdrObject().Broadcast(SdrHint(SdrHintKind::ObjectChange
, *pObj
));
575 pObj
->getSdrModelFromSdrObject().SetChanged();
578 void SdrObjList::sort( std::vector
<sal_Int32
>& sortOrder
)
580 // no negative indexes and indexes larger than maList size are allowed
581 auto it
= std::find_if( sortOrder
.begin(), sortOrder
.end(), [this](const sal_Int32
& rIt
)
582 { return ( rIt
< 0 || o3tl::make_unsigned(rIt
) >= maList
.size() ); } );
583 if ( it
!= sortOrder
.end())
584 throw css::lang::IllegalArgumentException("negative index of shape", nullptr, 1);
587 std::vector
<bool> aNoDuplicates(sortOrder
.size(), false);
588 for (size_t i
= 0; i
< sortOrder
.size(); ++i
)
590 size_t idx
= static_cast<size_t>( sortOrder
[i
] );
592 if ( aNoDuplicates
[idx
] )
593 throw css::lang::IllegalArgumentException("duplicate index of shape", nullptr, 2);
595 aNoDuplicates
[idx
] = true;
598 // example sortOrder [2 0 1]
599 // example maList [T T S T T] ( T T = shape with textbox, S = just a shape )
600 // (shapes at positions 0 and 2 have a textbox)
602 std::deque
<rtl::Reference
<SdrObject
>> aNewList(maList
.size());
603 std::set
<sal_Int32
> aShapesWithTextbox
;
604 std::vector
<sal_Int32
> aIncrements
;
605 std::vector
<sal_Int32
> aDuplicates
;
607 if ( maList
.size() > 1)
609 for (size_t i
= 1; i
< maList
.size(); ++i
)
611 // if this shape is a textbox, then look at its left neighbour
612 // (shape this textbox is in)
613 // and insert the number of textboxes to the left of it
614 if (maList
[i
]->IsTextBox())
615 aShapesWithTextbox
.insert( i
- 1 - aShapesWithTextbox
.size() );
617 // example aShapesWithTextbox [0 2]
620 if (aShapesWithTextbox
.size() != maList
.size() - sortOrder
.size())
622 throw lang::IllegalArgumentException("mismatch of no. of shapes", nullptr, 0);
625 for (size_t i
= 0; i
< sortOrder
.size(); ++i
)
628 if (aShapesWithTextbox
.count(sortOrder
[i
]) > 0)
629 aDuplicates
.push_back(sortOrder
[i
]);
631 aDuplicates
.push_back(sortOrder
[i
]);
633 // example aDuplicates [2 2 0 0 1]
635 assert(aDuplicates
.size() == maList
.size());
637 aIncrements
.push_back(0);
638 for (size_t i
= 1; i
< sortOrder
.size(); ++i
)
640 if (aShapesWithTextbox
.count(i
- 1))
641 aIncrements
.push_back(aIncrements
[i
-1] + 1 );
643 aIncrements
.push_back(aIncrements
[i
-1]);
645 // example aIncrements [0 1 1]
647 assert(aIncrements
.size() == sortOrder
.size());
649 std::vector
<sal_Int32
> aNewSortOrder(maList
.size());
650 sal_Int32 nPrev
= -1;
651 for (size_t i
= 0; i
< aDuplicates
.size(); ++i
)
653 if (nPrev
!= aDuplicates
[i
])
654 aNewSortOrder
[i
] = aDuplicates
[i
] + aIncrements
[aDuplicates
[i
]];
656 aNewSortOrder
[i
] = aNewSortOrder
[i
-1] + 1;
658 nPrev
= aDuplicates
[i
];
660 // example aNewSortOrder [3 4 0 1 2]
662 assert(aNewSortOrder
.size() == maList
.size());
666 std::vector
<sal_Int32
> tmp(aNewSortOrder
);
667 std::sort(tmp
.begin(), tmp
.end());
668 for (size_t i
= 0; i
< tmp
.size(); ++i
)
670 assert(size_t(tmp
[i
]) == i
);
675 SdrModel
& rModel(getSdrPageFromSdrObjList()->getSdrModelFromSdrPage());
676 bool const isUndo(rModel
.IsUndoEnabled());
679 rModel
.AddUndo(SdrUndoFactory::CreateUndoSort(*getSdrPageFromSdrObjList(), sortOrder
));
682 for (size_t i
= 0; i
< aNewSortOrder
.size(); ++i
)
684 aNewList
[i
] = maList
[ aNewSortOrder
[i
] ];
685 aNewList
[i
]->SetOrdNum(i
);
688 std::swap(aNewList
, maList
);
691 const tools::Rectangle
& SdrObjList::GetAllObjSnapRect() const
694 const_cast<SdrObjList
*>(this)->RecalcRects();
695 const_cast<SdrObjList
*>(this)->mbRectsDirty
=false;
697 return maSdrObjListSnapRect
;
700 const tools::Rectangle
& SdrObjList::GetAllObjBoundRect() const
702 // #i106183# for deep group hierarchies like in chart2, the invalidates
703 // through the hierarchy are not correct; use a 2nd hint for the needed
704 // recalculation. Future versions will have no bool flag at all, but
705 // just maSdrObjListOutRect in empty state to represent an invalid state, thus
706 // it's a step in the right direction.
707 if (mbRectsDirty
|| maSdrObjListOutRect
.IsEmpty())
709 const_cast<SdrObjList
*>(this)->RecalcRects();
710 const_cast<SdrObjList
*>(this)->mbRectsDirty
=false;
712 return maSdrObjListOutRect
;
715 void SdrObjList::NbcReformatAllTextObjects()
717 size_t nCount
=GetObjCount();
722 SdrObject
* pObj
= GetObj(nNum
);
724 pObj
->NbcReformatText();
725 nCount
=GetObjCount(); // ReformatText may delete an object
731 void SdrObjList::ReformatAllTextObjects()
733 NbcReformatAllTextObjects();
736 /** steps over all available objects and reformats all
737 edge objects that are connected to other objects so that
738 they may reposition themselves.
740 void SdrObjList::ReformatAllEdgeObjects()
742 ImplReformatAllEdgeObjects(*this);
745 void SdrObjList::ImplReformatAllEdgeObjects(const SdrObjList
& rObjList
)
747 // #i120437# go over whole hierarchy, not only over object level null (seen from grouping)
748 for(size_t nIdx(0), nCount(rObjList
.GetObjCount()); nIdx
< nCount
; ++nIdx
)
750 SdrObject
* pSdrObject(rObjList
.GetObjectForNavigationPosition(nIdx
));
751 const SdrObjList
* pChildren(pSdrObject
->getChildrenOfSdrObject());
752 const bool bIsGroup(nullptr != pChildren
);
755 // Check IsVirtualObj because sometimes we get SwDrawVirtObj here
756 if (pSdrObject
->GetObjIdentifier() == SdrObjKind::Edge
757 && !pSdrObject
->IsVirtualObj())
759 SdrEdgeObj
* pSdrEdgeObj
= static_cast< SdrEdgeObj
* >(pSdrObject
);
760 pSdrEdgeObj
->Reformat();
765 ImplReformatAllEdgeObjects(*pChildren
);
770 void SdrObjList::BurnInStyleSheetAttributes()
772 for (const rtl::Reference
<SdrObject
>& pObj
: *this)
773 pObj
->BurnInStyleSheetAttributes();
776 size_t SdrObjList::GetObjCount() const
778 return maList
.size();
782 SdrObject
* SdrObjList::GetObj(size_t nNum
) const
784 if (nNum
< maList
.size())
785 return maList
[nNum
].get();
790 SdrObject
* SdrObjList::GetObjByName(std::u16string_view sName
) const
792 for (const rtl::Reference
<SdrObject
>& pObj
: *this)
794 if (pObj
->GetName() == sName
)
801 bool SdrObjList::IsReadOnly() const
804 SdrObject
* pParentSdrObject(getSdrObjectFromSdrObjList());
806 if(nullptr != pParentSdrObject
)
808 SdrPage
* pSdrPage(pParentSdrObject
->getSdrPageFromSdrObject());
810 if(nullptr != pSdrPage
)
812 bRet
= pSdrPage
->IsReadOnly();
819 void SdrObjList::FlattenGroups()
821 const size_t nObj
= GetObjCount();
822 for( size_t i
= nObj
; i
>0; )
826 void SdrObjList::UnGroupObj( size_t nObjNum
)
828 // if the given object is no group, this method is a noop
829 SdrObject
* pUngroupObj
= GetObj( nObjNum
);
832 SdrObjList
* pSrcLst
= pUngroupObj
->GetSubList();
834 if(auto pUngroupGroup
= dynamic_cast<SdrObjGroup
*>( pUngroupObj
))
836 // ungroup recursively (has to be head recursion,
837 // otherwise our indices will get trashed when doing it in
839 pSrcLst
->FlattenGroups();
841 // the position at which we insert the members of rUngroupGroup
842 size_t nInsertPos( pUngroupGroup
->GetOrdNum() );
844 const size_t nCount
= pSrcLst
->GetObjCount();
845 for( size_t i
=0; i
<nCount
; ++i
)
847 rtl::Reference
<SdrObject
> pObj
= pSrcLst
->RemoveObject(0);
848 InsertObject(pObj
.get(), nInsertPos
);
852 RemoveObject(nInsertPos
);
857 OSL_FAIL("SdrObjList::UnGroupObj: object index invalid");
861 bool SdrObjList::HasObjectNavigationOrder() const { return bool(mxNavigationOrder
); }
863 void SdrObjList::SetObjectNavigationPosition (
865 const sal_uInt32 nNewPosition
)
867 // When the navigation order container has not yet been created then
868 // create one now. It is initialized with the z-order taken from
870 if (!mxNavigationOrder
)
872 mxNavigationOrder
.emplace(maList
.begin(), maList
.end());
874 OSL_ASSERT(bool(mxNavigationOrder
));
875 OSL_ASSERT( mxNavigationOrder
->size() == maList
.size());
877 unotools::WeakReference
<SdrObject
> aReference (&rObject
);
879 // Look up the object whose navigation position is to be changed.
880 auto iObject
= ::std::find(
881 mxNavigationOrder
->begin(),
882 mxNavigationOrder
->end(),
884 if (iObject
== mxNavigationOrder
->end())
886 // The given object is not a member of the navigation order.
890 // Move the object to its new position.
891 const sal_uInt32 nOldPosition
= ::std::distance(mxNavigationOrder
->begin(), iObject
);
892 if (nOldPosition
== nNewPosition
)
895 mxNavigationOrder
->erase(iObject
);
896 sal_uInt32
nInsertPosition (nNewPosition
);
897 // Adapt insertion position for the just erased object.
898 if (nNewPosition
>= nOldPosition
)
899 nInsertPosition
-= 1;
900 if (nInsertPosition
>= mxNavigationOrder
->size())
901 mxNavigationOrder
->push_back(aReference
);
903 mxNavigationOrder
->insert(mxNavigationOrder
->begin()+nInsertPosition
, aReference
);
905 mbIsNavigationOrderDirty
= true;
907 // The navigation order is written out to file so mark the model as modified.
908 rObject
.getSdrModelFromSdrObject().SetChanged();
912 SdrObject
* SdrObjList::GetObjectForNavigationPosition (const sal_uInt32 nNavigationPosition
) const
914 if (HasObjectNavigationOrder())
916 // There is a user defined navigation order. Make sure the object
917 // index is correct and look up the object in mxNavigationOrder.
918 if (nNavigationPosition
>= mxNavigationOrder
->size())
920 OSL_ASSERT(nNavigationPosition
< mxNavigationOrder
->size());
923 return (*mxNavigationOrder
)[nNavigationPosition
].get().get();
927 // There is no user defined navigation order. Use the z-order
929 if (nNavigationPosition
>= maList
.size())
931 OSL_ASSERT(nNavigationPosition
< maList
.size());
934 return maList
[nNavigationPosition
].get();
940 void SdrObjList::ClearObjectNavigationOrder()
942 mxNavigationOrder
.reset();
943 mbIsNavigationOrderDirty
= true;
947 bool SdrObjList::RecalcNavigationPositions()
949 if (mbIsNavigationOrderDirty
)
951 if (mxNavigationOrder
)
953 mbIsNavigationOrderDirty
= false;
955 sal_uInt32
nIndex (0);
956 for (auto& rpObject
: *mxNavigationOrder
)
958 rpObject
.get()->SetNavigationPosition(nIndex
);
964 return bool(mxNavigationOrder
);
968 void SdrObjList::SetNavigationOrder (const uno::Reference
<container::XIndexAccess
>& rxOrder
)
972 const sal_Int32 nCount
= rxOrder
->getCount();
973 if (static_cast<sal_uInt32
>(nCount
) != maList
.size())
976 if (!mxNavigationOrder
)
977 mxNavigationOrder
= std::vector
<unotools::WeakReference
<SdrObject
>>(nCount
);
979 for (sal_Int32 nIndex
=0; nIndex
<nCount
; ++nIndex
)
981 uno::Reference
<uno::XInterface
> xShape (rxOrder
->getByIndex(nIndex
), uno::UNO_QUERY
);
982 SdrObject
* pObject
= SdrObject::getSdrObjectFromXShape(xShape
);
983 if (pObject
== nullptr)
985 (*mxNavigationOrder
)[nIndex
] = pObject
;
988 mbIsNavigationOrderDirty
= true;
992 ClearObjectNavigationOrder();
997 void SdrObjList::InsertObjectIntoContainer (
999 const sal_uInt32 nInsertPosition
)
1001 OSL_ASSERT(nInsertPosition
<=maList
.size());
1003 // Update the navigation positions.
1004 if (HasObjectNavigationOrder())
1006 // The new object does not have a user defined position so append it
1008 rObject
.SetNavigationPosition(mxNavigationOrder
->size());
1009 mxNavigationOrder
->push_back(&rObject
);
1012 // Insert object into object list. Because the insert() method requires
1013 // a valid iterator as insertion position, we have to use push_back() to
1014 // insert at the end of the list.
1015 if (nInsertPosition
>= maList
.size())
1016 maList
.push_back(&rObject
);
1018 maList
.insert(maList
.begin()+nInsertPosition
, &rObject
);
1019 mbObjOrdNumsDirty
=true;
1023 void SdrObjList::ReplaceObjectInContainer (
1024 SdrObject
& rNewObject
,
1025 const sal_uInt32 nObjectPosition
)
1027 if (nObjectPosition
>= maList
.size())
1029 OSL_ASSERT(nObjectPosition
<maList
.size());
1033 // Update the navigation positions.
1034 if (HasObjectNavigationOrder())
1036 // A user defined position of the object that is to be replaced is
1037 // not transferred to the new object so erase the former and append
1038 // the later object from/to the navigation order.
1039 OSL_ASSERT(nObjectPosition
< maList
.size());
1040 unotools::WeakReference
<SdrObject
> aReference (maList
[nObjectPosition
].get());
1041 auto iObject
= ::std::find(
1042 mxNavigationOrder
->begin(),
1043 mxNavigationOrder
->end(),
1045 if (iObject
!= mxNavigationOrder
->end())
1046 mxNavigationOrder
->erase(iObject
);
1048 mxNavigationOrder
->push_back(&rNewObject
);
1050 mbIsNavigationOrderDirty
= true;
1053 maList
[nObjectPosition
] = &rNewObject
;
1054 mbObjOrdNumsDirty
=true;
1058 void SdrObjList::RemoveObjectFromContainer (
1059 const sal_uInt32 nObjectPosition
)
1061 if (nObjectPosition
>= maList
.size())
1063 OSL_ASSERT(nObjectPosition
<maList
.size());
1067 // Update the navigation positions.
1068 if (HasObjectNavigationOrder())
1070 unotools::WeakReference
<SdrObject
> aReference (maList
[nObjectPosition
]);
1071 auto iObject
= ::std::find(
1072 mxNavigationOrder
->begin(),
1073 mxNavigationOrder
->end(),
1075 if (iObject
!= mxNavigationOrder
->end())
1076 mxNavigationOrder
->erase(iObject
);
1077 mbIsNavigationOrderDirty
= true;
1080 maList
.erase(maList
.begin()+nObjectPosition
);
1081 mbObjOrdNumsDirty
=true;
1084 void SdrObjList::dumpAsXml(xmlTextWriterPtr pWriter
) const
1086 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SdrObjList"));
1087 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
1088 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
1090 for (const rtl::Reference
<SdrObject
>& pObject
: *this)
1091 pObject
->dumpAsXml(pWriter
);
1093 (void)xmlTextWriterEndElement(pWriter
);
1097 void SdrPageGridFrameList::Clear()
1099 sal_uInt16 nCount
=GetCount();
1100 for (sal_uInt16 i
=0; i
<nCount
; i
++) {
1101 delete GetObject(i
);
1109 void SdrPage::AddPageUser(sdr::PageUser
& rNewUser
)
1111 maPageUsers
.push_back(&rNewUser
);
1114 void SdrPage::RemovePageUser(sdr::PageUser
& rOldUser
)
1116 const sdr::PageUserVector::iterator aFindResult
= ::std::find(maPageUsers
.begin(), maPageUsers
.end(), &rOldUser
);
1117 if(aFindResult
!= maPageUsers
.end())
1119 maPageUsers
.erase(aFindResult
);
1124 // DrawContact section
1126 std::unique_ptr
<sdr::contact::ViewContact
> SdrPage::CreateObjectSpecificViewContact()
1128 return std::make_unique
<sdr::contact::ViewContactOfSdrPage
>(*this);
1131 const sdr::contact::ViewContact
& SdrPage::GetViewContact() const
1134 const_cast<SdrPage
*>(this)->mpViewContact
=
1135 const_cast<SdrPage
*>(this)->CreateObjectSpecificViewContact();
1137 return *mpViewContact
;
1140 sdr::contact::ViewContact
& SdrPage::GetViewContact()
1143 mpViewContact
= CreateObjectSpecificViewContact();
1145 return *mpViewContact
;
1148 void SdrPageProperties::ImpRemoveStyleSheet()
1152 EndListening(*mpStyleSheet
);
1153 maProperties
.SetParent(nullptr);
1154 mpStyleSheet
= nullptr;
1158 void SdrPageProperties::ImpAddStyleSheet(SfxStyleSheet
& rNewStyleSheet
)
1160 if(mpStyleSheet
!= &rNewStyleSheet
)
1162 ImpRemoveStyleSheet();
1163 mpStyleSheet
= &rNewStyleSheet
;
1164 StartListening(rNewStyleSheet
);
1165 maProperties
.SetParent(&rNewStyleSheet
.GetItemSet());
1169 static void ImpPageChange(SdrPage
& rSdrPage
)
1171 rSdrPage
.ActionChanged();
1172 rSdrPage
.getSdrModelFromSdrPage().SetChanged();
1173 SdrHint
aHint(SdrHintKind::PageOrderChange
, &rSdrPage
);
1174 rSdrPage
.getSdrModelFromSdrPage().Broadcast(aHint
);
1177 SdrPageProperties::SdrPageProperties(SdrPage
& rSdrPage
)
1178 : mpSdrPage(&rSdrPage
)
1179 , mpStyleSheet(nullptr)
1181 mpSdrPage
->getSdrModelFromSdrPage().GetItemPool(),
1182 svl::Items
<XATTR_FILL_FIRST
, XATTR_FILL_LAST
>)
1184 if (!rSdrPage
.IsMasterPage())
1186 maProperties
.Put(XFillStyleItem(drawing::FillStyle_NONE
));
1190 SdrPageProperties::~SdrPageProperties()
1192 ImpRemoveStyleSheet();
1195 void SdrPageProperties::Notify(SfxBroadcaster
& /*rBC*/, const SfxHint
& rHint
)
1197 switch(rHint
.GetId())
1199 case SfxHintId::DataChanged
:
1201 // notify change, broadcast
1202 ImpPageChange(*mpSdrPage
);
1205 case SfxHintId::Dying
:
1207 // Style needs to be forgotten
1208 ImpRemoveStyleSheet();
1215 bool SdrPageProperties::isUsedByModel() const
1218 return mpSdrPage
->IsInserted();
1222 void SdrPageProperties::PutItemSet(const SfxItemSet
& rSet
)
1224 OSL_ENSURE(!mpSdrPage
->IsMasterPage(), "Item set at MasterPage Attributes (!)");
1225 maProperties
.Put(rSet
);
1226 ImpPageChange(*mpSdrPage
);
1229 void SdrPageProperties::PutItem(const SfxPoolItem
& rItem
)
1231 OSL_ENSURE(!mpSdrPage
->IsMasterPage(), "Item set at MasterPage Attributes (!)");
1232 maProperties
.Put(rItem
);
1233 ImpPageChange(*mpSdrPage
);
1236 void SdrPageProperties::ClearItem(const sal_uInt16 nWhich
)
1238 maProperties
.ClearItem(nWhich
);
1239 ImpPageChange(*mpSdrPage
);
1242 void SdrPageProperties::SetStyleSheet(SfxStyleSheet
* pStyleSheet
)
1246 ImpAddStyleSheet(*pStyleSheet
);
1250 ImpRemoveStyleSheet();
1253 ImpPageChange(*mpSdrPage
);
1256 void SdrPageProperties::setTheme(std::shared_ptr
<model::Theme
> const& pTheme
)
1261 // Only set the theme on a master page, else set it on the model
1263 if (mpSdrPage
->IsMasterPage())
1265 if (mpTheme
!= pTheme
)
1270 mpSdrPage
->getSdrModelFromSdrPage().setTheme(pTheme
);
1274 std::shared_ptr
<model::Theme
> const& SdrPageProperties::getTheme() const
1276 // if set - page theme has priority
1279 // else the model theme
1281 return mpSdrPage
->getSdrModelFromSdrPage().getTheme();
1282 // else return empty shared_ptr
1286 void SdrPageProperties::dumpAsXml(xmlTextWriterPtr pWriter
) const
1288 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SdrPageProperties"));
1289 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
1293 mpTheme
->dumpAsXml(pWriter
);
1296 (void)xmlTextWriterEndElement(pWriter
);
1299 SdrPage::SdrPage(SdrModel
& rModel
, bool bMasterPage
)
1300 : mrSdrModelFromSdrPage(rModel
),
1307 mpLayerAdmin(new SdrLayerAdmin(&rModel
.GetLayerAdmin())),
1309 mbMaster(bMasterPage
),
1311 mbObjectsNotPersistent(false),
1312 mbPageBorderOnlyLeftRight(false)
1314 mpSdrPageProperties
.reset(new SdrPageProperties(*this));
1319 if( mxUnoPage
.is() ) try
1321 uno::Reference
< lang::XComponent
> xPageComponent( mxUnoPage
, uno::UNO_QUERY_THROW
);
1323 xPageComponent
->dispose();
1325 catch( const uno::Exception
& )
1327 DBG_UNHANDLED_EXCEPTION("svx");
1330 // tell all the registered PageUsers that the page is in destruction
1331 // This causes some (all?) PageUsers to remove themselves from the list
1332 // of page users. Therefore we have to use a copy of the list for the
1334 sdr::PageUserVector
aListCopy (maPageUsers
.begin(), maPageUsers
.end());
1335 for(sdr::PageUser
* pPageUser
: aListCopy
)
1337 DBG_ASSERT(pPageUser
, "SdrPage::~SdrPage: corrupt PageUser list (!)");
1338 pPageUser
->PageInDestruction(*this);
1341 // Clear the vector. This means that user do not need to call RemovePageUser()
1342 // when they get called from PageInDestruction().
1343 maPageUsers
.clear();
1345 mpLayerAdmin
.reset();
1347 TRG_ClearMasterPage();
1349 mpViewContact
.reset();
1350 mpSdrPageProperties
.reset();
1353 void SdrPage::lateInit(const SdrPage
& rSrcPage
)
1355 assert(!mpViewContact
);
1356 assert(!mxUnoPage
.is());
1358 // copy all the local parameters to make this instance
1359 // a valid copy of source page before copying and inserting
1360 // the contained objects
1361 mbMaster
= rSrcPage
.mbMaster
;
1362 mbPageBorderOnlyLeftRight
= rSrcPage
.mbPageBorderOnlyLeftRight
;
1363 mnWidth
= rSrcPage
.mnWidth
;
1364 mnHeight
= rSrcPage
.mnHeight
;
1365 mnBorderLeft
= rSrcPage
.mnBorderLeft
;
1366 mnBorderUpper
= rSrcPage
.mnBorderUpper
;
1367 mnBorderRight
= rSrcPage
.mnBorderRight
;
1368 mnBorderLower
= rSrcPage
.mnBorderLower
;
1369 mbBackgroundFullSize
= rSrcPage
.mbBackgroundFullSize
;
1370 m_nPageNum
= rSrcPage
.m_nPageNum
;
1372 if(rSrcPage
.TRG_HasMasterPage())
1374 TRG_SetMasterPage(rSrcPage
.TRG_GetMasterPage());
1375 TRG_SetMasterPageVisibleLayers(rSrcPage
.TRG_GetMasterPageVisibleLayers());
1379 TRG_ClearMasterPage();
1382 mbObjectsNotPersistent
= rSrcPage
.mbObjectsNotPersistent
;
1385 mpSdrPageProperties
.reset(new SdrPageProperties(*this));
1389 mpSdrPageProperties
->PutItemSet(rSrcPage
.getSdrPageProperties().GetItemSet());
1392 mpSdrPageProperties
->SetStyleSheet(rSrcPage
.getSdrPageProperties().GetStyleSheet());
1395 // Now copy the contained objects
1396 if(0 != rSrcPage
.GetObjCount())
1398 CopyObjects(rSrcPage
);
1402 rtl::Reference
<SdrPage
> SdrPage::CloneSdrPage(SdrModel
& rTargetModel
) const
1404 rtl::Reference
<SdrPage
> pClonedPage(new SdrPage(rTargetModel
));
1405 pClonedPage
->lateInit(*this);
1409 void SdrPage::SetSize(const Size
& aSiz
)
1411 bool bChanged(false);
1413 if(aSiz
.Width() != mnWidth
)
1415 mnWidth
= aSiz
.Width();
1419 if(aSiz
.Height() != mnHeight
)
1421 mnHeight
= aSiz
.Height();
1431 Size
SdrPage::GetSize() const
1433 return Size(mnWidth
,mnHeight
);
1436 tools::Long
SdrPage::GetWidth() const
1441 void SdrPage::SetOrientation(Orientation eOri
)
1443 // square: handle like portrait format
1444 Size
aSiz(GetSize());
1445 if (aSiz
.Width()!=aSiz
.Height()) {
1446 if ((eOri
==Orientation::Portrait
) == (aSiz
.Width()>aSiz
.Height())) {
1447 // coverity[swapped_arguments : FALSE] - this is in the correct order
1448 SetSize(Size(aSiz
.Height(),aSiz
.Width()));
1453 Orientation
SdrPage::GetOrientation() const
1455 // square: handle like portrait format
1456 Orientation eRet
=Orientation::Portrait
;
1457 Size
aSiz(GetSize());
1458 if (aSiz
.Width()>aSiz
.Height()) eRet
=Orientation::Landscape
;
1462 tools::Long
SdrPage::GetHeight() const
1467 void SdrPage::SetBorder(sal_Int32 nLft
, sal_Int32 nUpp
, sal_Int32 nRgt
, sal_Int32 nLwr
)
1469 bool bChanged(false);
1471 if(mnBorderLeft
!= nLft
)
1473 mnBorderLeft
= nLft
;
1477 if(mnBorderUpper
!= nUpp
)
1479 mnBorderUpper
= nUpp
;
1483 if(mnBorderRight
!= nRgt
)
1485 mnBorderRight
= nRgt
;
1489 if(mnBorderLower
!= nLwr
)
1491 mnBorderLower
= nLwr
;
1501 void SdrPage::SetLeftBorder(sal_Int32 nBorder
)
1503 if(mnBorderLeft
!= nBorder
)
1505 mnBorderLeft
= nBorder
;
1510 void SdrPage::SetUpperBorder(sal_Int32 nBorder
)
1512 if(mnBorderUpper
!= nBorder
)
1514 mnBorderUpper
= nBorder
;
1519 void SdrPage::SetRightBorder(sal_Int32 nBorder
)
1521 if(mnBorderRight
!= nBorder
)
1523 mnBorderRight
=nBorder
;
1528 void SdrPage::SetLowerBorder(sal_Int32 nBorder
)
1530 if(mnBorderLower
!= nBorder
)
1532 mnBorderLower
=nBorder
;
1537 sal_Int32
SdrPage::GetLeftBorder() const
1539 return mnBorderLeft
;
1542 sal_Int32
SdrPage::GetUpperBorder() const
1544 return mnBorderUpper
;
1547 sal_Int32
SdrPage::GetRightBorder() const
1549 return mnBorderRight
;
1552 sal_Int32
SdrPage::GetLowerBorder() const
1554 return mnBorderLower
;
1557 void SdrPage::SetBackgroundFullSize(bool const bIn
)
1559 if (bIn
!= mbBackgroundFullSize
)
1561 mbBackgroundFullSize
= bIn
;
1566 bool SdrPage::IsBackgroundFullSize() const
1568 return mbBackgroundFullSize
;
1571 // #i68775# React on PageNum changes (from Model in most cases)
1572 void SdrPage::SetPageNum(sal_uInt16 nNew
)
1574 if(nNew
!= m_nPageNum
)
1579 // notify visualisations, also notifies e.g. buffered MasterPages
1584 sal_uInt16
SdrPage::GetPageNum() const
1590 if (getSdrModelFromSdrPage().IsMPgNumsDirty())
1591 getSdrModelFromSdrPage().RecalcPageNums(true);
1593 if (getSdrModelFromSdrPage().IsPagNumsDirty())
1594 getSdrModelFromSdrPage().RecalcPageNums(false);
1599 void SdrPage::SetChanged()
1601 // For test purposes, use the new ViewContact for change
1602 // notification now.
1604 getSdrModelFromSdrPage().SetChanged();
1607 SdrPage
* SdrPage::getSdrPageFromSdrObjList() const
1609 return const_cast< SdrPage
* >(this);
1612 // MasterPage interface
1614 void SdrPage::TRG_SetMasterPage(SdrPage
& rNew
)
1616 if(mpMasterPageDescriptor
&& &(mpMasterPageDescriptor
->GetUsedPage()) == &rNew
)
1619 if(mpMasterPageDescriptor
)
1620 TRG_ClearMasterPage();
1622 mpMasterPageDescriptor
.reset(new sdr::MasterPageDescriptor(*this, rNew
));
1623 GetViewContact().ActionChanged();
1626 void SdrPage::TRG_ClearMasterPage()
1628 if(mpMasterPageDescriptor
)
1632 // the flushViewObjectContacts() will do needed invalidates by deleting the involved VOCs
1633 mpMasterPageDescriptor
->GetUsedPage().GetViewContact().flushViewObjectContacts();
1635 mpMasterPageDescriptor
.reset();
1639 SdrPage
& SdrPage::TRG_GetMasterPage() const
1641 DBG_ASSERT(mpMasterPageDescriptor
!= nullptr, "TRG_GetMasterPage(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
1642 return mpMasterPageDescriptor
->GetUsedPage();
1645 const SdrLayerIDSet
& SdrPage::TRG_GetMasterPageVisibleLayers() const
1647 DBG_ASSERT(mpMasterPageDescriptor
!= nullptr, "TRG_GetMasterPageVisibleLayers(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
1648 return mpMasterPageDescriptor
->GetVisibleLayers();
1651 void SdrPage::TRG_SetMasterPageVisibleLayers(const SdrLayerIDSet
& rNew
)
1653 DBG_ASSERT(mpMasterPageDescriptor
!= nullptr, "TRG_SetMasterPageVisibleLayers(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
1654 mpMasterPageDescriptor
->SetVisibleLayers(rNew
);
1657 sdr::contact::ViewContact
& SdrPage::TRG_GetMasterPageDescriptorViewContact() const
1659 DBG_ASSERT(mpMasterPageDescriptor
!= nullptr, "TRG_GetMasterPageDescriptorViewContact(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
1660 return mpMasterPageDescriptor
->GetViewContact();
1663 // used from SdrModel::RemoveMasterPage
1664 void SdrPage::TRG_ImpMasterPageRemoved(const SdrPage
& rRemovedPage
)
1666 if(TRG_HasMasterPage())
1668 if(&TRG_GetMasterPage() == &rRemovedPage
)
1670 TRG_ClearMasterPage();
1675 void SdrPage::MakePageObjectsNamesUnique()
1677 std::unordered_set
<OUString
> aNameSet
;
1678 for (const rtl::Reference
<SdrObject
>& pObj
: *this)
1680 if (!pObj
->GetName().isEmpty())
1682 pObj
->MakeNameUnique(aNameSet
);
1683 SdrObjList
* pSdrObjList
= pObj
->GetSubList(); // group
1686 SdrObject
* pListObj
;
1687 SdrObjListIter
aIter(pSdrObjList
, SdrIterMode::DeepWithGroups
);
1688 while (aIter
.IsMore())
1690 pListObj
= aIter
.Next();
1691 pListObj
->MakeNameUnique(aNameSet
);
1698 const SdrPageGridFrameList
* SdrPage::GetGridFrameList(const SdrPageView
* /*pPV*/, const tools::Rectangle
* /*pRect*/) const
1703 const SdrLayerAdmin
& SdrPage::GetLayerAdmin() const
1705 return *mpLayerAdmin
;
1708 SdrLayerAdmin
& SdrPage::GetLayerAdmin()
1710 return *mpLayerAdmin
;
1713 OUString
SdrPage::GetLayoutName() const
1718 void SdrPage::SetInserted( bool bIns
)
1720 if( mbInserted
== bIns
)
1725 // #i120437# go over whole hierarchy, not only over object level null (seen from grouping)
1726 SdrObjListIter
aIter(this, SdrIterMode::DeepNoGroups
);
1728 while ( aIter
.IsMore() )
1730 SdrObject
* pObj
= aIter
.Next();
1731 if ( auto pOleObj
= dynamic_cast<SdrOle2Obj
* >(pObj
) )
1736 pOleObj
->Disconnect();
1741 void SdrPage::SetUnoPage(uno::Reference
<drawing::XDrawPage
> const& xNewPage
)
1743 mxUnoPage
= xNewPage
;
1746 uno::Reference
< uno::XInterface
> const & SdrPage::getUnoPage()
1748 if( !mxUnoPage
.is() )
1751 mxUnoPage
= createUnoPage();
1757 uno::Reference
< uno::XInterface
> SdrPage::createUnoPage()
1759 return cppu::getXWeak(new SvxDrawPage(this));
1762 SfxStyleSheet
* SdrPage::GetTextStyleSheetForObject( SdrObject
* pObj
) const
1764 return pObj
->GetStyleSheet();
1767 /** returns an averaged background color of this page */
1768 // #i75566# GetBackgroundColor -> GetPageBackgroundColor and bScreenDisplay hint value
1769 Color
SdrPage::GetPageBackgroundColor( SdrPageView
const * pView
, bool bScreenDisplay
) const
1773 if(bScreenDisplay
&& (!pView
|| pView
->GetApplicationDocumentColor() == COL_AUTO
))
1775 if (const SfxViewShell
* pViewShell
= SfxViewShell::Current())
1776 aColor
= pViewShell
->GetColorConfigColor(svtools::DOCCOLOR
);
1779 svtools::ColorConfig aColorConfig
;
1780 aColor
= aColorConfig
.GetColorValue( svtools::DOCCOLOR
).nColor
;
1785 aColor
= pView
->GetApplicationDocumentColor();
1788 const SfxItemSet
* pBackgroundFill
= &getSdrPageProperties().GetItemSet();
1790 if(!IsMasterPage() && TRG_HasMasterPage())
1792 if(drawing::FillStyle_NONE
== pBackgroundFill
->Get(XATTR_FILLSTYLE
).GetValue())
1794 pBackgroundFill
= &TRG_GetMasterPage().getSdrPageProperties().GetItemSet();
1798 if (auto oColor
= GetDraftFillColor(*pBackgroundFill
))
1804 /** *deprecated, use GetBackgroundColor with SdrPageView */
1805 Color
SdrPage::GetPageBackgroundColor() const
1806 // #i75566# GetBackgroundColor -> GetPageBackgroundColor
1808 return GetPageBackgroundColor( nullptr );
1811 /** this method returns true if the object from the ViewObjectContact should
1812 be visible on this page while rendering.
1813 bEdit selects if visibility test is for an editing view or a final render,
1816 bool SdrPage::checkVisibility(
1817 const sdr::contact::ViewObjectContact
& /*rOriginal*/,
1818 const sdr::contact::DisplayInfo
& /*rDisplayInfo*/,
1821 // this will be handled in the application if needed
1825 void SdrPage::dumpAsXml(xmlTextWriterPtr pWriter
) const
1827 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SdrPage"));
1828 SdrObjList::dumpAsXml(pWriter
);
1830 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("width"));
1831 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("value"), "%s",
1832 BAD_CAST(OString::number(mnWidth
).getStr()));
1833 (void)xmlTextWriterEndElement(pWriter
);
1834 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("height"));
1835 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("value"), "%s",
1836 BAD_CAST(OString::number(mnHeight
).getStr()));
1837 (void)xmlTextWriterEndElement(pWriter
);
1839 if (mpSdrPageProperties
)
1841 mpSdrPageProperties
->dumpAsXml(pWriter
);
1844 (void)xmlTextWriterEndElement(pWriter
);
1847 // DrawContact support: Methods for handling Page changes
1848 void SdrPage::ActionChanged()
1850 // Do necessary ViewContact actions
1851 GetViewContact().ActionChanged();
1853 // #i48535# also handle MasterPage change
1854 if(TRG_HasMasterPage())
1856 TRG_GetMasterPageDescriptorViewContact().ActionChanged();
1860 SdrPageProperties
& SdrPage::getSdrPageProperties()
1862 return *mpSdrPageProperties
;
1865 const SdrPageProperties
& SdrPage::getSdrPageProperties() const
1867 return *mpSdrPageProperties
;
1870 const SdrPageProperties
* SdrPage::getCorrectSdrPageProperties() const
1872 if(mpMasterPageDescriptor
)
1874 return mpMasterPageDescriptor
->getCorrectSdrPageProperties();
1878 return &getSdrPageProperties();
1883 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */