Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / svx / source / svdraw / svdpage.cxx
blob1b0f43d2080cd6bdc74ff63995ac18c138d9bb06
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>
26 #include <svx/unoshape.hxx>
28 #include <o3tl/safeint.hxx>
29 #include <string.h>
31 #include <tools/debug.hxx>
32 #include <comphelper/diagnose_ex.hxx>
33 #include <comphelper/lok.hxx>
35 #include <svtools/colorcfg.hxx>
36 #include <svx/svdetc.hxx>
37 #include <svx/svdobj.hxx>
38 #include <svx/svdogrp.hxx>
39 #include <svx/svdoedge.hxx>
40 #include <svx/svdoole2.hxx>
41 #include <svx/svditer.hxx>
42 #include <svx/svdmodel.hxx>
43 #include <svx/svdlayer.hxx>
44 #include <svx/svdpagv.hxx>
45 #include <svx/svdundo.hxx>
46 #include <svx/xfillit0.hxx>
47 #include <svx/fmdpage.hxx>
48 #include <svx/theme/ThemeColorChanger.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>
54 #include <algorithm>
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),
69 mbRectsDirty(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();
88 if(bBroadcast)
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
125 return nullptr;
128 SdrObject* SdrObjList::getSdrObjectFromSdrObjList() const
130 // default is no SdrObject (SdrObjGroup)
131 return nullptr;
134 void SdrObjList::CopyObjects(const SdrObjList& rSrcList)
136 CloneList aCloneList;
138 // clear SdrObjects with broadcasting
139 ClearSdrObjList();
141 mbObjOrdNumsDirty = false;
142 mbRectsDirty = false;
143 #ifdef DBG_UTIL
144 size_t nCloneErrCnt(0);
145 #endif
146 const size_t nCount(rSrcList.GetObjCount());
148 if(nullptr == getSdrObjectFromSdrObjList() && nullptr == getSdrPageFromSdrObjList())
150 OSL_ENSURE(false, "SdrObjList which is not part of SdrPage or SdrObject (!)");
151 return;
154 SdrModel& rTargetSdrModel(nullptr == getSdrObjectFromSdrObjList()
155 ? getSdrPageFromSdrObjList()->getSdrModelFromSdrPage()
156 : getSdrObjectFromSdrObjList()->getSdrModelFromSdrObject());
158 for (size_t no(0); no < nCount; ++no)
160 SdrObject* pSO(rSrcList.GetObj(no));
161 rtl::Reference<SdrObject> pDO(pSO->CloneSdrObject(rTargetSdrModel));
163 if(pDO)
165 NbcInsertObject(pDO.get(), SAL_MAX_SIZE);
166 aCloneList.AddPair(pSO, pDO.get());
168 #ifdef DBG_UTIL
169 else
171 nCloneErrCnt++;
173 #endif
176 // Wires up the connections
177 aCloneList.CopyConnections();
178 #ifdef DBG_UTIL
179 if (nCloneErrCnt != 0)
181 OStringBuffer aStr("SdrObjList::operator=(): Error when cloning ");
183 if(nCloneErrCnt == 1)
185 aStr.append("a drawing object.");
187 else
189 aStr.append(OString::number(static_cast<sal_Int32>(nCloneErrCnt))
190 + " drawing objects.");
193 OSL_FAIL(aStr.getStr());
195 #endif
198 void SdrObjList::RecalcObjOrdNums()
200 size_t no=0;
201 for (const rtl::Reference<SdrObject>& pObj : maList)
202 pObj->SetOrdNum(no++);
203 mbObjOrdNumsDirty=false;
206 void SdrObjList::RecalcRects()
208 maSdrObjListOutRect=tools::Rectangle();
209 maSdrObjListSnapRect=maSdrObjListOutRect;
210 const size_t nCount = GetObjCount();
211 for (size_t i=0; i<nCount; ++i) {
212 SdrObject* pObj=GetObj(i);
213 if (i==0) {
214 maSdrObjListOutRect=pObj->GetCurrentBoundRect();
215 maSdrObjListSnapRect=pObj->GetSnapRect();
216 } else {
217 maSdrObjListOutRect.Union(pObj->GetCurrentBoundRect());
218 maSdrObjListSnapRect.Union(pObj->GetSnapRect());
223 void SdrObjList::SetSdrObjListRectsDirty()
225 mbRectsDirty=true;
226 SdrObject* pParentSdrObject(getSdrObjectFromSdrObjList());
228 if(nullptr != pParentSdrObject)
230 pParentSdrObject->SetBoundAndSnapRectsDirty();
234 void SdrObjList::impChildInserted(SdrObject const & rChild)
236 sdr::contact::ViewContact* pParent = rChild.GetViewContact().GetParentContact();
238 if(pParent)
240 pParent->ActionChildInserted(rChild.GetViewContact());
244 void SdrObjList::NbcInsertObject(SdrObject* pObj, size_t nPos)
246 DBG_ASSERT(pObj!=nullptr,"SdrObjList::NbcInsertObject(NULL)");
247 if (pObj==nullptr)
248 return;
250 DBG_ASSERT(!pObj->IsInserted(),"The object already has the status Inserted.");
251 const size_t nCount = GetObjCount();
252 if (nPos>nCount) nPos=nCount;
253 InsertObjectIntoContainer(*pObj,nPos);
255 if (nPos<nCount) mbObjOrdNumsDirty=true;
256 pObj->SetOrdNum(nPos);
257 pObj->setParentOfSdrObject(this);
259 // Inform the parent about change to allow invalidations at
260 // evtl. existing parent visualisations
261 impChildInserted(*pObj);
263 if (!mbRectsDirty) {
264 mbRectsDirty = true;
266 pObj->InsertedStateChange(); // calls the UserCall (among others)
269 void SdrObjList::InsertObjectThenMakeNameUnique(SdrObject* pObj)
271 std::unordered_set<rtl::OUString> aNameSet;
272 InsertObjectThenMakeNameUnique(pObj, aNameSet);
275 void SdrObjList::InsertObjectThenMakeNameUnique(SdrObject* pObj, std::unordered_set<OUString>& rNameSet, size_t nPos)
277 InsertObject(pObj, nPos);
278 if (pObj->GetName().isEmpty())
279 return;
281 pObj->MakeNameUnique(rNameSet);
282 SdrObjList* pSdrObjList = pObj->GetSubList(); // group
283 if (pSdrObjList)
285 SdrObject* pListObj;
286 SdrObjListIter aIter(pSdrObjList, SdrIterMode::DeepWithGroups);
287 while (aIter.IsMore())
289 pListObj = aIter.Next();
290 pListObj->MakeNameUnique(rNameSet);
295 void SdrObjList::InsertObject(SdrObject* pObj, size_t nPos)
297 DBG_ASSERT(pObj!=nullptr,"SdrObjList::InsertObject(NULL)");
299 if(!pObj)
300 return;
302 // if anchor is used, reset it before grouping
303 if(getSdrObjectFromSdrObjList())
305 const Point& rAnchorPos = pObj->GetAnchorPos();
306 if(rAnchorPos.X() || rAnchorPos.Y())
307 pObj->NbcSetAnchorPos(Point());
310 // do insert to new group
311 NbcInsertObject(pObj, nPos);
313 // In case the object is inserted into a group and doesn't overlap with
314 // the group's other members, it needs an own repaint.
315 SdrObject* pParentSdrObject(getSdrObjectFromSdrObjList());
317 if(pParentSdrObject)
319 // only repaint here
320 pParentSdrObject->ActionChanged();
323 // TODO: We need a different broadcast here!
324 // Repaint from object number ... (heads-up: GroupObj)
325 if(pObj->getSdrPageFromSdrObject() && !pObj->getSdrModelFromSdrObject().isLocked())
327 SdrHint aHint(SdrHintKind::ObjectInserted, *pObj);
328 pObj->getSdrModelFromSdrObject().Broadcast(aHint);
331 pObj->getSdrModelFromSdrObject().SetChanged();
334 rtl::Reference<SdrObject> SdrObjList::NbcRemoveObject(size_t nObjNum)
336 if (nObjNum >= maList.size())
338 OSL_ASSERT(nObjNum<maList.size());
339 return nullptr;
342 const size_t nCount = GetObjCount();
343 rtl::Reference<SdrObject> pObj=maList[nObjNum];
344 RemoveObjectFromContainer(nObjNum);
346 DBG_ASSERT(pObj!=nullptr,"Could not find object to remove.");
347 if (pObj!=nullptr)
349 // flushViewObjectContacts() clears the VOC's and those invalidate
350 pObj->GetViewContact().flushViewObjectContacts();
352 DBG_ASSERT(pObj->IsInserted(),"The object does not have the status Inserted.");
354 // tdf#121022 Do first remove from SdrObjList - InsertedStateChange
355 // relies now on IsInserted which uses getParentSdrObjListFromSdrObject
356 pObj->setParentOfSdrObject(nullptr);
358 // calls UserCall, among other
359 pObj->InsertedStateChange();
361 if (!mbObjOrdNumsDirty)
363 // optimizing for the case that the last object has to be removed
364 if (nObjNum+1!=nCount) {
365 mbObjOrdNumsDirty=true;
368 SetSdrObjListRectsDirty();
370 return pObj;
373 rtl::Reference<SdrObject> SdrObjList::RemoveObject(size_t nObjNum)
375 if (nObjNum >= maList.size())
377 OSL_ASSERT(nObjNum<maList.size());
378 return nullptr;
381 const size_t nCount = GetObjCount();
382 rtl::Reference<SdrObject> pObj=maList[nObjNum];
383 RemoveObjectFromContainer(nObjNum);
385 DBG_ASSERT(pObj!=nullptr,"Object to remove not found.");
386 if(pObj)
388 // flushViewObjectContacts() clears the VOC's and those invalidate
389 pObj->GetViewContact().flushViewObjectContacts();
390 DBG_ASSERT(pObj->IsInserted(),"The object does not have the status Inserted.");
392 // TODO: We need a different broadcast here.
393 if (pObj->getSdrPageFromSdrObject()!=nullptr)
395 SdrHint aHint(SdrHintKind::ObjectRemoved, *pObj);
396 pObj->getSdrModelFromSdrObject().Broadcast(aHint);
399 pObj->getSdrModelFromSdrObject().SetChanged();
401 // tdf#121022 Do first remove from SdrObjList - InsertedStateChange
402 // relies now on IsInserted which uses getParentSdrObjListFromSdrObject
403 pObj->setParentOfSdrObject(nullptr);
405 // calls, among other things, the UserCall
406 pObj->InsertedStateChange();
408 if (!mbObjOrdNumsDirty)
410 // optimization for the case that the last object is removed
411 if (nObjNum+1!=nCount) {
412 mbObjOrdNumsDirty=true;
416 SetSdrObjListRectsDirty();
417 SdrObject* pParentSdrObject(getSdrObjectFromSdrObjList());
419 if(pParentSdrObject && !GetObjCount())
421 // empty group created; it needs to be repainted since it's
422 // visualization changes
423 pParentSdrObject->ActionChanged();
426 return pObj;
429 rtl::Reference<SdrObject> SdrObjList::ReplaceObject(SdrObject* pNewObj, size_t nObjNum)
431 if (nObjNum >= maList.size())
433 OSL_ASSERT(nObjNum<maList.size());
434 return nullptr;
436 if (pNewObj == nullptr)
438 OSL_ASSERT(pNewObj!=nullptr);
439 return nullptr;
442 rtl::Reference<SdrObject> pObj=maList[nObjNum];
443 DBG_ASSERT(pObj!=nullptr,"SdrObjList::ReplaceObject: Could not find object to remove.");
444 if (pObj!=nullptr) {
445 DBG_ASSERT(pObj->IsInserted(),"SdrObjList::ReplaceObject: the object does not have status Inserted.");
447 // TODO: We need a different broadcast here.
448 if (pObj->getSdrPageFromSdrObject()!=nullptr)
450 SdrHint aHint(SdrHintKind::ObjectRemoved, *pObj);
451 pObj->getSdrModelFromSdrObject().Broadcast(aHint);
454 // Change parent and replace in SdrObjList
455 pObj->setParentOfSdrObject(nullptr);
456 ReplaceObjectInContainer(*pNewObj,nObjNum);
458 // tdf#121022 InsertedStateChange uses the parent
459 // to detect if pObj is inserted or not, so have to call
460 // it *after* changing these settings, else an obviously wrong
461 // 'SdrUserCallType::Inserted' would be sent
462 pObj->InsertedStateChange();
464 // flushViewObjectContacts() clears the VOC's and those
465 // trigger the evtl. needed invalidate(s)
466 pObj->GetViewContact().flushViewObjectContacts();
468 // Setup data at new SdrObject - it already *is* inserted to
469 // the SdrObjList due to 'ReplaceObjectInContainer' above
470 pNewObj->SetOrdNum(nObjNum);
471 pNewObj->setParentOfSdrObject(this);
473 // Inform the parent about change to allow invalidations at
474 // evtl. existing parent visualisations, but also react on
475 // newly inserted SdrObjects (as e.g. GraphCtrlUserCall does)
476 impChildInserted(*pNewObj);
478 pNewObj->InsertedStateChange();
480 // TODO: We need a different broadcast here.
481 if (pNewObj->getSdrPageFromSdrObject()!=nullptr) {
482 SdrHint aHint(SdrHintKind::ObjectInserted, *pNewObj);
483 pNewObj->getSdrModelFromSdrObject().Broadcast(aHint);
486 pNewObj->getSdrModelFromSdrObject().SetChanged();
488 SetSdrObjListRectsDirty();
490 return pObj;
493 SdrObject* SdrObjList::SetObjectOrdNum(size_t nOldObjNum, size_t nNewObjNum)
495 if (nOldObjNum >= maList.size() || nNewObjNum >= maList.size())
497 OSL_ASSERT(nOldObjNum<maList.size());
498 OSL_ASSERT(nNewObjNum<maList.size());
499 return nullptr;
502 rtl::Reference<SdrObject> pObj=maList[nOldObjNum];
503 if (nOldObjNum==nNewObjNum) return pObj.get();
504 DBG_ASSERT(pObj!=nullptr,"SdrObjList::SetObjectOrdNum: Object not found.");
505 if (pObj!=nullptr) {
506 DBG_ASSERT(pObj->IsInserted(),"SdrObjList::SetObjectOrdNum: the object does not have status Inserted.");
507 RemoveObjectFromContainer(nOldObjNum);
508 InsertObjectIntoContainer(*pObj,nNewObjNum);
510 // No need to delete visualisation data since same object
511 // gets inserted again. Also a single ActionChanged is enough
512 pObj->ActionChanged();
514 pObj->SetOrdNum(nNewObjNum);
515 mbObjOrdNumsDirty=true;
517 // TODO: We need a different broadcast here.
518 if (pObj->getSdrPageFromSdrObject()!=nullptr)
519 pObj->getSdrModelFromSdrObject().Broadcast(SdrHint(SdrHintKind::ObjectChange, *pObj));
520 pObj->getSdrModelFromSdrObject().SetChanged();
522 return pObj.get();
525 void SdrObjList::SetExistingObjectOrdNum(SdrObject* pObj, size_t nNewObjNum)
527 assert(std::find(maList.begin(), maList.end(), pObj) != maList.end() && "This method requires that the child object already be inserted");
528 assert(pObj->IsInserted() && "SdrObjList::SetObjectOrdNum: the object does not have status Inserted.");
530 // I am deliberately bypassing getOrdNum() because I don't want to unnecessarily
531 // trigger RecalcObjOrdNums()
532 const sal_uInt32 nOldOrdNum = pObj->m_nOrdNum;
533 if (!mbObjOrdNumsDirty && nOldOrdNum == nNewObjNum)
534 return;
536 // Update the navigation positions.
537 if (HasObjectNavigationOrder())
539 unotools::WeakReference<SdrObject> aReference (pObj);
540 auto iObject = ::std::find(
541 mxNavigationOrder->begin(),
542 mxNavigationOrder->end(),
543 aReference);
544 mxNavigationOrder->erase(iObject);
545 mbIsNavigationOrderDirty = true;
546 // The new object does not have a user defined position so append it
547 // to the list.
548 pObj->SetNavigationPosition(mxNavigationOrder->size());
549 mxNavigationOrder->push_back(pObj);
551 if (nOldOrdNum < maList.size() && maList[nOldOrdNum] == pObj)
552 maList.erase(maList.begin()+nOldOrdNum);
553 else
555 auto it = std::find(maList.begin(), maList.end(), pObj);
556 maList.erase(it);
558 // Insert object into object list. Because the insert() method requires
559 // a valid iterator as insertion position, we have to use push_back() to
560 // insert at the end of the list.
561 if (nNewObjNum >= maList.size())
562 maList.push_back(pObj);
563 else
564 maList.insert(maList.begin()+nNewObjNum, pObj);
566 mbObjOrdNumsDirty=true;
568 // No need to delete visualisation data since same object
569 // gets inserted again. Also a single ActionChanged is enough
570 pObj->ActionChanged();
572 pObj->SetOrdNum(nNewObjNum);
573 mbObjOrdNumsDirty=true;
575 // TODO: We need a different broadcast here.
576 if (pObj->getSdrPageFromSdrObject()!=nullptr)
577 pObj->getSdrModelFromSdrObject().Broadcast(SdrHint(SdrHintKind::ObjectChange, *pObj));
578 pObj->getSdrModelFromSdrObject().SetChanged();
581 void SdrObjList::sort( std::vector<sal_Int32>& sortOrder)
583 // no negative indexes and indexes larger than maList size are allowed
584 auto it = std::find_if( sortOrder.begin(), sortOrder.end(), [this](const sal_Int32& rIt)
585 { return ( rIt < 0 || o3tl::make_unsigned(rIt) >= maList.size() ); } );
586 if ( it != sortOrder.end())
587 throw css::lang::IllegalArgumentException("negative index of shape", nullptr, 1);
589 // no duplicates
590 std::vector<bool> aNoDuplicates(sortOrder.size(), false);
591 for (size_t i = 0; i < sortOrder.size(); ++i )
593 size_t idx = static_cast<size_t>( sortOrder[i] );
595 if ( aNoDuplicates[idx] )
596 throw css::lang::IllegalArgumentException("duplicate index of shape", nullptr, 2);
598 aNoDuplicates[idx] = true;
601 // example sortOrder [2 0 1]
602 // example maList [T T S T T] ( T T = shape with textbox, S = just a shape )
603 // (shapes at positions 0 and 2 have a textbox)
605 std::deque<rtl::Reference<SdrObject>> aNewList(maList.size());
606 std::set<sal_Int32> aShapesWithTextbox;
607 std::vector<sal_Int32> aIncrements;
608 std::vector<sal_Int32> aDuplicates;
610 if ( maList.size() > 1)
612 for (size_t i = 1; i< maList.size(); ++i)
614 // if this shape is a textbox, then look at its left neighbour
615 // (shape this textbox is in)
616 // and insert the number of textboxes to the left of it
617 if (maList[i]->IsTextBox())
618 aShapesWithTextbox.insert( i - 1 - aShapesWithTextbox.size() );
620 // example aShapesWithTextbox [0 2]
623 if (aShapesWithTextbox.size() != maList.size() - sortOrder.size())
625 throw lang::IllegalArgumentException("mismatch of no. of shapes", nullptr, 0);
628 for (size_t i = 0; i< sortOrder.size(); ++i)
631 if (aShapesWithTextbox.count(sortOrder[i]) > 0)
632 aDuplicates.push_back(sortOrder[i]);
634 aDuplicates.push_back(sortOrder[i]);
636 // example aDuplicates [2 2 0 0 1]
638 assert(aDuplicates.size() == maList.size());
640 aIncrements.push_back(0);
641 for (size_t i = 1; i< sortOrder.size(); ++i)
643 if (aShapesWithTextbox.count(i - 1))
644 aIncrements.push_back(aIncrements[i-1] + 1 );
645 else
646 aIncrements.push_back(aIncrements[i-1]);
648 // example aIncrements [0 1 1]
650 assert(aIncrements.size() == sortOrder.size());
652 std::vector<sal_Int32> aNewSortOrder(maList.size());
653 sal_Int32 nPrev = -1;
654 for (size_t i = 0; i< aDuplicates.size(); ++i)
656 if (nPrev != aDuplicates[i])
657 aNewSortOrder[i] = aDuplicates[i] + aIncrements[aDuplicates[i]];
658 else
659 aNewSortOrder[i] = aNewSortOrder[i-1] + 1;
661 nPrev = aDuplicates[i];
663 // example aNewSortOrder [3 4 0 1 2]
665 assert(aNewSortOrder.size() == maList.size());
667 #ifndef NDEBUG
669 std::vector<sal_Int32> tmp(aNewSortOrder);
670 std::sort(tmp.begin(), tmp.end());
671 for (size_t i = 0; i < tmp.size(); ++i)
673 assert(size_t(tmp[i]) == i);
676 #endif
678 SdrModel & rModel(getSdrPageFromSdrObjList()->getSdrModelFromSdrPage());
679 bool const isUndo(rModel.IsUndoEnabled());
680 if (isUndo)
682 rModel.AddUndo(SdrUndoFactory::CreateUndoSort(*getSdrPageFromSdrObjList(), sortOrder));
685 for (size_t i = 0; i < aNewSortOrder.size(); ++i)
687 aNewList[i] = maList[ aNewSortOrder[i] ];
688 aNewList[i]->SetOrdNum(i);
691 std::swap(aNewList, maList);
694 const tools::Rectangle& SdrObjList::GetAllObjSnapRect() const
696 if (mbRectsDirty) {
697 const_cast<SdrObjList*>(this)->RecalcRects();
698 const_cast<SdrObjList*>(this)->mbRectsDirty=false;
700 return maSdrObjListSnapRect;
703 const tools::Rectangle& SdrObjList::GetAllObjBoundRect() const
705 // #i106183# for deep group hierarchies like in chart2, the invalidates
706 // through the hierarchy are not correct; use a 2nd hint for the needed
707 // recalculation. Future versions will have no bool flag at all, but
708 // just maSdrObjListOutRect in empty state to represent an invalid state, thus
709 // it's a step in the right direction.
710 if (mbRectsDirty || maSdrObjListOutRect.IsEmpty())
712 const_cast<SdrObjList*>(this)->RecalcRects();
713 const_cast<SdrObjList*>(this)->mbRectsDirty=false;
715 return maSdrObjListOutRect;
718 void SdrObjList::NbcReformatAllTextObjects()
720 size_t nCount=GetObjCount();
721 size_t nNum=0;
723 while (nNum<nCount)
725 SdrObject* pObj = GetObj(nNum);
727 pObj->NbcReformatText();
728 nCount=GetObjCount(); // ReformatText may delete an object
729 nNum++;
734 void SdrObjList::ReformatAllTextObjects()
736 NbcReformatAllTextObjects();
739 /** steps over all available objects and reformats all
740 edge objects that are connected to other objects so that
741 they may reposition themselves.
743 void SdrObjList::ReformatAllEdgeObjects()
745 ImplReformatAllEdgeObjects(*this);
748 void SdrObjList::ImplReformatAllEdgeObjects(const SdrObjList& rObjList)
750 // #i120437# go over whole hierarchy, not only over object level null (seen from grouping)
751 for(size_t nIdx(0), nCount(rObjList.GetObjCount()); nIdx < nCount; ++nIdx)
753 SdrObject* pSdrObject(rObjList.GetObjectForNavigationPosition(nIdx));
754 const SdrObjList* pChildren(pSdrObject->getChildrenOfSdrObject());
755 const bool bIsGroup(nullptr != pChildren);
756 if(!bIsGroup)
758 // Check IsVirtualObj because sometimes we get SwDrawVirtObj here
759 if (pSdrObject->GetObjIdentifier() == SdrObjKind::Edge
760 && !pSdrObject->IsVirtualObj())
762 SdrEdgeObj* pSdrEdgeObj = static_cast< SdrEdgeObj* >(pSdrObject);
763 pSdrEdgeObj->Reformat();
766 else
768 ImplReformatAllEdgeObjects(*pChildren);
773 void SdrObjList::BurnInStyleSheetAttributes()
775 for(size_t a = 0; a < GetObjCount(); ++a)
777 GetObj(a)->BurnInStyleSheetAttributes();
781 size_t SdrObjList::GetObjCount() const
783 return maList.size();
787 SdrObject* SdrObjList::GetObj(size_t nNum) const
789 if (nNum < maList.size())
790 return maList[nNum].get();
792 return nullptr;
795 SdrObject* SdrObjList::GetObjByName(std::u16string_view sName) const
797 for (size_t i = 0; i < GetObjCount(); ++i)
799 SdrObject* pObj = GetObj(i);
800 if (pObj->GetName() == sName)
801 return pObj;
803 return nullptr;
807 bool SdrObjList::IsReadOnly() const
809 bool bRet(false);
810 SdrObject* pParentSdrObject(getSdrObjectFromSdrObjList());
812 if(nullptr != pParentSdrObject)
814 SdrPage* pSdrPage(pParentSdrObject->getSdrPageFromSdrObject());
816 if(nullptr != pSdrPage)
818 bRet = pSdrPage->IsReadOnly();
822 return bRet;
825 void SdrObjList::FlattenGroups()
827 const size_t nObj = GetObjCount();
828 for( size_t i = nObj; i>0; )
829 UnGroupObj(--i);
832 void SdrObjList::UnGroupObj( size_t nObjNum )
834 // if the given object is no group, this method is a noop
835 SdrObject* pUngroupObj = GetObj( nObjNum );
836 if( pUngroupObj )
838 SdrObjList* pSrcLst = pUngroupObj->GetSubList();
839 if(pSrcLst)
840 if(auto pUngroupGroup = dynamic_cast<SdrObjGroup*>( pUngroupObj))
842 // ungroup recursively (has to be head recursion,
843 // otherwise our indices will get trashed when doing it in
844 // the loop)
845 pSrcLst->FlattenGroups();
847 // the position at which we insert the members of rUngroupGroup
848 size_t nInsertPos( pUngroupGroup->GetOrdNum() );
850 const size_t nCount = pSrcLst->GetObjCount();
851 for( size_t i=0; i<nCount; ++i )
853 rtl::Reference<SdrObject> pObj = pSrcLst->RemoveObject(0);
854 InsertObject(pObj.get(), nInsertPos);
855 ++nInsertPos;
858 RemoveObject(nInsertPos);
861 #ifdef DBG_UTIL
862 else
863 OSL_FAIL("SdrObjList::UnGroupObj: object index invalid");
864 #endif
867 bool SdrObjList::HasObjectNavigationOrder() const { return bool(mxNavigationOrder); }
869 void SdrObjList::SetObjectNavigationPosition (
870 SdrObject& rObject,
871 const sal_uInt32 nNewPosition)
873 // When the navigation order container has not yet been created then
874 // create one now. It is initialized with the z-order taken from
875 // maList.
876 if (!mxNavigationOrder)
878 mxNavigationOrder.emplace(maList.begin(), maList.end());
880 OSL_ASSERT(bool(mxNavigationOrder));
881 OSL_ASSERT( mxNavigationOrder->size() == maList.size());
883 unotools::WeakReference<SdrObject> aReference (&rObject);
885 // Look up the object whose navigation position is to be changed.
886 auto iObject = ::std::find(
887 mxNavigationOrder->begin(),
888 mxNavigationOrder->end(),
889 aReference);
890 if (iObject == mxNavigationOrder->end())
892 // The given object is not a member of the navigation order.
893 return;
896 // Move the object to its new position.
897 const sal_uInt32 nOldPosition = ::std::distance(mxNavigationOrder->begin(), iObject);
898 if (nOldPosition == nNewPosition)
899 return;
901 mxNavigationOrder->erase(iObject);
902 sal_uInt32 nInsertPosition (nNewPosition);
903 // Adapt insertion position for the just erased object.
904 if (nNewPosition >= nOldPosition)
905 nInsertPosition -= 1;
906 if (nInsertPosition >= mxNavigationOrder->size())
907 mxNavigationOrder->push_back(aReference);
908 else
909 mxNavigationOrder->insert(mxNavigationOrder->begin()+nInsertPosition, aReference);
911 mbIsNavigationOrderDirty = true;
913 // The navigation order is written out to file so mark the model as modified.
914 rObject.getSdrModelFromSdrObject().SetChanged();
918 SdrObject* SdrObjList::GetObjectForNavigationPosition (const sal_uInt32 nNavigationPosition) const
920 if (HasObjectNavigationOrder())
922 // There is a user defined navigation order. Make sure the object
923 // index is correct and look up the object in mxNavigationOrder.
924 if (nNavigationPosition >= mxNavigationOrder->size())
926 OSL_ASSERT(nNavigationPosition < mxNavigationOrder->size());
928 else
929 return (*mxNavigationOrder)[nNavigationPosition].get().get();
931 else
933 // There is no user defined navigation order. Use the z-order
934 // instead.
935 if (nNavigationPosition >= maList.size())
937 OSL_ASSERT(nNavigationPosition < maList.size());
939 else
940 return maList[nNavigationPosition].get();
942 return nullptr;
946 void SdrObjList::ClearObjectNavigationOrder()
948 mxNavigationOrder.reset();
949 mbIsNavigationOrderDirty = true;
953 bool SdrObjList::RecalcNavigationPositions()
955 if (mbIsNavigationOrderDirty)
957 if (mxNavigationOrder)
959 mbIsNavigationOrderDirty = false;
961 sal_uInt32 nIndex (0);
962 for (auto& rpObject : *mxNavigationOrder)
964 rpObject.get()->SetNavigationPosition(nIndex);
965 ++nIndex;
970 return bool(mxNavigationOrder);
974 void SdrObjList::SetNavigationOrder (const uno::Reference<container::XIndexAccess>& rxOrder)
976 if (rxOrder.is())
978 const sal_Int32 nCount = rxOrder->getCount();
979 if (static_cast<sal_uInt32>(nCount) != maList.size())
980 return;
982 if (!mxNavigationOrder)
983 mxNavigationOrder = std::vector<unotools::WeakReference<SdrObject>>(nCount);
985 for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex)
987 uno::Reference<uno::XInterface> xShape (rxOrder->getByIndex(nIndex), uno::UNO_QUERY);
988 SdrObject* pObject = SdrObject::getSdrObjectFromXShape(xShape);
989 if (pObject == nullptr)
990 break;
991 (*mxNavigationOrder)[nIndex] = pObject;
994 mbIsNavigationOrderDirty = true;
996 else
998 ClearObjectNavigationOrder();
1003 void SdrObjList::InsertObjectIntoContainer (
1004 SdrObject& rObject,
1005 const sal_uInt32 nInsertPosition)
1007 OSL_ASSERT(nInsertPosition<=maList.size());
1009 // Update the navigation positions.
1010 if (HasObjectNavigationOrder())
1012 // The new object does not have a user defined position so append it
1013 // to the list.
1014 rObject.SetNavigationPosition(mxNavigationOrder->size());
1015 mxNavigationOrder->push_back(&rObject);
1018 // Insert object into object list. Because the insert() method requires
1019 // a valid iterator as insertion position, we have to use push_back() to
1020 // insert at the end of the list.
1021 if (nInsertPosition >= maList.size())
1022 maList.push_back(&rObject);
1023 else
1024 maList.insert(maList.begin()+nInsertPosition, &rObject);
1025 mbObjOrdNumsDirty=true;
1029 void SdrObjList::ReplaceObjectInContainer (
1030 SdrObject& rNewObject,
1031 const sal_uInt32 nObjectPosition)
1033 if (nObjectPosition >= maList.size())
1035 OSL_ASSERT(nObjectPosition<maList.size());
1036 return;
1039 // Update the navigation positions.
1040 if (HasObjectNavigationOrder())
1042 // A user defined position of the object that is to be replaced is
1043 // not transferred to the new object so erase the former and append
1044 // the later object from/to the navigation order.
1045 OSL_ASSERT(nObjectPosition < maList.size());
1046 unotools::WeakReference<SdrObject> aReference (maList[nObjectPosition].get());
1047 auto iObject = ::std::find(
1048 mxNavigationOrder->begin(),
1049 mxNavigationOrder->end(),
1050 aReference);
1051 if (iObject != mxNavigationOrder->end())
1052 mxNavigationOrder->erase(iObject);
1054 mxNavigationOrder->push_back(&rNewObject);
1056 mbIsNavigationOrderDirty = true;
1059 maList[nObjectPosition] = &rNewObject;
1060 mbObjOrdNumsDirty=true;
1064 void SdrObjList::RemoveObjectFromContainer (
1065 const sal_uInt32 nObjectPosition)
1067 if (nObjectPosition >= maList.size())
1069 OSL_ASSERT(nObjectPosition<maList.size());
1070 return;
1073 // Update the navigation positions.
1074 if (HasObjectNavigationOrder())
1076 unotools::WeakReference<SdrObject> aReference (maList[nObjectPosition]);
1077 auto iObject = ::std::find(
1078 mxNavigationOrder->begin(),
1079 mxNavigationOrder->end(),
1080 aReference);
1081 if (iObject != mxNavigationOrder->end())
1082 mxNavigationOrder->erase(iObject);
1083 mbIsNavigationOrderDirty = true;
1086 maList.erase(maList.begin()+nObjectPosition);
1087 mbObjOrdNumsDirty=true;
1090 void SdrObjList::dumpAsXml(xmlTextWriterPtr pWriter) const
1092 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SdrObjList"));
1093 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
1094 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
1096 size_t nObjCount = GetObjCount();
1097 for (size_t i = 0; i < nObjCount; ++i)
1099 if (const SdrObject* pObject = GetObj(i))
1100 pObject->dumpAsXml(pWriter);
1103 (void)xmlTextWriterEndElement(pWriter);
1107 void SdrPageGridFrameList::Clear()
1109 sal_uInt16 nCount=GetCount();
1110 for (sal_uInt16 i=0; i<nCount; i++) {
1111 delete GetObject(i);
1113 aList.clear();
1117 // PageUser section
1119 void SdrPage::AddPageUser(sdr::PageUser& rNewUser)
1121 maPageUsers.push_back(&rNewUser);
1124 void SdrPage::RemovePageUser(sdr::PageUser& rOldUser)
1126 const sdr::PageUserVector::iterator aFindResult = ::std::find(maPageUsers.begin(), maPageUsers.end(), &rOldUser);
1127 if(aFindResult != maPageUsers.end())
1129 maPageUsers.erase(aFindResult);
1134 // DrawContact section
1136 std::unique_ptr<sdr::contact::ViewContact> SdrPage::CreateObjectSpecificViewContact()
1138 return std::make_unique<sdr::contact::ViewContactOfSdrPage>(*this);
1141 const sdr::contact::ViewContact& SdrPage::GetViewContact() const
1143 if (!mpViewContact)
1144 const_cast<SdrPage*>(this)->mpViewContact =
1145 const_cast<SdrPage*>(this)->CreateObjectSpecificViewContact();
1147 return *mpViewContact;
1150 sdr::contact::ViewContact& SdrPage::GetViewContact()
1152 if (!mpViewContact)
1153 mpViewContact = CreateObjectSpecificViewContact();
1155 return *mpViewContact;
1158 void SdrPageProperties::ImpRemoveStyleSheet()
1160 if(mpStyleSheet)
1162 EndListening(*mpStyleSheet);
1163 maProperties.SetParent(nullptr);
1164 mpStyleSheet = nullptr;
1168 void SdrPageProperties::ImpAddStyleSheet(SfxStyleSheet& rNewStyleSheet)
1170 if(mpStyleSheet != &rNewStyleSheet)
1172 ImpRemoveStyleSheet();
1173 mpStyleSheet = &rNewStyleSheet;
1174 StartListening(rNewStyleSheet);
1175 maProperties.SetParent(&rNewStyleSheet.GetItemSet());
1179 static void ImpPageChange(SdrPage& rSdrPage)
1181 rSdrPage.ActionChanged();
1182 rSdrPage.getSdrModelFromSdrPage().SetChanged();
1183 SdrHint aHint(SdrHintKind::PageOrderChange, &rSdrPage);
1184 rSdrPage.getSdrModelFromSdrPage().Broadcast(aHint);
1187 SdrPageProperties::SdrPageProperties(SdrPage& rSdrPage)
1188 : mpSdrPage(&rSdrPage)
1189 , mpStyleSheet(nullptr)
1190 , maProperties(
1191 mpSdrPage->getSdrModelFromSdrPage().GetItemPool(),
1192 svl::Items<XATTR_FILL_FIRST, XATTR_FILL_LAST>)
1194 if (!rSdrPage.IsMasterPage())
1196 maProperties.Put(XFillStyleItem(drawing::FillStyle_NONE));
1199 //if (rSdrPage.getSdrModelFromSdrPage().IsWriter() || rSdrPage.IsMasterPage())
1201 mpTheme.reset(new model::Theme("Office Theme"));
1202 auto const* pColorSet = svx::ColorSets::get().getColorSet(u"LibreOffice");
1203 if (pColorSet)
1205 std::shared_ptr<model::ColorSet> pDefaultColorSet(new model::ColorSet(*pColorSet));
1206 mpTheme->setColorSet(pDefaultColorSet);
1211 SdrPageProperties::~SdrPageProperties()
1213 ImpRemoveStyleSheet();
1216 void SdrPageProperties::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
1218 switch(rHint.GetId())
1220 case SfxHintId::DataChanged :
1222 // notify change, broadcast
1223 ImpPageChange(*mpSdrPage);
1224 break;
1226 case SfxHintId::Dying :
1228 // Style needs to be forgotten
1229 ImpRemoveStyleSheet();
1230 break;
1232 default: break;
1236 bool SdrPageProperties::isUsedByModel() const
1238 assert(mpSdrPage);
1239 return mpSdrPage->IsInserted();
1243 void SdrPageProperties::PutItemSet(const SfxItemSet& rSet)
1245 OSL_ENSURE(!mpSdrPage->IsMasterPage(), "Item set at MasterPage Attributes (!)");
1246 maProperties.Put(rSet);
1247 ImpPageChange(*mpSdrPage);
1250 void SdrPageProperties::PutItem(const SfxPoolItem& rItem)
1252 OSL_ENSURE(!mpSdrPage->IsMasterPage(), "Item set at MasterPage Attributes (!)");
1253 maProperties.Put(rItem);
1254 ImpPageChange(*mpSdrPage);
1257 void SdrPageProperties::ClearItem(const sal_uInt16 nWhich)
1259 maProperties.ClearItem(nWhich);
1260 ImpPageChange(*mpSdrPage);
1263 void SdrPageProperties::SetStyleSheet(SfxStyleSheet* pStyleSheet)
1265 if(pStyleSheet)
1267 ImpAddStyleSheet(*pStyleSheet);
1269 else
1271 ImpRemoveStyleSheet();
1274 ImpPageChange(*mpSdrPage);
1277 void SdrPageProperties::SetTheme(std::shared_ptr<model::Theme> const& pTheme)
1279 if (mpTheme == pTheme)
1280 return;
1282 mpTheme = pTheme;
1284 if (mpTheme && mpTheme->getColorSet() && mpSdrPage->IsMasterPage())
1286 SdrModel& rModel = mpSdrPage->getSdrModelFromSdrPage();
1287 sal_uInt16 nPageCount = rModel.GetPageCount();
1288 for (sal_uInt16 nPage = 0; nPage < nPageCount; ++nPage)
1290 SdrPage* pPage = rModel.GetPage(nPage);
1291 if (!pPage->TRG_HasMasterPage() || &pPage->TRG_GetMasterPage() != mpSdrPage)
1293 continue;
1296 svx::ThemeColorChanger aChanger(pPage);
1297 aChanger.apply(mpTheme->getColorSet());
1302 std::shared_ptr<model::Theme> const& SdrPageProperties::GetTheme() const
1304 return mpTheme;
1307 void SdrPageProperties::dumpAsXml(xmlTextWriterPtr pWriter) const
1309 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SdrPageProperties"));
1310 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
1312 if (mpTheme)
1314 mpTheme->dumpAsXml(pWriter);
1317 (void)xmlTextWriterEndElement(pWriter);
1320 SdrPage::SdrPage(SdrModel& rModel, bool bMasterPage)
1321 : mrSdrModelFromSdrPage(rModel),
1322 mnWidth(10),
1323 mnHeight(10),
1324 mnBorderLeft(0),
1325 mnBorderUpper(0),
1326 mnBorderRight(0),
1327 mnBorderLower(0),
1328 mpLayerAdmin(new SdrLayerAdmin(&rModel.GetLayerAdmin())),
1329 nPageNum(0),
1330 mbMaster(bMasterPage),
1331 mbInserted(false),
1332 mbObjectsNotPersistent(false),
1333 mbPageBorderOnlyLeftRight(false)
1335 mpSdrPageProperties.reset(new SdrPageProperties(*this));
1338 SdrPage::~SdrPage()
1340 if( mxUnoPage.is() ) try
1342 uno::Reference< lang::XComponent > xPageComponent( mxUnoPage, uno::UNO_QUERY_THROW );
1343 mxUnoPage.clear();
1344 xPageComponent->dispose();
1346 catch( const uno::Exception& )
1348 DBG_UNHANDLED_EXCEPTION("svx");
1351 // tell all the registered PageUsers that the page is in destruction
1352 // This causes some (all?) PageUsers to remove themselves from the list
1353 // of page users. Therefore we have to use a copy of the list for the
1354 // iteration.
1355 sdr::PageUserVector aListCopy (maPageUsers.begin(), maPageUsers.end());
1356 for(sdr::PageUser* pPageUser : aListCopy)
1358 DBG_ASSERT(pPageUser, "SdrPage::~SdrPage: corrupt PageUser list (!)");
1359 pPageUser->PageInDestruction(*this);
1362 // Clear the vector. This means that user do not need to call RemovePageUser()
1363 // when they get called from PageInDestruction().
1364 maPageUsers.clear();
1366 mpLayerAdmin.reset();
1368 TRG_ClearMasterPage();
1370 mpViewContact.reset();
1371 mpSdrPageProperties.reset();
1374 void SdrPage::lateInit(const SdrPage& rSrcPage)
1376 assert(!mpViewContact);
1377 assert(!mxUnoPage.is());
1379 // copy all the local parameters to make this instance
1380 // a valid copy of source page before copying and inserting
1381 // the contained objects
1382 mbMaster = rSrcPage.mbMaster;
1383 mbPageBorderOnlyLeftRight = rSrcPage.mbPageBorderOnlyLeftRight;
1384 mnWidth = rSrcPage.mnWidth;
1385 mnHeight = rSrcPage.mnHeight;
1386 mnBorderLeft = rSrcPage.mnBorderLeft;
1387 mnBorderUpper = rSrcPage.mnBorderUpper;
1388 mnBorderRight = rSrcPage.mnBorderRight;
1389 mnBorderLower = rSrcPage.mnBorderLower;
1390 mbBackgroundFullSize = rSrcPage.mbBackgroundFullSize;
1391 nPageNum = rSrcPage.nPageNum;
1393 if(rSrcPage.TRG_HasMasterPage())
1395 TRG_SetMasterPage(rSrcPage.TRG_GetMasterPage());
1396 TRG_SetMasterPageVisibleLayers(rSrcPage.TRG_GetMasterPageVisibleLayers());
1398 else
1400 TRG_ClearMasterPage();
1403 mbObjectsNotPersistent = rSrcPage.mbObjectsNotPersistent;
1406 mpSdrPageProperties.reset(new SdrPageProperties(*this));
1408 if(!IsMasterPage())
1410 mpSdrPageProperties->PutItemSet(rSrcPage.getSdrPageProperties().GetItemSet());
1413 mpSdrPageProperties->SetStyleSheet(rSrcPage.getSdrPageProperties().GetStyleSheet());
1416 // Now copy the contained objects
1417 if(0 != rSrcPage.GetObjCount())
1419 CopyObjects(rSrcPage);
1423 rtl::Reference<SdrPage> SdrPage::CloneSdrPage(SdrModel& rTargetModel) const
1425 rtl::Reference<SdrPage> pClonedPage(new SdrPage(rTargetModel));
1426 pClonedPage->lateInit(*this);
1427 return pClonedPage;
1430 void SdrPage::SetSize(const Size& aSiz)
1432 bool bChanged(false);
1434 if(aSiz.Width() != mnWidth)
1436 mnWidth = aSiz.Width();
1437 bChanged = true;
1440 if(aSiz.Height() != mnHeight)
1442 mnHeight = aSiz.Height();
1443 bChanged = true;
1446 if(bChanged)
1448 SetChanged();
1452 Size SdrPage::GetSize() const
1454 return Size(mnWidth,mnHeight);
1457 tools::Long SdrPage::GetWidth() const
1459 return mnWidth;
1462 void SdrPage::SetOrientation(Orientation eOri)
1464 // square: handle like portrait format
1465 Size aSiz(GetSize());
1466 if (aSiz.Width()!=aSiz.Height()) {
1467 if ((eOri==Orientation::Portrait) == (aSiz.Width()>aSiz.Height())) {
1468 // coverity[swapped_arguments : FALSE] - this is in the correct order
1469 SetSize(Size(aSiz.Height(),aSiz.Width()));
1474 Orientation SdrPage::GetOrientation() const
1476 // square: handle like portrait format
1477 Orientation eRet=Orientation::Portrait;
1478 Size aSiz(GetSize());
1479 if (aSiz.Width()>aSiz.Height()) eRet=Orientation::Landscape;
1480 return eRet;
1483 tools::Long SdrPage::GetHeight() const
1485 return mnHeight;
1488 void SdrPage::SetBorder(sal_Int32 nLft, sal_Int32 nUpp, sal_Int32 nRgt, sal_Int32 nLwr)
1490 bool bChanged(false);
1492 if(mnBorderLeft != nLft)
1494 mnBorderLeft = nLft;
1495 bChanged = true;
1498 if(mnBorderUpper != nUpp)
1500 mnBorderUpper = nUpp;
1501 bChanged = true;
1504 if(mnBorderRight != nRgt)
1506 mnBorderRight = nRgt;
1507 bChanged = true;
1510 if(mnBorderLower != nLwr)
1512 mnBorderLower = nLwr;
1513 bChanged = true;
1516 if(bChanged)
1518 SetChanged();
1522 void SdrPage::SetLeftBorder(sal_Int32 nBorder)
1524 if(mnBorderLeft != nBorder)
1526 mnBorderLeft = nBorder;
1527 SetChanged();
1531 void SdrPage::SetUpperBorder(sal_Int32 nBorder)
1533 if(mnBorderUpper != nBorder)
1535 mnBorderUpper = nBorder;
1536 SetChanged();
1540 void SdrPage::SetRightBorder(sal_Int32 nBorder)
1542 if(mnBorderRight != nBorder)
1544 mnBorderRight=nBorder;
1545 SetChanged();
1549 void SdrPage::SetLowerBorder(sal_Int32 nBorder)
1551 if(mnBorderLower != nBorder)
1553 mnBorderLower=nBorder;
1554 SetChanged();
1558 sal_Int32 SdrPage::GetLeftBorder() const
1560 return mnBorderLeft;
1563 sal_Int32 SdrPage::GetUpperBorder() const
1565 return mnBorderUpper;
1568 sal_Int32 SdrPage::GetRightBorder() const
1570 return mnBorderRight;
1573 sal_Int32 SdrPage::GetLowerBorder() const
1575 return mnBorderLower;
1578 void SdrPage::SetBackgroundFullSize(bool const bIn)
1580 if (bIn != mbBackgroundFullSize)
1582 mbBackgroundFullSize = bIn;
1583 SetChanged();
1587 bool SdrPage::IsBackgroundFullSize() const
1589 return mbBackgroundFullSize;
1592 // #i68775# React on PageNum changes (from Model in most cases)
1593 void SdrPage::SetPageNum(sal_uInt16 nNew)
1595 if(nNew != nPageNum)
1597 // change
1598 nPageNum = nNew;
1600 // notify visualisations, also notifies e.g. buffered MasterPages
1601 ActionChanged();
1605 sal_uInt16 SdrPage::GetPageNum() const
1607 if (!mbInserted)
1608 return 0;
1610 if (mbMaster) {
1611 if (getSdrModelFromSdrPage().IsMPgNumsDirty())
1612 getSdrModelFromSdrPage().RecalcPageNums(true);
1613 } else {
1614 if (getSdrModelFromSdrPage().IsPagNumsDirty())
1615 getSdrModelFromSdrPage().RecalcPageNums(false);
1617 return nPageNum;
1620 void SdrPage::SetChanged()
1622 // For test purposes, use the new ViewContact for change
1623 // notification now.
1624 ActionChanged();
1625 getSdrModelFromSdrPage().SetChanged();
1628 SdrPage* SdrPage::getSdrPageFromSdrObjList() const
1630 return const_cast< SdrPage* >(this);
1633 // MasterPage interface
1635 void SdrPage::TRG_SetMasterPage(SdrPage& rNew)
1637 if(mpMasterPageDescriptor && &(mpMasterPageDescriptor->GetUsedPage()) == &rNew)
1638 return;
1640 if(mpMasterPageDescriptor)
1641 TRG_ClearMasterPage();
1643 mpMasterPageDescriptor.reset(new sdr::MasterPageDescriptor(*this, rNew));
1644 GetViewContact().ActionChanged();
1647 void SdrPage::TRG_ClearMasterPage()
1649 if(mpMasterPageDescriptor)
1651 SetChanged();
1653 // the flushViewObjectContacts() will do needed invalidates by deleting the involved VOCs
1654 mpMasterPageDescriptor->GetUsedPage().GetViewContact().flushViewObjectContacts();
1656 mpMasterPageDescriptor.reset();
1660 SdrPage& SdrPage::TRG_GetMasterPage() const
1662 DBG_ASSERT(mpMasterPageDescriptor != nullptr, "TRG_GetMasterPage(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
1663 return mpMasterPageDescriptor->GetUsedPage();
1666 const SdrLayerIDSet& SdrPage::TRG_GetMasterPageVisibleLayers() const
1668 DBG_ASSERT(mpMasterPageDescriptor != nullptr, "TRG_GetMasterPageVisibleLayers(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
1669 return mpMasterPageDescriptor->GetVisibleLayers();
1672 void SdrPage::TRG_SetMasterPageVisibleLayers(const SdrLayerIDSet& rNew)
1674 DBG_ASSERT(mpMasterPageDescriptor != nullptr, "TRG_SetMasterPageVisibleLayers(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
1675 mpMasterPageDescriptor->SetVisibleLayers(rNew);
1678 sdr::contact::ViewContact& SdrPage::TRG_GetMasterPageDescriptorViewContact() const
1680 DBG_ASSERT(mpMasterPageDescriptor != nullptr, "TRG_GetMasterPageDescriptorViewContact(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
1681 return mpMasterPageDescriptor->GetViewContact();
1684 // used from SdrModel::RemoveMasterPage
1685 void SdrPage::TRG_ImpMasterPageRemoved(const SdrPage& rRemovedPage)
1687 if(TRG_HasMasterPage())
1689 if(&TRG_GetMasterPage() == &rRemovedPage)
1691 TRG_ClearMasterPage();
1696 void SdrPage::MakePageObjectsNamesUnique()
1698 std::unordered_set<OUString> aNameSet;
1699 for (size_t no(0); no < GetObjCount(); ++no)
1701 SdrObject* pObj(GetObj(no));
1702 if(nullptr != pObj)
1704 if (!pObj->GetName().isEmpty())
1706 pObj->MakeNameUnique(aNameSet);
1707 SdrObjList* pSdrObjList = pObj->GetSubList(); // group
1708 if (pSdrObjList)
1710 SdrObject* pListObj;
1711 SdrObjListIter aIter(pSdrObjList, SdrIterMode::DeepWithGroups);
1712 while (aIter.IsMore())
1714 pListObj = aIter.Next();
1715 pListObj->MakeNameUnique(aNameSet);
1723 const SdrPageGridFrameList* SdrPage::GetGridFrameList(const SdrPageView* /*pPV*/, const tools::Rectangle* /*pRect*/) const
1725 return nullptr;
1728 const SdrLayerAdmin& SdrPage::GetLayerAdmin() const
1730 return *mpLayerAdmin;
1733 SdrLayerAdmin& SdrPage::GetLayerAdmin()
1735 return *mpLayerAdmin;
1738 OUString SdrPage::GetLayoutName() const
1740 return OUString();
1743 void SdrPage::SetInserted( bool bIns )
1745 if( mbInserted == bIns )
1746 return;
1748 mbInserted = bIns;
1750 // #i120437# go over whole hierarchy, not only over object level null (seen from grouping)
1751 SdrObjListIter aIter(this, SdrIterMode::DeepNoGroups);
1753 while ( aIter.IsMore() )
1755 SdrObject* pObj = aIter.Next();
1756 if ( auto pOleObj = dynamic_cast<SdrOle2Obj* >(pObj) )
1758 if( mbInserted )
1759 pOleObj->Connect();
1760 else
1761 pOleObj->Disconnect();
1766 void SdrPage::SetUnoPage(uno::Reference<drawing::XDrawPage> const& xNewPage)
1768 mxUnoPage = xNewPage;
1771 uno::Reference< uno::XInterface > const & SdrPage::getUnoPage()
1773 if( !mxUnoPage.is() )
1775 // create one
1776 mxUnoPage = createUnoPage();
1779 return mxUnoPage;
1782 uno::Reference< uno::XInterface > SdrPage::createUnoPage()
1784 css::uno::Reference< css::uno::XInterface > xInt =
1785 static_cast<cppu::OWeakObject*>( new SvxFmDrawPage( this ) );
1786 return xInt;
1789 SfxStyleSheet* SdrPage::GetTextStyleSheetForObject( SdrObject* pObj ) const
1791 return pObj->GetStyleSheet();
1794 /** returns an averaged background color of this page */
1795 // #i75566# GetBackgroundColor -> GetPageBackgroundColor and bScreenDisplay hint value
1796 Color SdrPage::GetPageBackgroundColor( SdrPageView const * pView, bool bScreenDisplay ) const
1798 Color aColor;
1800 if(bScreenDisplay && (!pView || pView->GetApplicationDocumentColor() == COL_AUTO))
1802 svtools::ColorConfig aColorConfig;
1803 aColor = aColorConfig.GetColorValue( svtools::DOCCOLOR ).nColor;
1805 else
1807 aColor = pView->GetApplicationDocumentColor();
1810 const SfxItemSet* pBackgroundFill = &getSdrPageProperties().GetItemSet();
1812 if(!IsMasterPage() && TRG_HasMasterPage())
1814 if(drawing::FillStyle_NONE == pBackgroundFill->Get(XATTR_FILLSTYLE).GetValue())
1816 pBackgroundFill = &TRG_GetMasterPage().getSdrPageProperties().GetItemSet();
1820 GetDraftFillColor(*pBackgroundFill, aColor);
1822 return aColor;
1825 /** *deprecated, use GetBackgroundColor with SdrPageView */
1826 Color SdrPage::GetPageBackgroundColor() const
1827 // #i75566# GetBackgroundColor -> GetPageBackgroundColor
1829 return GetPageBackgroundColor( nullptr );
1832 /** this method returns true if the object from the ViewObjectContact should
1833 be visible on this page while rendering.
1834 bEdit selects if visibility test is for an editing view or a final render,
1835 like printing.
1837 bool SdrPage::checkVisibility(
1838 const sdr::contact::ViewObjectContact& /*rOriginal*/,
1839 const sdr::contact::DisplayInfo& /*rDisplayInfo*/,
1840 bool /*bEdit*/)
1842 // this will be handled in the application if needed
1843 return true;
1846 void SdrPage::dumpAsXml(xmlTextWriterPtr pWriter) const
1848 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SdrPage"));
1849 SdrObjList::dumpAsXml(pWriter);
1851 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("width"));
1852 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("value"), "%s",
1853 BAD_CAST(OString::number(mnWidth).getStr()));
1854 (void)xmlTextWriterEndElement(pWriter);
1855 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("height"));
1856 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("value"), "%s",
1857 BAD_CAST(OString::number(mnHeight).getStr()));
1858 (void)xmlTextWriterEndElement(pWriter);
1860 if (mpSdrPageProperties)
1862 mpSdrPageProperties->dumpAsXml(pWriter);
1865 (void)xmlTextWriterEndElement(pWriter);
1868 // DrawContact support: Methods for handling Page changes
1869 void SdrPage::ActionChanged()
1871 // Do necessary ViewContact actions
1872 GetViewContact().ActionChanged();
1874 // #i48535# also handle MasterPage change
1875 if(TRG_HasMasterPage())
1877 TRG_GetMasterPageDescriptorViewContact().ActionChanged();
1881 SdrPageProperties& SdrPage::getSdrPageProperties()
1883 return *mpSdrPageProperties;
1886 const SdrPageProperties& SdrPage::getSdrPageProperties() const
1888 return *mpSdrPageProperties;
1891 const SdrPageProperties* SdrPage::getCorrectSdrPageProperties() const
1893 if(mpMasterPageDescriptor)
1895 return mpMasterPageDescriptor->getCorrectSdrPageProperties();
1897 else
1899 return &getSdrPageProperties();
1904 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */