Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / svx / source / svdraw / svdpage.cxx
blobc1f8980f42361a1526c81975239c33e8ad9e845a
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 <memory>
21 #include <cassert>
22 #include <set>
23 #include <unordered_set>
25 #include <svx/svdpage.hxx>
27 #include <o3tl/safeint.hxx>
28 #include <string.h>
30 #include <tools/debug.hxx>
31 #include <tools/diagnose_ex.h>
33 #include <svtools/colorcfg.hxx>
34 #include <svx/svdetc.hxx>
35 #include <svx/svdobj.hxx>
36 #include <svx/svdogrp.hxx>
37 #include <svx/svdoedge.hxx>
38 #include <svx/svdoole2.hxx>
39 #include <svx/svditer.hxx>
40 #include <svx/svdmodel.hxx>
41 #include <svx/svdlayer.hxx>
42 #include <svx/svdpagv.hxx>
43 #include <svx/xfillit0.hxx>
44 #include <svx/fmdpage.hxx>
46 #include <sdr/contact/viewcontactofsdrpage.hxx>
47 #include <svx/sdr/contact/viewobjectcontact.hxx>
48 #include <svx/sdr/contact/displayinfo.hxx>
49 #include <algorithm>
50 #include <svl/hint.hxx>
51 #include <rtl/strbuf.hxx>
52 #include <libxml/xmlwriter.h>
54 #include <com/sun/star/lang/IllegalArgumentException.hpp>
56 using namespace ::com::sun::star;
58 const sal_Int32 InitialObjectContainerCapacity (64);
60 ////////////////////////////////////////////////////////////////////////////////////////////////////
61 // helper to allow changing parent at SdrObject, but only from SdrObjList
63 void SetParentAtSdrObjectFromSdrObjList(SdrObject& rSdrObject, SdrObjList* pNew)
65 rSdrObject.setParentOfSdrObject(pNew);
68 //////////////////////////////////////////////////////////////////////////////
70 SdrObjList::SdrObjList()
71 : maList(),
72 maSdrObjListOutRect(),
73 maSdrObjListSnapRect(),
74 mbObjOrdNumsDirty(false),
75 mbRectsDirty(false),
76 mxNavigationOrder(),
77 mbIsNavigationOrderDirty(false)
79 maList.reserve(InitialObjectContainerCapacity);
82 void SdrObjList::impClearSdrObjList(bool bBroadcast)
84 SdrModel* pSdrModelFromRemovedSdrObject(nullptr);
86 while(!maList.empty())
88 // remove last object from list
89 SdrObject* pObj(maList.back());
90 RemoveObjectFromContainer(maList.size()-1);
92 // flushViewObjectContacts() is done since SdrObject::Free is not guaranteed
93 // to delete the object and thus refresh visualisations
94 pObj->GetViewContact().flushViewObjectContacts();
96 if(bBroadcast)
98 if(nullptr == pSdrModelFromRemovedSdrObject)
100 pSdrModelFromRemovedSdrObject = &pObj->getSdrModelFromSdrObject();
103 // sent remove hint (after removal, see RemoveObject())
104 // TTTT SdrPage not needed, can be accessed using SdrObject
105 SdrHint aHint(SdrHintKind::ObjectRemoved, *pObj, getSdrPageFromSdrObjList());
106 pObj->getSdrModelFromSdrObject().Broadcast(aHint);
109 // delete the object itself
110 SdrObject::Free( pObj );
113 if(bBroadcast && nullptr != pSdrModelFromRemovedSdrObject)
115 pSdrModelFromRemovedSdrObject->SetChanged();
119 void SdrObjList::ClearSdrObjList()
121 // clear SdrObjects with broadcasting
122 impClearSdrObjList(true);
125 SdrObjList::~SdrObjList()
127 // clear SdrObjects without broadcasting
128 impClearSdrObjList(false);
131 SdrPage* SdrObjList::getSdrPageFromSdrObjList() const
133 // default is no page and returns zero
134 return nullptr;
137 SdrObject* SdrObjList::getSdrObjectFromSdrObjList() const
139 // default is no SdrObject (SdrObjGroup)
140 return nullptr;
143 void SdrObjList::CopyObjects(const SdrObjList& rSrcList)
145 // clear SdrObjects with broadcasting
146 ClearSdrObjList();
148 mbObjOrdNumsDirty = false;
149 mbRectsDirty = false;
150 size_t nCloneErrCnt(0);
151 const size_t nCount(rSrcList.GetObjCount());
153 if(nullptr == getSdrObjectFromSdrObjList() && nullptr == getSdrPageFromSdrObjList())
155 OSL_ENSURE(false, "SdrObjList which is not part of SdrPage or SdrObject (!)");
156 return;
159 SdrModel& rTargetSdrModel(nullptr == getSdrObjectFromSdrObjList()
160 ? getSdrPageFromSdrObjList()->getSdrModelFromSdrPage()
161 : getSdrObjectFromSdrObjList()->getSdrModelFromSdrObject());
163 for (size_t no(0); no < nCount; ++no)
165 SdrObject* pSO(rSrcList.GetObj(no));
166 SdrObject* pDO(pSO->CloneSdrObject(rTargetSdrModel));
168 if(nullptr != pDO)
170 NbcInsertObject(pDO, SAL_MAX_SIZE);
172 else
174 nCloneErrCnt++;
178 // and now for the Connectors
179 // The new objects would be shown in the rSrcList
180 // and then the object connections are made.
181 // Similar implementation are setup as the following:
182 // void SdrObjList::CopyObjects(const SdrObjList& rSrcList)
183 // SdrModel* SdrExchangeView::CreateMarkedObjModel() const
184 // BOOL SdrExchangeView::Paste(const SdrModel& rMod,...)
185 // void SdrEditView::CopyMarked()
186 if (nCloneErrCnt==0) {
187 for (size_t no=0; no<nCount; ++no) {
188 const SdrObject* pSrcOb=rSrcList.GetObj(no);
189 const SdrEdgeObj* pSrcEdge=dynamic_cast<const SdrEdgeObj*>( pSrcOb );
190 if (pSrcEdge!=nullptr) {
191 SdrObject* pSrcNode1=pSrcEdge->GetConnectedNode(true);
192 SdrObject* pSrcNode2=pSrcEdge->GetConnectedNode(false);
193 if (pSrcNode1!=nullptr && pSrcNode1->getParentSdrObjListFromSdrObject()!=pSrcEdge->getParentSdrObjListFromSdrObject()) pSrcNode1=nullptr; // can't do this
194 if (pSrcNode2!=nullptr && pSrcNode2->getParentSdrObjListFromSdrObject()!=pSrcEdge->getParentSdrObjListFromSdrObject()) pSrcNode2=nullptr; // across all lists (yet)
195 if (pSrcNode1!=nullptr || pSrcNode2!=nullptr) {
196 SdrObject* pEdgeObjTmp=GetObj(no);
197 SdrEdgeObj* pDstEdge=dynamic_cast<SdrEdgeObj*>( pEdgeObjTmp );
198 if (pDstEdge!=nullptr) {
199 if (pSrcNode1!=nullptr) {
200 sal_uInt32 nDstNode1=pSrcNode1->GetOrdNum();
201 SdrObject* pDstNode1=GetObj(nDstNode1);
202 if (pDstNode1!=nullptr) { // else we get an error!
203 pDstEdge->ConnectToNode(true,pDstNode1);
204 } else {
205 OSL_FAIL("SdrObjList::operator=(): pDstNode1==NULL!");
208 if (pSrcNode2!=nullptr) {
209 sal_uInt32 nDstNode2=pSrcNode2->GetOrdNum();
210 SdrObject* pDstNode2=GetObj(nDstNode2);
211 if (pDstNode2!=nullptr) { // else the node was probably not selected
212 pDstEdge->ConnectToNode(false,pDstNode2);
213 } else {
214 OSL_FAIL("SdrObjList::operator=(): pDstNode2==NULL!");
217 } else {
218 OSL_FAIL("SdrObjList::operator=(): pDstEdge==NULL!");
223 } else {
224 #ifdef DBG_UTIL
225 OStringBuffer aStr("SdrObjList::operator=(): Error when cloning ");
227 if(nCloneErrCnt == 1)
229 aStr.append("a drawing object.");
231 else
233 aStr.append(static_cast<sal_Int32>(nCloneErrCnt));
234 aStr.append(" drawing objects.");
237 aStr.append(" Not copying connectors.");
239 OSL_FAIL(aStr.getStr());
240 #endif
244 void SdrObjList::RecalcObjOrdNums()
246 const size_t nCount = GetObjCount();
247 for (size_t no=0; no<nCount; ++no) {
248 SdrObject* pObj=GetObj(no);
249 pObj->SetOrdNum(no);
251 mbObjOrdNumsDirty=false;
254 void SdrObjList::RecalcRects()
256 maSdrObjListOutRect=tools::Rectangle();
257 maSdrObjListSnapRect=maSdrObjListOutRect;
258 const size_t nCount = GetObjCount();
259 for (size_t i=0; i<nCount; ++i) {
260 SdrObject* pObj=GetObj(i);
261 if (i==0) {
262 maSdrObjListOutRect=pObj->GetCurrentBoundRect();
263 maSdrObjListSnapRect=pObj->GetSnapRect();
264 } else {
265 maSdrObjListOutRect.Union(pObj->GetCurrentBoundRect());
266 maSdrObjListSnapRect.Union(pObj->GetSnapRect());
271 void SdrObjList::SetSdrObjListRectsDirty()
273 mbRectsDirty=true;
274 SdrObject* pParentSdrObject(getSdrObjectFromSdrObjList());
276 if(nullptr != pParentSdrObject)
278 pParentSdrObject->SetRectsDirty();
282 void SdrObjList::impChildInserted(SdrObject const & rChild)
284 sdr::contact::ViewContact* pParent = rChild.GetViewContact().GetParentContact();
286 if(pParent)
288 pParent->ActionChildInserted(rChild.GetViewContact());
292 void SdrObjList::NbcInsertObject(SdrObject* pObj, size_t nPos)
294 DBG_ASSERT(pObj!=nullptr,"SdrObjList::NbcInsertObject(NULL)");
295 if (pObj==nullptr)
296 return;
298 DBG_ASSERT(!pObj->IsInserted(),"The object already has the status Inserted.");
299 const size_t nCount = GetObjCount();
300 if (nPos>nCount) nPos=nCount;
301 InsertObjectIntoContainer(*pObj,nPos);
303 if (nPos<nCount) mbObjOrdNumsDirty=true;
304 pObj->SetOrdNum(nPos);
305 SetParentAtSdrObjectFromSdrObjList(*pObj, this);
307 // Inform the parent about change to allow invalidations at
308 // evtl. existing parent visualisations
309 impChildInserted(*pObj);
311 if (!mbRectsDirty) {
312 mbRectsDirty = true;
314 pObj->InsertedStateChange(); // calls the UserCall (among others)
317 void SdrObjList::InsertObjectThenMakeNameUnique(SdrObject* pObj)
319 std::unordered_set<rtl::OUString> aNameSet;
320 InsertObjectThenMakeNameUnique(pObj, aNameSet);
323 void SdrObjList::InsertObjectThenMakeNameUnique(SdrObject* pObj, std::unordered_set<OUString>& rNameSet, size_t nPos)
325 InsertObject(pObj, nPos);
326 if (pObj->GetName().isEmpty())
327 return;
329 pObj->MakeNameUnique(rNameSet);
330 SdrObjList* pSdrObjList = pObj->GetSubList(); // group
331 if (pSdrObjList)
333 SdrObject* pListObj;
334 SdrObjListIter aIter(pSdrObjList, SdrIterMode::DeepWithGroups);
335 while (aIter.IsMore())
337 pListObj = aIter.Next();
338 pListObj->MakeNameUnique(rNameSet);
343 void SdrObjList::InsertObject(SdrObject* pObj, size_t nPos)
345 DBG_ASSERT(pObj!=nullptr,"SdrObjList::InsertObject(NULL)");
347 if(!pObj)
348 return;
350 // if anchor is used, reset it before grouping
351 if(getSdrObjectFromSdrObjList())
353 const Point& rAnchorPos = pObj->GetAnchorPos();
354 if(rAnchorPos.X() || rAnchorPos.Y())
355 pObj->NbcSetAnchorPos(Point());
358 // do insert to new group
359 NbcInsertObject(pObj, nPos);
361 // In case the object is inserted into a group and doesn't overlap with
362 // the group's other members, it needs an own repaint.
363 SdrObject* pParentSdrObject(getSdrObjectFromSdrObjList());
365 if(pParentSdrObject)
367 // only repaint here
368 pParentSdrObject->ActionChanged();
371 // TODO: We need a different broadcast here!
372 // Repaint from object number ... (heads-up: GroupObj)
373 if(pObj->getSdrPageFromSdrObject())
375 SdrHint aHint(SdrHintKind::ObjectInserted, *pObj);
376 pObj->getSdrModelFromSdrObject().Broadcast(aHint);
379 pObj->getSdrModelFromSdrObject().SetChanged();
382 SdrObject* SdrObjList::NbcRemoveObject(size_t nObjNum)
384 if (nObjNum >= maList.size())
386 OSL_ASSERT(nObjNum<maList.size());
387 return nullptr;
390 const size_t nCount = GetObjCount();
391 SdrObject* pObj=maList[nObjNum];
392 RemoveObjectFromContainer(nObjNum);
394 DBG_ASSERT(pObj!=nullptr,"Could not find object to remove.");
395 if (pObj!=nullptr)
397 // flushViewObjectContacts() clears the VOC's and those invalidate
398 pObj->GetViewContact().flushViewObjectContacts();
400 DBG_ASSERT(pObj->IsInserted(),"The object does not have the status Inserted.");
402 // tdf#121022 Do first remove from SdrObjList - InsertedStateChange
403 // relies now on IsInserted which uses getParentSdrObjListFromSdrObject
404 SetParentAtSdrObjectFromSdrObjList(*pObj, nullptr);
406 // calls UserCall, among other
407 pObj->InsertedStateChange();
409 if (!mbObjOrdNumsDirty)
411 // optimizing for the case that the last object has to be removed
412 if (nObjNum+1!=nCount) {
413 mbObjOrdNumsDirty=true;
416 SetSdrObjListRectsDirty();
418 return pObj;
421 SdrObject* SdrObjList::RemoveObject(size_t nObjNum)
423 if (nObjNum >= maList.size())
425 OSL_ASSERT(nObjNum<maList.size());
426 return nullptr;
429 const size_t nCount = GetObjCount();
430 SdrObject* pObj=maList[nObjNum];
431 RemoveObjectFromContainer(nObjNum);
433 DBG_ASSERT(pObj!=nullptr,"Object to remove not found.");
434 if(pObj)
436 // flushViewObjectContacts() clears the VOC's and those invalidate
437 pObj->GetViewContact().flushViewObjectContacts();
438 DBG_ASSERT(pObj->IsInserted(),"The object does not have the status Inserted.");
440 // TODO: We need a different broadcast here.
441 if (pObj->getSdrPageFromSdrObject()!=nullptr)
443 SdrHint aHint(SdrHintKind::ObjectRemoved, *pObj);
444 pObj->getSdrModelFromSdrObject().Broadcast(aHint);
447 pObj->getSdrModelFromSdrObject().SetChanged();
449 // tdf#121022 Do first remove from SdrObjList - InsertedStateChange
450 // relies now on IsInserted which uses getParentSdrObjListFromSdrObject
451 SetParentAtSdrObjectFromSdrObjList(*pObj, nullptr);
453 // calls, among other things, the UserCall
454 pObj->InsertedStateChange();
456 if (!mbObjOrdNumsDirty)
458 // optimization for the case that the last object is removed
459 if (nObjNum+1!=nCount) {
460 mbObjOrdNumsDirty=true;
464 SetSdrObjListRectsDirty();
465 SdrObject* pParentSdrObject(getSdrObjectFromSdrObjList());
467 if(pParentSdrObject && !GetObjCount())
469 // empty group created; it needs to be repainted since it's
470 // visualization changes
471 pParentSdrObject->ActionChanged();
474 return pObj;
477 SdrObject* SdrObjList::ReplaceObject(SdrObject* pNewObj, size_t nObjNum)
479 if (nObjNum >= maList.size())
481 OSL_ASSERT(nObjNum<maList.size());
482 return nullptr;
484 if (pNewObj == nullptr)
486 OSL_ASSERT(pNewObj!=nullptr);
487 return nullptr;
490 SdrObject* pObj=maList[nObjNum];
491 DBG_ASSERT(pObj!=nullptr,"SdrObjList::ReplaceObject: Could not find object to remove.");
492 if (pObj!=nullptr) {
493 DBG_ASSERT(pObj->IsInserted(),"SdrObjList::ReplaceObject: the object does not have status Inserted.");
495 // TODO: We need a different broadcast here.
496 if (pObj->getSdrPageFromSdrObject()!=nullptr)
498 SdrHint aHint(SdrHintKind::ObjectRemoved, *pObj);
499 pObj->getSdrModelFromSdrObject().Broadcast(aHint);
502 // Change parent and replace in SdrObjList
503 SetParentAtSdrObjectFromSdrObjList(*pObj, nullptr);
504 ReplaceObjectInContainer(*pNewObj,nObjNum);
506 // tdf#121022 InsertedStateChange uses the parent
507 // to detect if pObj is inserted or not, so have to call
508 // it *after* changing these settings, else an obviously wrong
509 // 'SdrUserCallType::Inserted' would be sent
510 pObj->InsertedStateChange();
512 // flushViewObjectContacts() clears the VOC's and those
513 // trigger the evtl. needed invalidate(s)
514 pObj->GetViewContact().flushViewObjectContacts();
516 // Setup data at new SdrObject - it already *is* inserted to
517 // the SdrObjList due to 'ReplaceObjectInContainer' above
518 pNewObj->SetOrdNum(nObjNum);
519 SetParentAtSdrObjectFromSdrObjList(*pNewObj, this);
521 // Inform the parent about change to allow invalidations at
522 // evtl. existing parent visualisations, but also react on
523 // newly inserted SdrObjects (as e.g. GraphCtrlUserCall does)
524 impChildInserted(*pNewObj);
526 pNewObj->InsertedStateChange();
528 // TODO: We need a different broadcast here.
529 if (pNewObj->getSdrPageFromSdrObject()!=nullptr) {
530 SdrHint aHint(SdrHintKind::ObjectInserted, *pNewObj);
531 pNewObj->getSdrModelFromSdrObject().Broadcast(aHint);
534 pNewObj->getSdrModelFromSdrObject().SetChanged();
536 SetSdrObjListRectsDirty();
538 return pObj;
541 SdrObject* SdrObjList::SetObjectOrdNum(size_t nOldObjNum, size_t nNewObjNum)
543 if (nOldObjNum >= maList.size() || nNewObjNum >= maList.size())
545 OSL_ASSERT(nOldObjNum<maList.size());
546 OSL_ASSERT(nNewObjNum<maList.size());
547 return nullptr;
550 SdrObject* pObj=maList[nOldObjNum];
551 if (nOldObjNum==nNewObjNum) return pObj;
552 DBG_ASSERT(pObj!=nullptr,"SdrObjList::SetObjectOrdNum: Object not found.");
553 if (pObj!=nullptr) {
554 DBG_ASSERT(pObj->IsInserted(),"SdrObjList::SetObjectOrdNum: the object does not have status Inserted.");
555 RemoveObjectFromContainer(nOldObjNum);
556 InsertObjectIntoContainer(*pObj,nNewObjNum);
558 // No need to delete visualisation data since same object
559 // gets inserted again. Also a single ActionChanged is enough
560 pObj->ActionChanged();
562 pObj->SetOrdNum(nNewObjNum);
563 mbObjOrdNumsDirty=true;
565 // TODO: We need a different broadcast here.
566 if (pObj->getSdrPageFromSdrObject()!=nullptr)
567 pObj->getSdrModelFromSdrObject().Broadcast(SdrHint(SdrHintKind::ObjectChange, *pObj));
568 pObj->getSdrModelFromSdrObject().SetChanged();
570 return pObj;
573 void SdrObjList::sort( std::vector<sal_Int32>& sortOrder)
575 // no negative indexes and indexes larger than maList size are allowed
576 auto it = std::find_if( sortOrder.begin(), sortOrder.end(), [this](const sal_Int32& rIt)
577 { return ( rIt < 0 || o3tl::make_unsigned(rIt) >= maList.size() ); } );
578 if ( it != sortOrder.end())
579 throw css::lang::IllegalArgumentException("negative index of shape", nullptr, 1);
581 // no duplicates
582 std::vector<bool> aNoDuplicates(sortOrder.size(), false);
583 for (size_t i = 0; i < sortOrder.size(); ++i )
585 size_t idx = static_cast<size_t>( sortOrder[i] );
587 if ( aNoDuplicates[idx] )
588 throw css::lang::IllegalArgumentException("duplicate index of shape", nullptr, 2);
590 aNoDuplicates[idx] = true;
593 // example sortOrder [2 0 1]
594 // example maList [T T S T T] ( T T = shape with textbox, S = just a shape )
595 // (shapes at positions 0 and 2 have a textbox)
597 std::vector<SdrObject*> aNewList(maList.size());
598 std::set<sal_Int32> aShapesWithTextbox;
599 std::vector<sal_Int32> aIncrements;
600 std::vector<sal_Int32> aDuplicates;
602 if ( maList.size() > 1)
604 for (size_t i = 1; i< maList.size(); ++i)
606 // if this shape is a textbox, then look at its left neighbour
607 // (shape this textbox is in)
608 // and insert the number of textboxes to the left of it
609 if (maList[i]->IsTextBox())
610 aShapesWithTextbox.insert( i - 1 - aShapesWithTextbox.size() );
612 // example aShapesWithTextbox [0 2]
615 if (aShapesWithTextbox.size() != maList.size() - sortOrder.size())
617 throw lang::IllegalArgumentException("mismatch of no. of shapes", nullptr, 0);
620 for (size_t i = 0; i< sortOrder.size(); ++i)
623 if (aShapesWithTextbox.count(sortOrder[i]) > 0)
624 aDuplicates.push_back(sortOrder[i]);
626 aDuplicates.push_back(sortOrder[i]);
628 // example aDuplicates [2 2 0 0 1]
630 assert(aDuplicates.size() == maList.size());
632 aIncrements.push_back(0);
633 for (size_t i = 1; i< sortOrder.size(); ++i)
635 if (aShapesWithTextbox.count(i - 1))
636 aIncrements.push_back(aIncrements[i-1] + 1 );
637 else
638 aIncrements.push_back(aIncrements[i-1]);
640 // example aIncrements [0 1 1]
642 assert(aIncrements.size() == sortOrder.size());
644 std::vector<sal_Int32> aNewSortOrder(maList.size());
645 sal_Int32 nPrev = -1;
646 for (size_t i = 0; i< aDuplicates.size(); ++i)
648 if (nPrev != aDuplicates[i])
649 aNewSortOrder[i] = aDuplicates[i] + aIncrements[aDuplicates[i]];
650 else
651 aNewSortOrder[i] = aNewSortOrder[i-1] + 1;
653 nPrev = aDuplicates[i];
655 // example aNewSortOrder [3 4 0 1 2]
657 assert(aNewSortOrder.size() == maList.size());
659 #ifndef NDEBUG
661 std::vector<sal_Int32> tmp(aNewSortOrder);
662 std::sort(tmp.begin(), tmp.end());
663 for (size_t i = 0; i < tmp.size(); ++i)
665 assert(size_t(tmp[i]) == i);
668 #endif
670 for (size_t i = 0; i < aNewSortOrder.size(); ++i)
672 aNewList[i] = maList[ aNewSortOrder[i] ];
673 aNewList[i]->SetOrdNum(i);
676 std::swap(aNewList, maList);
679 const tools::Rectangle& SdrObjList::GetAllObjSnapRect() const
681 if (mbRectsDirty) {
682 const_cast<SdrObjList*>(this)->RecalcRects();
683 const_cast<SdrObjList*>(this)->mbRectsDirty=false;
685 return maSdrObjListSnapRect;
688 const tools::Rectangle& SdrObjList::GetAllObjBoundRect() const
690 // #i106183# for deep group hierarchies like in chart2, the invalidates
691 // through the hierarchy are not correct; use a 2nd hint for the needed
692 // recalculation. Future versions will have no bool flag at all, but
693 // just maSdrObjListOutRect in empty state to represent an invalid state, thus
694 // it's a step in the right direction.
695 if (mbRectsDirty || maSdrObjListOutRect.IsEmpty())
697 const_cast<SdrObjList*>(this)->RecalcRects();
698 const_cast<SdrObjList*>(this)->mbRectsDirty=false;
700 return maSdrObjListOutRect;
703 void SdrObjList::NbcReformatAllTextObjects()
705 size_t nCount=GetObjCount();
706 size_t nNum=0;
708 while (nNum<nCount)
710 SdrObject* pObj = GetObj(nNum);
712 pObj->NbcReformatText();
713 nCount=GetObjCount(); // ReformatText may delete an object
714 nNum++;
719 void SdrObjList::ReformatAllTextObjects()
721 NbcReformatAllTextObjects();
724 /** steps over all available objects and reformats all
725 edge objects that are connected to other objects so that
726 they may reposition themselves.
728 void SdrObjList::ReformatAllEdgeObjects()
730 // #i120437# go over whole hierarchy, not only over object level null (seen from grouping)
731 SdrObjListIter aIter(this, SdrIterMode::DeepNoGroups);
733 while(aIter.IsMore())
735 SdrObject* pObj = aIter.Next();
736 if (pObj->GetObjIdentifier() != OBJ_EDGE)
737 continue;
739 SdrEdgeObj* pSdrEdgeObj = static_cast< SdrEdgeObj* >(pObj);
740 pSdrEdgeObj->Reformat();
744 void SdrObjList::BurnInStyleSheetAttributes()
746 for(size_t a = 0; a < GetObjCount(); ++a)
748 GetObj(a)->BurnInStyleSheetAttributes();
752 size_t SdrObjList::GetObjCount() const
754 return maList.size();
758 SdrObject* SdrObjList::GetObj(size_t nNum) const
760 return maList[nNum];
764 bool SdrObjList::IsReadOnly() const
766 bool bRet(false);
767 SdrObject* pParentSdrObject(getSdrObjectFromSdrObjList());
769 if(nullptr != pParentSdrObject)
771 SdrPage* pSdrPage(pParentSdrObject->getSdrPageFromSdrObject());
773 if(nullptr != pSdrPage)
775 bRet = pSdrPage->IsReadOnly();
779 return bRet;
782 void SdrObjList::FlattenGroups()
784 const size_t nObj = GetObjCount();
785 for( size_t i = nObj; i>0; )
786 UnGroupObj(--i);
789 void SdrObjList::UnGroupObj( size_t nObjNum )
791 // if the given object is no group, this method is a noop
792 SdrObject* pUngroupObj = GetObj( nObjNum );
793 if( pUngroupObj )
795 SdrObjList* pSrcLst = pUngroupObj->GetSubList();
796 if( dynamic_cast<const SdrObjGroup*>( pUngroupObj) != nullptr && pSrcLst )
798 SdrObjGroup* pUngroupGroup = static_cast< SdrObjGroup* > (pUngroupObj);
800 // ungroup recursively (has to be head recursion,
801 // otherwise our indices will get trashed when doing it in
802 // the loop)
803 pSrcLst->FlattenGroups();
805 // the position at which we insert the members of rUngroupGroup
806 size_t nInsertPos( pUngroupGroup->GetOrdNum() );
808 const size_t nCount = pSrcLst->GetObjCount();
809 for( size_t i=0; i<nCount; ++i )
811 SdrObject* pObj = pSrcLst->RemoveObject(0);
812 InsertObject(pObj, nInsertPos);
813 ++nInsertPos;
816 RemoveObject(nInsertPos);
819 #ifdef DBG_UTIL
820 else
821 OSL_FAIL("SdrObjList::UnGroupObj: object index invalid");
822 #endif
825 bool SdrObjList::HasObjectNavigationOrder() const { return mxNavigationOrder != nullptr; }
827 void SdrObjList::SetObjectNavigationPosition (
828 SdrObject& rObject,
829 const sal_uInt32 nNewPosition)
831 // When the navigation order container has not yet been created then
832 // create one now. It is initialized with the z-order taken from
833 // maList.
834 if (mxNavigationOrder == nullptr)
836 mxNavigationOrder.reset(new std::vector<tools::WeakReference<SdrObject>>(maList.begin(),
837 maList.end()));
839 OSL_ASSERT(mxNavigationOrder != nullptr);
840 OSL_ASSERT( mxNavigationOrder->size() == maList.size());
842 tools::WeakReference<SdrObject> aReference (&rObject);
844 // Look up the object whose navigation position is to be changed.
845 auto iObject = ::std::find(
846 mxNavigationOrder->begin(),
847 mxNavigationOrder->end(),
848 aReference);
849 if (iObject == mxNavigationOrder->end())
851 // The given object is not a member of the navigation order.
852 return;
855 // Move the object to its new position.
856 const sal_uInt32 nOldPosition = ::std::distance(mxNavigationOrder->begin(), iObject);
857 if (nOldPosition == nNewPosition)
858 return;
860 mxNavigationOrder->erase(iObject);
861 sal_uInt32 nInsertPosition (nNewPosition);
862 // Adapt insertion position for the just erased object.
863 if (nNewPosition >= nOldPosition)
864 nInsertPosition -= 1;
865 if (nInsertPosition >= mxNavigationOrder->size())
866 mxNavigationOrder->push_back(aReference);
867 else
868 mxNavigationOrder->insert(mxNavigationOrder->begin()+nInsertPosition, aReference);
870 mbIsNavigationOrderDirty = true;
872 // The navigation order is written out to file so mark the model as modified.
873 rObject.getSdrModelFromSdrObject().SetChanged();
877 SdrObject* SdrObjList::GetObjectForNavigationPosition (const sal_uInt32 nNavigationPosition) const
879 if (HasObjectNavigationOrder())
881 // There is a user defined navigation order. Make sure the object
882 // index is correct and look up the object in mxNavigationOrder.
883 if (nNavigationPosition >= mxNavigationOrder->size())
885 OSL_ASSERT(nNavigationPosition < mxNavigationOrder->size());
887 else
888 return (*mxNavigationOrder)[nNavigationPosition].get();
890 else
892 // There is no user defined navigation order. Use the z-order
893 // instead.
894 if (nNavigationPosition >= maList.size())
896 OSL_ASSERT(nNavigationPosition < maList.size());
898 else
899 return maList[nNavigationPosition];
901 return nullptr;
905 void SdrObjList::ClearObjectNavigationOrder()
907 mxNavigationOrder.reset();
908 mbIsNavigationOrderDirty = true;
912 bool SdrObjList::RecalcNavigationPositions()
914 if (mbIsNavigationOrderDirty)
916 if (mxNavigationOrder != nullptr)
918 mbIsNavigationOrderDirty = false;
920 sal_uInt32 nIndex (0);
921 for (auto& rpObject : *mxNavigationOrder)
923 rpObject->SetNavigationPosition(nIndex);
924 ++nIndex;
929 return mxNavigationOrder != nullptr;
933 void SdrObjList::SetNavigationOrder (const uno::Reference<container::XIndexAccess>& rxOrder)
935 if (rxOrder.is())
937 const sal_Int32 nCount = rxOrder->getCount();
938 if (static_cast<sal_uInt32>(nCount) != maList.size())
939 return;
941 if (mxNavigationOrder == nullptr)
942 mxNavigationOrder.reset(new std::vector<tools::WeakReference<SdrObject>>(nCount));
944 for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex)
946 uno::Reference<uno::XInterface> xShape (rxOrder->getByIndex(nIndex), uno::UNO_QUERY);
947 SdrObject* pObject = SdrObject::getSdrObjectFromXShape(xShape);
948 if (pObject == nullptr)
949 break;
950 (*mxNavigationOrder)[nIndex] = pObject;
953 mbIsNavigationOrderDirty = true;
955 else
957 ClearObjectNavigationOrder();
962 void SdrObjList::InsertObjectIntoContainer (
963 SdrObject& rObject,
964 const sal_uInt32 nInsertPosition)
966 OSL_ASSERT(nInsertPosition<=maList.size());
968 // Update the navigation positions.
969 if (HasObjectNavigationOrder())
971 // The new object does not have a user defined position so append it
972 // to the list.
973 rObject.SetNavigationPosition(mxNavigationOrder->size());
974 mxNavigationOrder->push_back(&rObject);
977 // Insert object into object list. Because the insert() method requires
978 // a valid iterator as insertion position, we have to use push_back() to
979 // insert at the end of the list.
980 if (nInsertPosition >= maList.size())
981 maList.push_back(&rObject);
982 else
983 maList.insert(maList.begin()+nInsertPosition, &rObject);
984 mbObjOrdNumsDirty=true;
988 void SdrObjList::ReplaceObjectInContainer (
989 SdrObject& rNewObject,
990 const sal_uInt32 nObjectPosition)
992 if (nObjectPosition >= maList.size())
994 OSL_ASSERT(nObjectPosition<maList.size());
995 return;
998 // Update the navigation positions.
999 if (HasObjectNavigationOrder())
1001 // A user defined position of the object that is to be replaced is
1002 // not transferred to the new object so erase the former and append
1003 // the later object from/to the navigation order.
1004 OSL_ASSERT(nObjectPosition < maList.size());
1005 tools::WeakReference<SdrObject> aReference (maList[nObjectPosition]);
1006 auto iObject = ::std::find(
1007 mxNavigationOrder->begin(),
1008 mxNavigationOrder->end(),
1009 aReference);
1010 if (iObject != mxNavigationOrder->end())
1011 mxNavigationOrder->erase(iObject);
1013 mxNavigationOrder->push_back(&rNewObject);
1015 mbIsNavigationOrderDirty = true;
1018 maList[nObjectPosition] = &rNewObject;
1019 mbObjOrdNumsDirty=true;
1023 void SdrObjList::RemoveObjectFromContainer (
1024 const sal_uInt32 nObjectPosition)
1026 if (nObjectPosition >= maList.size())
1028 OSL_ASSERT(nObjectPosition<maList.size());
1029 return;
1032 // Update the navigation positions.
1033 if (HasObjectNavigationOrder())
1035 tools::WeakReference<SdrObject> aReference (maList[nObjectPosition]);
1036 auto iObject = ::std::find(
1037 mxNavigationOrder->begin(),
1038 mxNavigationOrder->end(),
1039 aReference);
1040 if (iObject != mxNavigationOrder->end())
1041 mxNavigationOrder->erase(iObject);
1042 mbIsNavigationOrderDirty = true;
1045 maList.erase(maList.begin()+nObjectPosition);
1046 mbObjOrdNumsDirty=true;
1049 void SdrObjList::dumpAsXml(xmlTextWriterPtr pWriter) const
1051 xmlTextWriterStartElement(pWriter, BAD_CAST("SdrObjList"));
1052 xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
1053 xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
1055 size_t nObjCount = GetObjCount();
1056 for (size_t i = 0; i < nObjCount; ++i)
1058 if (const SdrObject* pObject = GetObj(i))
1059 pObject->dumpAsXml(pWriter);
1062 xmlTextWriterEndElement(pWriter);
1066 void SdrPageGridFrameList::Clear()
1068 sal_uInt16 nCount=GetCount();
1069 for (sal_uInt16 i=0; i<nCount; i++) {
1070 delete GetObject(i);
1072 aList.clear();
1076 // PageUser section
1078 void SdrPage::AddPageUser(sdr::PageUser& rNewUser)
1080 maPageUsers.push_back(&rNewUser);
1083 void SdrPage::RemovePageUser(sdr::PageUser& rOldUser)
1085 const sdr::PageUserVector::iterator aFindResult = ::std::find(maPageUsers.begin(), maPageUsers.end(), &rOldUser);
1086 if(aFindResult != maPageUsers.end())
1088 maPageUsers.erase(aFindResult);
1093 // DrawContact section
1095 std::unique_ptr<sdr::contact::ViewContact> SdrPage::CreateObjectSpecificViewContact()
1097 return std::make_unique<sdr::contact::ViewContactOfSdrPage>(*this);
1100 const sdr::contact::ViewContact& SdrPage::GetViewContact() const
1102 if (!mpViewContact)
1103 const_cast<SdrPage*>(this)->mpViewContact =
1104 const_cast<SdrPage*>(this)->CreateObjectSpecificViewContact();
1106 return *mpViewContact;
1109 sdr::contact::ViewContact& SdrPage::GetViewContact()
1111 if (!mpViewContact)
1112 mpViewContact = CreateObjectSpecificViewContact();
1114 return *mpViewContact;
1117 void SdrPageProperties::ImpRemoveStyleSheet()
1119 if(mpStyleSheet)
1121 EndListening(*mpStyleSheet);
1122 maProperties.SetParent(nullptr);
1123 mpStyleSheet = nullptr;
1127 void SdrPageProperties::ImpAddStyleSheet(SfxStyleSheet& rNewStyleSheet)
1129 if(mpStyleSheet != &rNewStyleSheet)
1131 ImpRemoveStyleSheet();
1132 mpStyleSheet = &rNewStyleSheet;
1133 StartListening(rNewStyleSheet);
1134 maProperties.SetParent(&rNewStyleSheet.GetItemSet());
1138 static void ImpPageChange(SdrPage& rSdrPage)
1140 rSdrPage.ActionChanged();
1141 rSdrPage.getSdrModelFromSdrPage().SetChanged();
1142 SdrHint aHint(SdrHintKind::PageOrderChange, &rSdrPage);
1143 rSdrPage.getSdrModelFromSdrPage().Broadcast(aHint);
1146 SdrPageProperties::SdrPageProperties(SdrPage& rSdrPage)
1147 : SfxListener(),
1148 mpSdrPage(&rSdrPage),
1149 mpStyleSheet(nullptr),
1150 maProperties(
1151 mpSdrPage->getSdrModelFromSdrPage().GetItemPool(),
1152 svl::Items<XATTR_FILL_FIRST, XATTR_FILL_LAST>{})
1154 if(!rSdrPage.IsMasterPage())
1156 maProperties.Put(XFillStyleItem(drawing::FillStyle_NONE));
1160 SdrPageProperties::~SdrPageProperties()
1162 ImpRemoveStyleSheet();
1165 void SdrPageProperties::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
1167 switch(rHint.GetId())
1169 case SfxHintId::DataChanged :
1171 // notify change, broadcast
1172 ImpPageChange(*mpSdrPage);
1173 break;
1175 case SfxHintId::Dying :
1177 // Style needs to be forgotten
1178 ImpRemoveStyleSheet();
1179 break;
1181 default: break;
1185 bool SdrPageProperties::isUsedByModel() const
1187 assert(mpSdrPage);
1188 return mpSdrPage->IsInserted();
1192 void SdrPageProperties::PutItemSet(const SfxItemSet& rSet)
1194 OSL_ENSURE(!mpSdrPage->IsMasterPage(), "Item set at MasterPage Attributes (!)");
1195 maProperties.Put(rSet);
1196 ImpPageChange(*mpSdrPage);
1199 void SdrPageProperties::PutItem(const SfxPoolItem& rItem)
1201 OSL_ENSURE(!mpSdrPage->IsMasterPage(), "Item set at MasterPage Attributes (!)");
1202 maProperties.Put(rItem);
1203 ImpPageChange(*mpSdrPage);
1206 void SdrPageProperties::ClearItem(const sal_uInt16 nWhich)
1208 maProperties.ClearItem(nWhich);
1209 ImpPageChange(*mpSdrPage);
1212 void SdrPageProperties::SetStyleSheet(SfxStyleSheet* pStyleSheet)
1214 if(pStyleSheet)
1216 ImpAddStyleSheet(*pStyleSheet);
1218 else
1220 ImpRemoveStyleSheet();
1223 ImpPageChange(*mpSdrPage);
1227 SdrPage::SdrPage(SdrModel& rModel, bool bMasterPage)
1228 : SdrObjList(),
1229 tools::WeakBase(),
1230 maPageUsers(),
1231 mrSdrModelFromSdrPage(rModel),
1232 mnWidth(10),
1233 mnHeight(10),
1234 mnBorderLeft(0),
1235 mnBorderUpper(0),
1236 mnBorderRight(0),
1237 mnBorderLower(0),
1238 mpLayerAdmin(new SdrLayerAdmin(&rModel.GetLayerAdmin())),
1239 mxUnoPage(),
1240 nPageNum(0),
1241 mbMaster(bMasterPage),
1242 mbInserted(false),
1243 mbObjectsNotPersistent(false),
1244 mbPageBorderOnlyLeftRight(false)
1246 mpSdrPageProperties.reset(new SdrPageProperties(*this));
1249 SdrPage::~SdrPage()
1251 if( mxUnoPage.is() ) try
1253 uno::Reference< lang::XComponent > xPageComponent( mxUnoPage, uno::UNO_QUERY_THROW );
1254 mxUnoPage.clear();
1255 xPageComponent->dispose();
1257 catch( const uno::Exception& )
1259 DBG_UNHANDLED_EXCEPTION("svx");
1262 // tell all the registered PageUsers that the page is in destruction
1263 // This causes some (all?) PageUsers to remove themselves from the list
1264 // of page users. Therefore we have to use a copy of the list for the
1265 // iteration.
1266 sdr::PageUserVector aListCopy (maPageUsers.begin(), maPageUsers.end());
1267 for(sdr::PageUser* pPageUser : aListCopy)
1269 DBG_ASSERT(pPageUser, "SdrPage::~SdrPage: corrupt PageUser list (!)");
1270 pPageUser->PageInDestruction(*this);
1273 // Clear the vector. This means that user do not need to call RemovePageUser()
1274 // when they get called from PageInDestruction().
1275 maPageUsers.clear();
1277 mpLayerAdmin.reset();
1279 TRG_ClearMasterPage();
1281 mpViewContact.reset();
1282 mpSdrPageProperties.reset();
1285 void SdrPage::lateInit(const SdrPage& rSrcPage)
1287 assert(!mpViewContact);
1288 assert(!mxUnoPage.is());
1290 // copy all the local parameters to make this instance
1291 // a valid copy of source page before copying and inserting
1292 // the contained objects
1293 mbMaster = rSrcPage.mbMaster;
1294 mbPageBorderOnlyLeftRight = rSrcPage.mbPageBorderOnlyLeftRight;
1295 mnWidth = rSrcPage.mnWidth;
1296 mnHeight = rSrcPage.mnHeight;
1297 mnBorderLeft = rSrcPage.mnBorderLeft;
1298 mnBorderUpper = rSrcPage.mnBorderUpper;
1299 mnBorderRight = rSrcPage.mnBorderRight;
1300 mnBorderLower = rSrcPage.mnBorderLower;
1301 nPageNum = rSrcPage.nPageNum;
1303 if(rSrcPage.TRG_HasMasterPage())
1305 TRG_SetMasterPage(rSrcPage.TRG_GetMasterPage());
1306 TRG_SetMasterPageVisibleLayers(rSrcPage.TRG_GetMasterPageVisibleLayers());
1308 else
1310 TRG_ClearMasterPage();
1313 mbObjectsNotPersistent = rSrcPage.mbObjectsNotPersistent;
1316 mpSdrPageProperties.reset(new SdrPageProperties(*this));
1318 if(!IsMasterPage())
1320 mpSdrPageProperties->PutItemSet(rSrcPage.getSdrPageProperties().GetItemSet());
1323 mpSdrPageProperties->SetStyleSheet(rSrcPage.getSdrPageProperties().GetStyleSheet());
1326 // Now copy the contained objects
1327 if(0 != rSrcPage.GetObjCount())
1329 CopyObjects(rSrcPage);
1333 SdrPage* SdrPage::CloneSdrPage(SdrModel& rTargetModel) const
1335 SdrPage* pClonedPage(new SdrPage(rTargetModel));
1336 pClonedPage->lateInit(*this);
1337 return pClonedPage;
1340 void SdrPage::SetSize(const Size& aSiz)
1342 bool bChanged(false);
1344 if(aSiz.Width() != mnWidth)
1346 mnWidth = aSiz.Width();
1347 bChanged = true;
1350 if(aSiz.Height() != mnHeight)
1352 mnHeight = aSiz.Height();
1353 bChanged = true;
1356 if(bChanged)
1358 SetChanged();
1362 Size SdrPage::GetSize() const
1364 return Size(mnWidth,mnHeight);
1367 sal_Int32 SdrPage::GetWidth() const
1369 return mnWidth;
1372 void SdrPage::SetOrientation(Orientation eOri)
1374 // square: handle like portrait format
1375 Size aSiz(GetSize());
1376 if (aSiz.Width()!=aSiz.Height()) {
1377 if ((eOri==Orientation::Portrait) == (aSiz.Width()>aSiz.Height())) {
1378 // coverity[swapped_arguments : FALSE] - this is in the correct order
1379 SetSize(Size(aSiz.Height(),aSiz.Width()));
1384 Orientation SdrPage::GetOrientation() const
1386 // square: handle like portrait format
1387 Orientation eRet=Orientation::Portrait;
1388 Size aSiz(GetSize());
1389 if (aSiz.Width()>aSiz.Height()) eRet=Orientation::Landscape;
1390 return eRet;
1393 sal_Int32 SdrPage::GetHeight() const
1395 return mnHeight;
1398 void SdrPage::SetBorder(sal_Int32 nLft, sal_Int32 nUpp, sal_Int32 nRgt, sal_Int32 nLwr)
1400 bool bChanged(false);
1402 if(mnBorderLeft != nLft)
1404 mnBorderLeft = nLft;
1405 bChanged = true;
1408 if(mnBorderUpper != nUpp)
1410 mnBorderUpper = nUpp;
1411 bChanged = true;
1414 if(mnBorderRight != nRgt)
1416 mnBorderRight = nRgt;
1417 bChanged = true;
1420 if(mnBorderLower != nLwr)
1422 mnBorderLower = nLwr;
1423 bChanged = true;
1426 if(bChanged)
1428 SetChanged();
1432 void SdrPage::SetLeftBorder(sal_Int32 nBorder)
1434 if(mnBorderLeft != nBorder)
1436 mnBorderLeft = nBorder;
1437 SetChanged();
1441 void SdrPage::SetUpperBorder(sal_Int32 nBorder)
1443 if(mnBorderUpper != nBorder)
1445 mnBorderUpper = nBorder;
1446 SetChanged();
1450 void SdrPage::SetRightBorder(sal_Int32 nBorder)
1452 if(mnBorderRight != nBorder)
1454 mnBorderRight=nBorder;
1455 SetChanged();
1459 void SdrPage::SetLowerBorder(sal_Int32 nBorder)
1461 if(mnBorderLower != nBorder)
1463 mnBorderLower=nBorder;
1464 SetChanged();
1468 sal_Int32 SdrPage::GetLeftBorder() const
1470 return mnBorderLeft;
1473 sal_Int32 SdrPage::GetUpperBorder() const
1475 return mnBorderUpper;
1478 sal_Int32 SdrPage::GetRightBorder() const
1480 return mnBorderRight;
1483 sal_Int32 SdrPage::GetLowerBorder() const
1485 return mnBorderLower;
1488 // #i68775# React on PageNum changes (from Model in most cases)
1489 void SdrPage::SetPageNum(sal_uInt16 nNew)
1491 if(nNew != nPageNum)
1493 // change
1494 nPageNum = nNew;
1496 // notify visualisations, also notifies e.g. buffered MasterPages
1497 ActionChanged();
1501 sal_uInt16 SdrPage::GetPageNum() const
1503 if (!mbInserted)
1504 return 0;
1506 if (mbMaster) {
1507 if (getSdrModelFromSdrPage().IsMPgNumsDirty())
1508 getSdrModelFromSdrPage().RecalcPageNums(true);
1509 } else {
1510 if (getSdrModelFromSdrPage().IsPagNumsDirty())
1511 getSdrModelFromSdrPage().RecalcPageNums(false);
1513 return nPageNum;
1516 void SdrPage::SetChanged()
1518 // For test purposes, use the new ViewContact for change
1519 // notification now.
1520 ActionChanged();
1521 getSdrModelFromSdrPage().SetChanged();
1524 SdrPage* SdrPage::getSdrPageFromSdrObjList() const
1526 return const_cast< SdrPage* >(this);
1529 // MasterPage interface
1531 void SdrPage::TRG_SetMasterPage(SdrPage& rNew)
1533 if(mpMasterPageDescriptor && &(mpMasterPageDescriptor->GetUsedPage()) == &rNew)
1534 return;
1536 if(mpMasterPageDescriptor)
1537 TRG_ClearMasterPage();
1539 mpMasterPageDescriptor.reset(new sdr::MasterPageDescriptor(*this, rNew));
1540 GetViewContact().ActionChanged();
1543 void SdrPage::TRG_ClearMasterPage()
1545 if(mpMasterPageDescriptor)
1547 SetChanged();
1549 // the flushViewObjectContacts() will do needed invalidates by deleting the involved VOCs
1550 mpMasterPageDescriptor->GetUsedPage().GetViewContact().flushViewObjectContacts();
1552 mpMasterPageDescriptor.reset();
1556 SdrPage& SdrPage::TRG_GetMasterPage() const
1558 DBG_ASSERT(mpMasterPageDescriptor != nullptr, "TRG_GetMasterPage(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
1559 return mpMasterPageDescriptor->GetUsedPage();
1562 const SdrLayerIDSet& SdrPage::TRG_GetMasterPageVisibleLayers() const
1564 DBG_ASSERT(mpMasterPageDescriptor != nullptr, "TRG_GetMasterPageVisibleLayers(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
1565 return mpMasterPageDescriptor->GetVisibleLayers();
1568 void SdrPage::TRG_SetMasterPageVisibleLayers(const SdrLayerIDSet& rNew)
1570 DBG_ASSERT(mpMasterPageDescriptor != nullptr, "TRG_SetMasterPageVisibleLayers(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
1571 mpMasterPageDescriptor->SetVisibleLayers(rNew);
1574 sdr::contact::ViewContact& SdrPage::TRG_GetMasterPageDescriptorViewContact() const
1576 DBG_ASSERT(mpMasterPageDescriptor != nullptr, "TRG_GetMasterPageDescriptorViewContact(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
1577 return mpMasterPageDescriptor->GetViewContact();
1580 // used from SdrModel::RemoveMasterPage
1581 void SdrPage::TRG_ImpMasterPageRemoved(const SdrPage& rRemovedPage)
1583 if(TRG_HasMasterPage())
1585 if(&TRG_GetMasterPage() == &rRemovedPage)
1587 TRG_ClearMasterPage();
1592 void SdrPage::MakePageObjectsNamesUnique()
1594 std::unordered_set<OUString> aNameSet;
1595 for (size_t no(0); no < GetObjCount(); ++no)
1597 SdrObject* pObj(GetObj(no));
1598 if(nullptr != pObj)
1600 if (!pObj->GetName().isEmpty())
1602 pObj->MakeNameUnique(aNameSet);
1603 SdrObjList* pSdrObjList = pObj->GetSubList(); // group
1604 if (pSdrObjList)
1606 SdrObject* pListObj;
1607 SdrObjListIter aIter(pSdrObjList, SdrIterMode::DeepWithGroups);
1608 while (aIter.IsMore())
1610 pListObj = aIter.Next();
1611 pListObj->MakeNameUnique(aNameSet);
1619 const SdrPageGridFrameList* SdrPage::GetGridFrameList(const SdrPageView* /*pPV*/, const tools::Rectangle* /*pRect*/) const
1621 return nullptr;
1624 const SdrLayerAdmin& SdrPage::GetLayerAdmin() const
1626 return *mpLayerAdmin;
1629 SdrLayerAdmin& SdrPage::GetLayerAdmin()
1631 return *mpLayerAdmin;
1634 OUString SdrPage::GetLayoutName() const
1636 return OUString();
1639 void SdrPage::SetInserted( bool bIns )
1641 if( mbInserted == bIns )
1642 return;
1644 mbInserted = bIns;
1646 // #i120437# go over whole hierarchy, not only over object level null (seen from grouping)
1647 SdrObjListIter aIter(this, SdrIterMode::DeepNoGroups);
1649 while ( aIter.IsMore() )
1651 SdrObject* pObj = aIter.Next();
1652 if ( auto pOleObj = dynamic_cast<SdrOle2Obj* >(pObj) )
1654 if( mbInserted )
1655 pOleObj->Connect();
1656 else
1657 pOleObj->Disconnect();
1662 void SdrPage::SetUnoPage(uno::Reference<drawing::XDrawPage> const& xNewPage)
1664 mxUnoPage = xNewPage;
1667 uno::Reference< uno::XInterface > const & SdrPage::getUnoPage()
1669 if( !mxUnoPage.is() )
1671 // create one
1672 mxUnoPage = createUnoPage();
1675 return mxUnoPage;
1678 uno::Reference< uno::XInterface > SdrPage::createUnoPage()
1680 css::uno::Reference< css::uno::XInterface > xInt =
1681 static_cast<cppu::OWeakObject*>( new SvxFmDrawPage( this ) );
1682 return xInt;
1685 SfxStyleSheet* SdrPage::GetTextStyleSheetForObject( SdrObject* pObj ) const
1687 return pObj->GetStyleSheet();
1690 /** returns an averaged background color of this page */
1691 // #i75566# GetBackgroundColor -> GetPageBackgroundColor and bScreenDisplay hint value
1692 Color SdrPage::GetPageBackgroundColor( SdrPageView const * pView, bool bScreenDisplay ) const
1694 Color aColor;
1696 if(bScreenDisplay && (!pView || pView->GetApplicationDocumentColor() == COL_AUTO))
1698 svtools::ColorConfig aColorConfig;
1699 aColor = aColorConfig.GetColorValue( svtools::DOCCOLOR ).nColor;
1701 else
1703 aColor = pView->GetApplicationDocumentColor();
1706 const SfxItemSet* pBackgroundFill = &getSdrPageProperties().GetItemSet();
1708 if(!IsMasterPage() && TRG_HasMasterPage())
1710 if(drawing::FillStyle_NONE == pBackgroundFill->Get(XATTR_FILLSTYLE).GetValue())
1712 pBackgroundFill = &TRG_GetMasterPage().getSdrPageProperties().GetItemSet();
1716 GetDraftFillColor(*pBackgroundFill, aColor);
1718 return aColor;
1721 /** *deprecated, use GetBackgroundColor with SdrPageView */
1722 Color SdrPage::GetPageBackgroundColor() const
1723 // #i75566# GetBackgroundColor -> GetPageBackgroundColor
1725 return GetPageBackgroundColor( nullptr );
1728 /** this method returns true if the object from the ViewObjectContact should
1729 be visible on this page while rendering.
1730 bEdit selects if visibility test is for an editing view or a final render,
1731 like printing.
1733 bool SdrPage::checkVisibility(
1734 const sdr::contact::ViewObjectContact& /*rOriginal*/,
1735 const sdr::contact::DisplayInfo& /*rDisplayInfo*/,
1736 bool /*bEdit*/)
1738 // this will be handled in the application if needed
1739 return true;
1742 // DrawContact support: Methods for handling Page changes
1743 void SdrPage::ActionChanged()
1745 // Do necessary ViewContact actions
1746 GetViewContact().ActionChanged();
1748 // #i48535# also handle MasterPage change
1749 if(TRG_HasMasterPage())
1751 TRG_GetMasterPageDescriptorViewContact().ActionChanged();
1755 SdrPageProperties& SdrPage::getSdrPageProperties()
1757 return *mpSdrPageProperties;
1760 const SdrPageProperties& SdrPage::getSdrPageProperties() const
1762 return *mpSdrPageProperties;
1765 const SdrPageProperties* SdrPage::getCorrectSdrPageProperties() const
1767 if(mpMasterPageDescriptor)
1769 return mpMasterPageDescriptor->getCorrectSdrPageProperties();
1771 else
1773 return &getSdrPageProperties();
1778 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */