tdf#161412 - UI: fix warning in PDF password dialog didn't disappear
[LibreOffice.git] / svx / source / svdraw / svdpage.cxx
blob3dc8464b6f211cb2333dc4a42a9f5d38893a7752
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/unopage.hxx>
28 #include <o3tl/safeint.hxx>
29 #include <string.h>
31 #include <tools/debug.hxx>
32 #include <tools/json_writer.hxx>
33 #include <comphelper/diagnose_ex.hxx>
35 #include <sfx2/viewsh.hxx>
36 #include <svtools/colorcfg.hxx>
37 #include <svx/svdetc.hxx>
38 #include <svx/svdobj.hxx>
39 #include <svx/svdogrp.hxx>
40 #include <svx/svdoedge.hxx>
41 #include <svx/svdoole2.hxx>
42 #include <svx/svditer.hxx>
43 #include <svx/svdmodel.hxx>
44 #include <svx/svdlayer.hxx>
45 #include <svx/svdpagv.hxx>
46 #include <svx/svdundo.hxx>
47 #include <svx/xfillit0.hxx>
49 #include <sdr/contact/viewcontactofsdrpage.hxx>
50 #include <svx/sdr/contact/viewobjectcontact.hxx>
51 #include <svx/sdr/contact/displayinfo.hxx>
52 #include <svx/annotation/Annotation.hxx>
53 #include <svx/annotation/ObjectAnnotationData.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>
60 #include <comphelper/lok.hxx>
62 #include <com/sun/star/lang/IllegalArgumentException.hpp>
64 using namespace ::com::sun::star;
66 //////////////////////////////////////////////////////////////////////////////
68 SdrObjList::SdrObjList()
69 : mbObjOrdNumsDirty(false),
70 mbRectsDirty(false),
71 mbIsNavigationOrderDirty(false)
75 void SdrObjList::impClearSdrObjList()
77 SdrModel* pSdrModelFromRemovedSdrObject(nullptr);
79 while(!maList.empty())
81 // remove last object from list
82 rtl::Reference<SdrObject> pObj(maList.back());
83 RemoveObjectFromContainer(maList.size()-1);
85 // flushViewObjectContacts() is done since SdrObject::Free is not guaranteed
86 // to delete the object and thus refresh visualisations
87 pObj->GetViewContact().flushViewObjectContacts();
89 if(nullptr == pSdrModelFromRemovedSdrObject)
91 pSdrModelFromRemovedSdrObject = &pObj->getSdrModelFromSdrObject();
94 // sent remove hint (after removal, see RemoveObject())
95 // TTTT SdrPage not needed, can be accessed using SdrObject
96 SdrHint aHint(SdrHintKind::ObjectRemoved, *pObj, getSdrPageFromSdrObjList());
97 pObj->getSdrModelFromSdrObject().Broadcast(aHint);
99 pObj->setParentOfSdrObject(nullptr);
102 if(nullptr != pSdrModelFromRemovedSdrObject)
104 pSdrModelFromRemovedSdrObject->SetChanged();
108 void SdrObjList::ClearSdrObjList()
110 // clear SdrObjects with broadcasting
111 impClearSdrObjList();
114 SdrObjList::~SdrObjList()
116 // Clear SdrObjects without broadcasting.
117 for (auto& rxObj : maList)
118 rxObj->setParentOfSdrObject(nullptr);
121 SdrPage* SdrObjList::getSdrPageFromSdrObjList() const
123 // default is no page and returns zero
124 return nullptr;
127 SdrObject* SdrObjList::getSdrObjectFromSdrObjList() const
129 // default is no SdrObject (SdrObjGroup)
130 return nullptr;
133 OString SdrObjList::GetObjectRectangles(const SdrObjList& rSrcList)
135 tools::JsonWriter jsWriter;
138 auto array = jsWriter.startAnonArray();
140 for (const rtl::Reference<SdrObject>& item: rSrcList)
142 if (item->IsPrintable() && item->IsVisible())
144 tools::Rectangle rectangle = item->GetCurrentBoundRect();
145 OStringBuffer value(OString::number(item->GetOrdNum()));
146 value = rectangle.toString() + ", "_ostr + value;
148 auto subArray = jsWriter.startAnonArray();
149 jsWriter.putRaw(value.makeStringAndClear());
154 return jsWriter.finishAndGetAsOString();
157 void SdrObjList::CopyObjects(const SdrObjList& rSrcList)
159 CloneList aCloneList;
161 // clear SdrObjects with broadcasting
162 ClearSdrObjList();
164 mbObjOrdNumsDirty = false;
165 mbRectsDirty = false;
166 #ifdef DBG_UTIL
167 size_t nCloneErrCnt(0);
168 #endif
170 if(nullptr == getSdrObjectFromSdrObjList() && nullptr == getSdrPageFromSdrObjList())
172 OSL_ENSURE(false, "SdrObjList which is not part of SdrPage or SdrObject (!)");
173 return;
176 SdrModel& rTargetSdrModel(nullptr == getSdrObjectFromSdrObjList()
177 ? getSdrPageFromSdrObjList()->getSdrModelFromSdrPage()
178 : getSdrObjectFromSdrObjList()->getSdrModelFromSdrObject());
180 for (const rtl::Reference<SdrObject>& pSourceObject : rSrcList)
182 rtl::Reference<SdrObject> pTargetObject(pSourceObject->CloneSdrObject(rTargetSdrModel));
184 if (pTargetObject)
186 NbcInsertObject(pTargetObject.get(), SAL_MAX_SIZE);
187 aCloneList.AddPair(pSourceObject.get(), pTargetObject.get());
188 if (pSourceObject->isAnnotationObject())
190 pTargetObject->setAsAnnotationObject();
191 pTargetObject->SetPrintable(false);
192 rtl::Reference<sdr::annotation::Annotation> xNewAnnotation;
193 SdrPage* pPage = pTargetObject->getSdrPageFromSdrObject();
194 xNewAnnotation = pSourceObject->getAnnotationData()->mxAnnotation->clone(pPage);
195 pTargetObject->getAnnotationData()->mxAnnotation = xNewAnnotation;
196 pPage->addAnnotationNoNotify(xNewAnnotation, -1);
199 #ifdef DBG_UTIL
200 else
202 nCloneErrCnt++;
204 #endif
207 // Wires up the connections
208 aCloneList.CopyConnections();
209 #ifdef DBG_UTIL
210 if (nCloneErrCnt != 0)
212 OStringBuffer aStr("SdrObjList::operator=(): Error when cloning ");
214 if(nCloneErrCnt == 1)
216 aStr.append("a drawing object.");
218 else
220 aStr.append(OString::number(static_cast<sal_Int32>(nCloneErrCnt))
221 + " drawing objects.");
224 OSL_FAIL(aStr.getStr());
226 #endif
229 void SdrObjList::RecalcObjOrdNums()
231 size_t no=0;
232 for (const rtl::Reference<SdrObject>& pObj : maList)
233 pObj->SetOrdNum(no++);
234 mbObjOrdNumsDirty=false;
237 void SdrObjList::RecalcRects()
239 maSdrObjListOutRect=tools::Rectangle();
240 maSdrObjListSnapRect=maSdrObjListOutRect;
241 for (auto it = begin(), itEnd = end(); it != itEnd; ++it) {
242 SdrObject* pObj = it->get();
243 if (it == begin()) {
244 maSdrObjListOutRect=pObj->GetCurrentBoundRect();
245 maSdrObjListSnapRect=pObj->GetSnapRect();
246 } else {
247 maSdrObjListOutRect.Union(pObj->GetCurrentBoundRect());
248 maSdrObjListSnapRect.Union(pObj->GetSnapRect());
253 void SdrObjList::SetSdrObjListRectsDirty()
255 mbRectsDirty=true;
256 SdrObject* pParentSdrObject(getSdrObjectFromSdrObjList());
258 if(nullptr != pParentSdrObject)
260 pParentSdrObject->SetBoundAndSnapRectsDirty();
264 void SdrObjList::impChildInserted(SdrObject const & rChild)
266 sdr::contact::ViewContact* pParent = rChild.GetViewContact().GetParentContact();
268 if(pParent)
270 pParent->ActionChildInserted(rChild.GetViewContact());
274 void SdrObjList::NbcInsertObject(SdrObject* pObj, size_t nPos)
276 DBG_ASSERT(pObj!=nullptr,"SdrObjList::NbcInsertObject(NULL)");
277 if (pObj==nullptr)
278 return;
280 DBG_ASSERT(!pObj->IsInserted(),"The object already has the status Inserted.");
281 const size_t nCount = GetObjCount();
282 if (nPos>nCount) nPos=nCount;
283 InsertObjectIntoContainer(*pObj,nPos);
285 if (nPos<nCount) mbObjOrdNumsDirty=true;
286 pObj->SetOrdNum(nPos);
287 pObj->setParentOfSdrObject(this);
289 // Inform the parent about change to allow invalidations at
290 // evtl. existing parent visualisations
291 impChildInserted(*pObj);
293 if (!mbRectsDirty) {
294 mbRectsDirty = true;
296 pObj->InsertedStateChange(); // calls the UserCall (among others)
299 void SdrObjList::InsertObjectThenMakeNameUnique(SdrObject* pObj)
301 std::unordered_set<rtl::OUString> aNameSet;
302 InsertObjectThenMakeNameUnique(pObj, aNameSet);
305 void SdrObjList::InsertObjectThenMakeNameUnique(SdrObject* pObj, std::unordered_set<OUString>& rNameSet, size_t nPos)
307 InsertObject(pObj, nPos);
308 if (pObj->GetName().isEmpty())
309 return;
311 pObj->MakeNameUnique(rNameSet);
312 SdrObjList* pSdrObjList = pObj->GetSubList(); // group
313 if (pSdrObjList)
315 SdrObject* pListObj;
316 SdrObjListIter aIter(pSdrObjList, SdrIterMode::DeepWithGroups);
317 while (aIter.IsMore())
319 pListObj = aIter.Next();
320 pListObj->MakeNameUnique(rNameSet);
325 void SdrObjList::InsertObject(SdrObject* pObj, size_t nPos)
327 DBG_ASSERT(pObj!=nullptr,"SdrObjList::InsertObject(NULL)");
329 if(!pObj)
330 return;
332 // if anchor is used, reset it before grouping
333 if(getSdrObjectFromSdrObjList())
335 const Point& rAnchorPos = pObj->GetAnchorPos();
336 if(rAnchorPos.X() || rAnchorPos.Y())
337 pObj->NbcSetAnchorPos(Point());
340 // do insert to new group
341 NbcInsertObject(pObj, nPos);
343 // In case the object is inserted into a group and doesn't overlap with
344 // the group's other members, it needs an own repaint.
345 SdrObject* pParentSdrObject(getSdrObjectFromSdrObjList());
347 if(pParentSdrObject)
349 // only repaint here
350 pParentSdrObject->ActionChanged();
353 // TODO: We need a different broadcast here!
354 // Repaint from object number ... (heads-up: GroupObj)
355 if(pObj->getSdrPageFromSdrObject() && !pObj->getSdrModelFromSdrObject().isLocked())
357 SdrHint aHint(SdrHintKind::ObjectInserted, *pObj);
358 pObj->getSdrModelFromSdrObject().Broadcast(aHint);
361 pObj->getSdrModelFromSdrObject().SetChanged();
364 rtl::Reference<SdrObject> SdrObjList::NbcRemoveObject(size_t nObjNum)
366 if (nObjNum >= maList.size())
368 OSL_ASSERT(nObjNum<maList.size());
369 return nullptr;
372 const size_t nCount = GetObjCount();
373 rtl::Reference<SdrObject> pObj=maList[nObjNum];
374 RemoveObjectFromContainer(nObjNum);
376 DBG_ASSERT(pObj!=nullptr,"Could not find object to remove.");
377 if (pObj!=nullptr)
379 // flushViewObjectContacts() clears the VOC's and those invalidate
380 pObj->GetViewContact().flushViewObjectContacts();
382 DBG_ASSERT(pObj->IsInserted(),"The object does not have the status Inserted.");
384 // tdf#121022 Do first remove from SdrObjList - InsertedStateChange
385 // relies now on IsInserted which uses getParentSdrObjListFromSdrObject
386 pObj->setParentOfSdrObject(nullptr);
388 // calls UserCall, among other
389 pObj->InsertedStateChange();
391 if (!mbObjOrdNumsDirty)
393 // optimizing for the case that the last object has to be removed
394 if (nObjNum+1!=nCount) {
395 mbObjOrdNumsDirty=true;
398 SetSdrObjListRectsDirty();
400 return pObj;
403 rtl::Reference<SdrObject> SdrObjList::RemoveObject(size_t nObjNum)
405 if (nObjNum >= maList.size())
407 OSL_ASSERT(nObjNum<maList.size());
408 return nullptr;
411 const size_t nCount = GetObjCount();
412 rtl::Reference<SdrObject> pObj=maList[nObjNum];
413 RemoveObjectFromContainer(nObjNum);
415 DBG_ASSERT(pObj!=nullptr,"Object to remove not found.");
416 if(pObj)
418 // flushViewObjectContacts() clears the VOC's and those invalidate
419 pObj->GetViewContact().flushViewObjectContacts();
420 DBG_ASSERT(pObj->IsInserted(),"The object does not have the status Inserted.");
422 // TODO: We need a different broadcast here.
423 if (pObj->getSdrPageFromSdrObject()!=nullptr)
425 SdrHint aHint(SdrHintKind::ObjectRemoved, *pObj);
426 pObj->getSdrModelFromSdrObject().Broadcast(aHint);
429 pObj->getSdrModelFromSdrObject().SetChanged();
431 // tdf#121022 Do first remove from SdrObjList - InsertedStateChange
432 // relies now on IsInserted which uses getParentSdrObjListFromSdrObject
433 pObj->setParentOfSdrObject(nullptr);
435 // calls, among other things, the UserCall
436 pObj->InsertedStateChange();
438 if (!mbObjOrdNumsDirty)
440 // optimization for the case that the last object is removed
441 if (nObjNum+1!=nCount) {
442 mbObjOrdNumsDirty=true;
446 SetSdrObjListRectsDirty();
447 SdrObject* pParentSdrObject(getSdrObjectFromSdrObjList());
449 if(pParentSdrObject && !GetObjCount())
451 // empty group created; it needs to be repainted since it's
452 // visualization changes
453 pParentSdrObject->ActionChanged();
456 return pObj;
459 rtl::Reference<SdrObject> SdrObjList::ReplaceObject(SdrObject* pNewObj, size_t nObjNum)
461 if (nObjNum >= maList.size())
463 OSL_ASSERT(nObjNum<maList.size());
464 return nullptr;
466 if (pNewObj == nullptr)
468 OSL_ASSERT(pNewObj!=nullptr);
469 return nullptr;
472 rtl::Reference<SdrObject> pObj=maList[nObjNum];
473 DBG_ASSERT(pObj!=nullptr,"SdrObjList::ReplaceObject: Could not find object to remove.");
474 if (pObj!=nullptr) {
475 DBG_ASSERT(pObj->IsInserted(),"SdrObjList::ReplaceObject: the object does not have status Inserted.");
477 // TODO: We need a different broadcast here.
478 if (pObj->getSdrPageFromSdrObject()!=nullptr)
480 SdrHint aHint(SdrHintKind::ObjectRemoved, *pObj);
481 pObj->getSdrModelFromSdrObject().Broadcast(aHint);
484 // Change parent and replace in SdrObjList
485 pObj->setParentOfSdrObject(nullptr);
486 ReplaceObjectInContainer(*pNewObj,nObjNum);
488 // tdf#121022 InsertedStateChange uses the parent
489 // to detect if pObj is inserted or not, so have to call
490 // it *after* changing these settings, else an obviously wrong
491 // 'SdrUserCallType::Inserted' would be sent
492 pObj->InsertedStateChange();
494 // flushViewObjectContacts() clears the VOC's and those
495 // trigger the evtl. needed invalidate(s)
496 pObj->GetViewContact().flushViewObjectContacts();
498 // Setup data at new SdrObject - it already *is* inserted to
499 // the SdrObjList due to 'ReplaceObjectInContainer' above
500 pNewObj->SetOrdNum(nObjNum);
501 pNewObj->setParentOfSdrObject(this);
503 // Inform the parent about change to allow invalidations at
504 // evtl. existing parent visualisations, but also react on
505 // newly inserted SdrObjects (as e.g. GraphCtrlUserCall does)
506 impChildInserted(*pNewObj);
508 pNewObj->InsertedStateChange();
510 // TODO: We need a different broadcast here.
511 if (pNewObj->getSdrPageFromSdrObject()!=nullptr) {
512 SdrHint aHint(SdrHintKind::ObjectInserted, *pNewObj);
513 pNewObj->getSdrModelFromSdrObject().Broadcast(aHint);
516 pNewObj->getSdrModelFromSdrObject().SetChanged();
518 SetSdrObjListRectsDirty();
520 return pObj;
523 SdrObject* SdrObjList::SetObjectOrdNum(size_t nOldObjNum, size_t nNewObjNum)
525 if (nOldObjNum >= maList.size() || nNewObjNum >= maList.size())
527 OSL_ASSERT(nOldObjNum<maList.size());
528 OSL_ASSERT(nNewObjNum<maList.size());
529 return nullptr;
532 rtl::Reference<SdrObject> pObj=maList[nOldObjNum];
533 if (nOldObjNum==nNewObjNum) return pObj.get();
534 DBG_ASSERT(pObj!=nullptr,"SdrObjList::SetObjectOrdNum: Object not found.");
535 if (pObj!=nullptr) {
536 DBG_ASSERT(pObj->IsInserted(),"SdrObjList::SetObjectOrdNum: the object does not have status Inserted.");
537 RemoveObjectFromContainer(nOldObjNum);
538 InsertObjectIntoContainer(*pObj,nNewObjNum);
540 // No need to delete visualisation data since same object
541 // gets inserted again. Also a single ActionChanged is enough
542 pObj->ActionChanged();
544 pObj->SetOrdNum(nNewObjNum);
545 mbObjOrdNumsDirty=true;
547 // TODO: We need a different broadcast here.
548 if (pObj->getSdrPageFromSdrObject()!=nullptr)
549 pObj->getSdrModelFromSdrObject().Broadcast(SdrHint(SdrHintKind::ObjectChange, *pObj));
550 pObj->getSdrModelFromSdrObject().SetChanged();
552 return pObj.get();
555 void SdrObjList::SetExistingObjectOrdNum(SdrObject* pObj, size_t nNewObjNum)
557 assert(std::find(maList.begin(), maList.end(), pObj) != maList.end() && "This method requires that the child object already be inserted");
558 assert(pObj->IsInserted() && "SdrObjList::SetObjectOrdNum: the object does not have status Inserted.");
560 // I am deliberately bypassing getOrdNum() because I don't want to unnecessarily
561 // trigger RecalcObjOrdNums()
562 const sal_uInt32 nOldOrdNum = pObj->m_nOrdNum;
563 if (!mbObjOrdNumsDirty && nOldOrdNum == nNewObjNum)
564 return;
566 // Update the navigation positions.
567 if (HasObjectNavigationOrder())
569 unotools::WeakReference<SdrObject> aReference (pObj);
570 auto iObject = ::std::find(
571 mxNavigationOrder->begin(),
572 mxNavigationOrder->end(),
573 aReference);
574 mxNavigationOrder->erase(iObject);
575 mbIsNavigationOrderDirty = true;
576 // The new object does not have a user defined position so append it
577 // to the list.
578 pObj->SetNavigationPosition(mxNavigationOrder->size());
579 mxNavigationOrder->push_back(pObj);
581 if (nOldOrdNum < maList.size() && maList[nOldOrdNum] == pObj)
582 maList.erase(maList.begin()+nOldOrdNum);
583 else
585 auto it = std::find(maList.begin(), maList.end(), pObj);
586 maList.erase(it);
588 // Insert object into object list. Because the insert() method requires
589 // a valid iterator as insertion position, we have to use push_back() to
590 // insert at the end of the list.
591 if (nNewObjNum >= maList.size())
592 maList.push_back(pObj);
593 else
594 maList.insert(maList.begin()+nNewObjNum, pObj);
596 mbObjOrdNumsDirty=true;
598 // No need to delete visualisation data since same object
599 // gets inserted again. Also a single ActionChanged is enough
600 pObj->ActionChanged();
602 pObj->SetOrdNum(nNewObjNum);
603 mbObjOrdNumsDirty=true;
605 // TODO: We need a different broadcast here.
606 if (pObj->getSdrPageFromSdrObject()!=nullptr)
607 pObj->getSdrModelFromSdrObject().Broadcast(SdrHint(SdrHintKind::ObjectChange, *pObj));
608 pObj->getSdrModelFromSdrObject().SetChanged();
611 void SdrObjList::sort( std::vector<sal_Int32>& sortOrder)
613 // no negative indexes and indexes larger than maList size are allowed
614 auto it = std::find_if( sortOrder.begin(), sortOrder.end(), [this](const sal_Int32& rIt)
615 { return ( rIt < 0 || o3tl::make_unsigned(rIt) >= maList.size() ); } );
616 if ( it != sortOrder.end())
617 throw css::lang::IllegalArgumentException(u"negative index of shape"_ustr, nullptr, 1);
619 // no duplicates
620 std::vector<bool> aNoDuplicates(sortOrder.size(), false);
621 for (const sal_Int32 nSortOrder : sortOrder )
623 size_t idx = static_cast<size_t>( nSortOrder );
625 if ( aNoDuplicates[idx] )
626 throw css::lang::IllegalArgumentException(u"duplicate index of shape"_ustr, nullptr, 2);
628 aNoDuplicates[idx] = true;
631 // example sortOrder [2 0 1]
632 // example maList [T T S T T] ( T T = shape with textbox, S = just a shape )
633 // (shapes at positions 0 and 2 have a textbox)
635 std::deque<rtl::Reference<SdrObject>> aNewList(maList.size());
636 std::set<sal_Int32> aShapesWithTextbox;
637 std::vector<sal_Int32> aIncrements;
638 std::vector<sal_Int32> aDuplicates;
640 if ( maList.size() > 1)
642 for (size_t i = 1; i< maList.size(); ++i)
644 // if this shape is a textbox, then look at its left neighbour
645 // (shape this textbox is in)
646 // and insert the number of textboxes to the left of it
647 if (maList[i]->IsTextBox())
648 aShapesWithTextbox.insert( i - 1 - aShapesWithTextbox.size() );
650 // example aShapesWithTextbox [0 2]
653 if (aShapesWithTextbox.size() != maList.size() - sortOrder.size())
655 throw lang::IllegalArgumentException(u"mismatch of no. of shapes"_ustr, nullptr, 0);
658 for (size_t i = 0; i< sortOrder.size(); ++i)
661 if (aShapesWithTextbox.count(sortOrder[i]) > 0)
662 aDuplicates.push_back(sortOrder[i]);
664 aDuplicates.push_back(sortOrder[i]);
666 // example aDuplicates [2 2 0 0 1]
668 assert(aDuplicates.size() == maList.size());
670 aIncrements.push_back(0);
671 for (size_t i = 1; i< sortOrder.size(); ++i)
673 if (aShapesWithTextbox.count(i - 1))
674 aIncrements.push_back(aIncrements[i-1] + 1 );
675 else
676 aIncrements.push_back(aIncrements[i-1]);
678 // example aIncrements [0 1 1]
680 assert(aIncrements.size() == sortOrder.size());
682 std::vector<sal_Int32> aNewSortOrder(maList.size());
683 sal_Int32 nPrev = -1;
684 for (size_t i = 0; i< aDuplicates.size(); ++i)
686 if (nPrev != aDuplicates[i])
687 aNewSortOrder[i] = aDuplicates[i] + aIncrements[aDuplicates[i]];
688 else if (i > 0)
689 aNewSortOrder[i] = aNewSortOrder[i-1] + 1;
691 nPrev = aDuplicates[i];
693 // example aNewSortOrder [3 4 0 1 2]
695 assert(aNewSortOrder.size() == maList.size());
697 #ifndef NDEBUG
699 std::vector<sal_Int32> tmp(aNewSortOrder);
700 std::sort(tmp.begin(), tmp.end());
701 for (size_t i = 0; i < tmp.size(); ++i)
703 assert(size_t(tmp[i]) == i);
706 #endif
708 SdrModel & rModel(getSdrPageFromSdrObjList()->getSdrModelFromSdrPage());
709 bool const isUndo(rModel.IsUndoEnabled());
710 if (isUndo)
712 rModel.AddUndo(SdrUndoFactory::CreateUndoSort(*getSdrPageFromSdrObjList(), sortOrder));
715 for (size_t i = 0; i < aNewSortOrder.size(); ++i)
717 aNewList[i] = maList[ aNewSortOrder[i] ];
718 aNewList[i]->SetOrdNum(i);
721 std::swap(aNewList, maList);
724 const tools::Rectangle& SdrObjList::GetAllObjSnapRect() const
726 if (mbRectsDirty) {
727 const_cast<SdrObjList*>(this)->RecalcRects();
728 const_cast<SdrObjList*>(this)->mbRectsDirty=false;
730 return maSdrObjListSnapRect;
733 const tools::Rectangle& SdrObjList::GetAllObjBoundRect() const
735 // #i106183# for deep group hierarchies like in chart2, the invalidates
736 // through the hierarchy are not correct; use a 2nd hint for the needed
737 // recalculation. Future versions will have no bool flag at all, but
738 // just maSdrObjListOutRect in empty state to represent an invalid state, thus
739 // it's a step in the right direction.
740 if (mbRectsDirty || maSdrObjListOutRect.IsEmpty())
742 const_cast<SdrObjList*>(this)->RecalcRects();
743 const_cast<SdrObjList*>(this)->mbRectsDirty=false;
745 return maSdrObjListOutRect;
748 void SdrObjList::NbcReformatAllTextObjects()
750 size_t nCount=GetObjCount();
751 size_t nNum=0;
753 while (nNum<nCount)
755 SdrObject* pObj = GetObj(nNum);
757 pObj->NbcReformatText();
758 nCount=GetObjCount(); // ReformatText may delete an object
759 nNum++;
764 void SdrObjList::ReformatAllTextObjects()
766 NbcReformatAllTextObjects();
769 /** steps over all available objects and reformats all
770 edge objects that are connected to other objects so that
771 they may reposition themselves.
773 void SdrObjList::ReformatAllEdgeObjects()
775 ImplReformatAllEdgeObjects(*this);
778 void SdrObjList::ImplReformatAllEdgeObjects(const SdrObjList& rObjList)
780 // #i120437# go over whole hierarchy, not only over object level null (seen from grouping)
781 for(size_t nIdx(0), nCount(rObjList.GetObjCount()); nIdx < nCount; ++nIdx)
783 SdrObject* pSdrObject(rObjList.GetObjectForNavigationPosition(nIdx));
784 const SdrObjList* pChildren(pSdrObject->getChildrenOfSdrObject());
785 const bool bIsGroup(nullptr != pChildren);
786 if(!bIsGroup)
788 // Check IsVirtualObj because sometimes we get SwDrawVirtObj here
789 if (pSdrObject->GetObjIdentifier() == SdrObjKind::Edge
790 && !pSdrObject->IsVirtualObj())
792 SdrEdgeObj* pSdrEdgeObj = static_cast< SdrEdgeObj* >(pSdrObject);
793 pSdrEdgeObj->Reformat();
796 else
798 ImplReformatAllEdgeObjects(*pChildren);
803 void SdrObjList::BurnInStyleSheetAttributes()
805 for (const rtl::Reference<SdrObject>& pObj : *this)
806 pObj->BurnInStyleSheetAttributes();
809 size_t SdrObjList::GetObjCount() const
811 return maList.size();
815 SdrObject* SdrObjList::GetObj(size_t nNum) const
817 if (nNum < maList.size())
818 return maList[nNum].get();
820 return nullptr;
823 SdrObject* SdrObjList::GetObjByName(std::u16string_view sName) const
825 for (const rtl::Reference<SdrObject>& pObj : *this)
827 if (pObj->GetName() == sName)
828 return pObj.get();
830 return nullptr;
834 bool SdrObjList::IsReadOnly() const
836 bool bRet(false);
837 SdrObject* pParentSdrObject(getSdrObjectFromSdrObjList());
839 if(nullptr != pParentSdrObject)
841 SdrPage* pSdrPage(pParentSdrObject->getSdrPageFromSdrObject());
843 if(nullptr != pSdrPage)
845 bRet = pSdrPage->IsReadOnly();
849 return bRet;
852 void SdrObjList::FlattenGroups()
854 const size_t nObj = GetObjCount();
855 for( size_t i = nObj; i>0; )
856 UnGroupObj(--i);
859 void SdrObjList::UnGroupObj( size_t nObjNum )
861 // if the given object is no group, this method is a noop
862 SdrObject* pUngroupObj = GetObj( nObjNum );
863 if( pUngroupObj )
865 SdrObjList* pSrcLst = pUngroupObj->GetSubList();
866 if(pSrcLst)
867 if(auto pUngroupGroup = dynamic_cast<SdrObjGroup*>( pUngroupObj))
869 // ungroup recursively (has to be head recursion,
870 // otherwise our indices will get trashed when doing it in
871 // the loop)
872 pSrcLst->FlattenGroups();
874 // the position at which we insert the members of rUngroupGroup
875 size_t nInsertPos( pUngroupGroup->GetOrdNum() );
877 const size_t nCount = pSrcLst->GetObjCount();
878 for( size_t i=0; i<nCount; ++i )
880 rtl::Reference<SdrObject> pObj = pSrcLst->RemoveObject(0);
881 InsertObject(pObj.get(), nInsertPos);
882 ++nInsertPos;
885 RemoveObject(nInsertPos);
888 #ifdef DBG_UTIL
889 else
890 OSL_FAIL("SdrObjList::UnGroupObj: object index invalid");
891 #endif
894 bool SdrObjList::HasObjectNavigationOrder() const { return bool(mxNavigationOrder); }
896 void SdrObjList::SetObjectNavigationPosition (
897 SdrObject& rObject,
898 const sal_uInt32 nNewPosition)
900 // When the navigation order container has not yet been created then
901 // create one now. It is initialized with the z-order taken from
902 // maList.
903 if (!mxNavigationOrder)
905 mxNavigationOrder.emplace(maList.begin(), maList.end());
907 OSL_ASSERT(bool(mxNavigationOrder));
908 OSL_ASSERT( mxNavigationOrder->size() == maList.size());
910 unotools::WeakReference<SdrObject> aReference (&rObject);
912 // Look up the object whose navigation position is to be changed.
913 auto iObject = ::std::find(
914 mxNavigationOrder->begin(),
915 mxNavigationOrder->end(),
916 aReference);
917 if (iObject == mxNavigationOrder->end())
919 // The given object is not a member of the navigation order.
920 return;
923 // Move the object to its new position.
924 const sal_uInt32 nOldPosition = ::std::distance(mxNavigationOrder->begin(), iObject);
925 if (nOldPosition == nNewPosition)
926 return;
928 mxNavigationOrder->erase(iObject);
929 sal_uInt32 nInsertPosition (nNewPosition);
930 // Adapt insertion position for the just erased object.
931 if (nNewPosition >= nOldPosition)
932 nInsertPosition -= 1;
933 if (nInsertPosition >= mxNavigationOrder->size())
934 mxNavigationOrder->push_back(aReference);
935 else
936 mxNavigationOrder->insert(mxNavigationOrder->begin()+nInsertPosition, aReference);
938 mbIsNavigationOrderDirty = true;
940 // The navigation order is written out to file so mark the model as modified.
941 rObject.getSdrModelFromSdrObject().SetChanged();
945 SdrObject* SdrObjList::GetObjectForNavigationPosition (const sal_uInt32 nNavigationPosition) const
947 if (HasObjectNavigationOrder())
949 // There is a user defined navigation order. Make sure the object
950 // index is correct and look up the object in mxNavigationOrder.
951 if (nNavigationPosition >= mxNavigationOrder->size())
953 OSL_ASSERT(nNavigationPosition < mxNavigationOrder->size());
955 else
956 return (*mxNavigationOrder)[nNavigationPosition].get().get();
958 else
960 // There is no user defined navigation order. Use the z-order
961 // instead.
962 if (nNavigationPosition >= maList.size())
964 OSL_ASSERT(nNavigationPosition < maList.size());
966 else
967 return maList[nNavigationPosition].get();
969 return nullptr;
973 void SdrObjList::ClearObjectNavigationOrder()
975 mxNavigationOrder.reset();
976 mbIsNavigationOrderDirty = true;
980 bool SdrObjList::RecalcNavigationPositions()
982 if (mbIsNavigationOrderDirty)
984 if (mxNavigationOrder)
986 mbIsNavigationOrderDirty = false;
988 sal_uInt32 nIndex (0);
989 for (auto& rpObject : *mxNavigationOrder)
991 rpObject.get()->SetNavigationPosition(nIndex);
992 ++nIndex;
997 return bool(mxNavigationOrder);
1001 void SdrObjList::SetNavigationOrder (const uno::Reference<container::XIndexAccess>& rxOrder)
1003 if (rxOrder.is())
1005 const sal_Int32 nCount = rxOrder->getCount();
1006 if (static_cast<sal_uInt32>(nCount) != maList.size())
1007 return;
1009 if (!mxNavigationOrder)
1010 mxNavigationOrder = std::vector<unotools::WeakReference<SdrObject>>(nCount);
1012 for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex)
1014 uno::Reference<uno::XInterface> xShape (rxOrder->getByIndex(nIndex), uno::UNO_QUERY);
1015 SdrObject* pObject = SdrObject::getSdrObjectFromXShape(xShape);
1016 if (pObject == nullptr)
1017 break;
1018 (*mxNavigationOrder)[nIndex] = pObject;
1021 mbIsNavigationOrderDirty = true;
1023 else
1025 ClearObjectNavigationOrder();
1030 void SdrObjList::InsertObjectIntoContainer (
1031 SdrObject& rObject,
1032 const sal_uInt32 nInsertPosition)
1034 OSL_ASSERT(nInsertPosition<=maList.size());
1036 // Update the navigation positions.
1037 if (HasObjectNavigationOrder())
1039 // The new object does not have a user defined position so append it
1040 // to the list.
1041 rObject.SetNavigationPosition(mxNavigationOrder->size());
1042 mxNavigationOrder->push_back(&rObject);
1045 // Insert object into object list. Because the insert() method requires
1046 // a valid iterator as insertion position, we have to use push_back() to
1047 // insert at the end of the list.
1048 if (nInsertPosition >= maList.size())
1049 maList.push_back(&rObject);
1050 else
1051 maList.insert(maList.begin()+nInsertPosition, &rObject);
1052 mbObjOrdNumsDirty=true;
1056 void SdrObjList::ReplaceObjectInContainer (
1057 SdrObject& rNewObject,
1058 const sal_uInt32 nObjectPosition)
1060 if (nObjectPosition >= maList.size())
1062 OSL_ASSERT(nObjectPosition<maList.size());
1063 return;
1066 // Update the navigation positions.
1067 if (HasObjectNavigationOrder())
1069 // A user defined position of the object that is to be replaced is
1070 // not transferred to the new object so erase the former and append
1071 // the later object from/to the navigation order.
1072 OSL_ASSERT(nObjectPosition < maList.size());
1073 unotools::WeakReference<SdrObject> aReference (maList[nObjectPosition].get());
1074 auto iObject = ::std::find(
1075 mxNavigationOrder->begin(),
1076 mxNavigationOrder->end(),
1077 aReference);
1078 if (iObject != mxNavigationOrder->end())
1079 mxNavigationOrder->erase(iObject);
1081 mxNavigationOrder->push_back(&rNewObject);
1083 mbIsNavigationOrderDirty = true;
1086 maList[nObjectPosition] = &rNewObject;
1087 mbObjOrdNumsDirty=true;
1091 void SdrObjList::RemoveObjectFromContainer (
1092 const sal_uInt32 nObjectPosition)
1094 if (nObjectPosition >= maList.size())
1096 OSL_ASSERT(nObjectPosition<maList.size());
1097 return;
1100 // Update the navigation positions.
1101 if (HasObjectNavigationOrder())
1103 unotools::WeakReference<SdrObject> aReference (maList[nObjectPosition]);
1104 auto iObject = ::std::find(
1105 mxNavigationOrder->begin(),
1106 mxNavigationOrder->end(),
1107 aReference);
1108 if (iObject != mxNavigationOrder->end())
1109 mxNavigationOrder->erase(iObject);
1110 mbIsNavigationOrderDirty = true;
1113 maList.erase(maList.begin()+nObjectPosition);
1114 mbObjOrdNumsDirty=true;
1117 void SdrObjList::dumpAsXml(xmlTextWriterPtr pWriter) const
1119 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SdrObjList"));
1120 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
1121 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
1123 for (const rtl::Reference<SdrObject>& pObject : *this)
1124 pObject->dumpAsXml(pWriter);
1126 (void)xmlTextWriterEndElement(pWriter);
1130 void SdrPageGridFrameList::Clear()
1132 sal_uInt16 nCount=GetCount();
1133 for (sal_uInt16 i=0; i<nCount; i++) {
1134 delete GetObject(i);
1136 m_aList.clear();
1140 // PageUser section
1142 void SdrPage::AddPageUser(sdr::PageUser& rNewUser)
1144 maPageUsers.push_back(&rNewUser);
1147 void SdrPage::RemovePageUser(sdr::PageUser& rOldUser)
1149 const sdr::PageUserVector::iterator aFindResult = ::std::find(maPageUsers.begin(), maPageUsers.end(), &rOldUser);
1150 if(aFindResult != maPageUsers.end())
1152 maPageUsers.erase(aFindResult);
1157 // DrawContact section
1159 std::unique_ptr<sdr::contact::ViewContact> SdrPage::CreateObjectSpecificViewContact()
1161 return std::make_unique<sdr::contact::ViewContactOfSdrPage>(*this);
1164 const sdr::contact::ViewContact& SdrPage::GetViewContact() const
1166 if (!mpViewContact)
1167 const_cast<SdrPage*>(this)->mpViewContact =
1168 const_cast<SdrPage*>(this)->CreateObjectSpecificViewContact();
1170 return *mpViewContact;
1173 sdr::contact::ViewContact& SdrPage::GetViewContact()
1175 if (!mpViewContact)
1176 mpViewContact = CreateObjectSpecificViewContact();
1178 return *mpViewContact;
1181 void SdrPageProperties::ImpRemoveStyleSheet()
1183 if(mpStyleSheet)
1185 EndListening(*mpStyleSheet);
1186 maProperties.SetParent(nullptr);
1187 mpStyleSheet = nullptr;
1191 void SdrPageProperties::ImpAddStyleSheet(SfxStyleSheet& rNewStyleSheet)
1193 if(mpStyleSheet != &rNewStyleSheet)
1195 ImpRemoveStyleSheet();
1196 mpStyleSheet = &rNewStyleSheet;
1197 StartListening(rNewStyleSheet);
1198 maProperties.SetParent(&rNewStyleSheet.GetItemSet());
1202 static void ImpPageChange(SdrPage& rSdrPage)
1204 rSdrPage.ActionChanged();
1205 rSdrPage.getSdrModelFromSdrPage().SetChanged();
1206 SdrHint aHint(SdrHintKind::PageOrderChange, &rSdrPage);
1207 rSdrPage.getSdrModelFromSdrPage().Broadcast(aHint);
1210 SdrPageProperties::SdrPageProperties(SdrPage& rSdrPage)
1211 : mpSdrPage(&rSdrPage)
1212 , mpStyleSheet(nullptr)
1213 , maProperties(
1214 mpSdrPage->getSdrModelFromSdrPage().GetItemPool(),
1215 svl::Items<XATTR_FILL_FIRST, XATTR_FILL_LAST>)
1217 if (!rSdrPage.IsMasterPage())
1219 maProperties.Put(XFillStyleItem(drawing::FillStyle_NONE));
1223 SdrPageProperties::~SdrPageProperties()
1225 ImpRemoveStyleSheet();
1228 void SdrPageProperties::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
1230 switch(rHint.GetId())
1232 case SfxHintId::DataChanged :
1234 // notify change, broadcast
1235 ImpPageChange(*mpSdrPage);
1236 break;
1238 case SfxHintId::Dying :
1240 // Style needs to be forgotten
1241 ImpRemoveStyleSheet();
1242 break;
1244 default: break;
1248 bool SdrPageProperties::isUsedByModel() const
1250 assert(mpSdrPage);
1251 return mpSdrPage->IsInserted();
1255 void SdrPageProperties::PutItemSet(const SfxItemSet& rSet)
1257 OSL_ENSURE(!mpSdrPage->IsMasterPage(), "Item set at MasterPage Attributes (!)");
1258 maProperties.Put(rSet);
1259 ImpPageChange(*mpSdrPage);
1262 void SdrPageProperties::PutItem(const SfxPoolItem& rItem)
1264 OSL_ENSURE(!mpSdrPage->IsMasterPage(), "Item set at MasterPage Attributes (!)");
1265 maProperties.Put(rItem);
1266 ImpPageChange(*mpSdrPage);
1269 void SdrPageProperties::ClearItem(const sal_uInt16 nWhich)
1271 maProperties.ClearItem(nWhich);
1272 ImpPageChange(*mpSdrPage);
1275 void SdrPageProperties::SetStyleSheet(SfxStyleSheet* pStyleSheet)
1277 if(pStyleSheet)
1279 ImpAddStyleSheet(*pStyleSheet);
1281 else
1283 ImpRemoveStyleSheet();
1286 ImpPageChange(*mpSdrPage);
1289 void SdrPageProperties::setTheme(std::shared_ptr<model::Theme> const& pTheme)
1291 if (!mpSdrPage)
1292 return;
1294 // Only set the theme on a master page, else set it on the model
1296 if (mpSdrPage->IsMasterPage())
1298 if (mpTheme != pTheme)
1299 mpTheme = pTheme;
1301 else
1303 mpSdrPage->getSdrModelFromSdrPage().setTheme(pTheme);
1307 std::shared_ptr<model::Theme> const& SdrPageProperties::getTheme() const
1309 // if set - page theme has priority
1310 if (mpTheme)
1311 return mpTheme;
1312 // else the model theme
1313 else if (mpSdrPage)
1314 return mpSdrPage->getSdrModelFromSdrPage().getTheme();
1315 // else return empty shared_ptr
1316 return mpTheme;
1319 void SdrPageProperties::dumpAsXml(xmlTextWriterPtr pWriter) const
1321 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SdrPageProperties"));
1322 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
1324 if (mpTheme)
1326 mpTheme->dumpAsXml(pWriter);
1329 (void)xmlTextWriterEndElement(pWriter);
1332 SdrPage::SdrPage(SdrModel& rModel, bool bMasterPage)
1333 : mrSdrModelFromSdrPage(rModel),
1334 mnWidth(10),
1335 mnHeight(10),
1336 mnBorderLeft(0),
1337 mnBorderUpper(0),
1338 mnBorderRight(0),
1339 mnBorderLower(0),
1340 mpLayerAdmin(new SdrLayerAdmin(&rModel.GetLayerAdmin())),
1341 m_nPageNum(0),
1342 mbMaster(bMasterPage),
1343 mbInserted(false),
1344 mbObjectsNotPersistent(false),
1345 mbPageBorderOnlyLeftRight(false)
1347 mpSdrPageProperties.reset(new SdrPageProperties(*this));
1350 SdrPage::~SdrPage()
1352 if( mxUnoPage.is() ) try
1354 uno::Reference< lang::XComponent > xPageComponent( mxUnoPage, uno::UNO_QUERY_THROW );
1355 mxUnoPage.clear();
1356 xPageComponent->dispose();
1358 catch( const uno::Exception& )
1360 DBG_UNHANDLED_EXCEPTION("svx");
1363 // tell all the registered PageUsers that the page is in destruction
1364 // This causes some (all?) PageUsers to remove themselves from the list
1365 // of page users. Therefore we have to use a copy of the list for the
1366 // iteration.
1367 sdr::PageUserVector aListCopy (maPageUsers.begin(), maPageUsers.end());
1368 for(sdr::PageUser* pPageUser : aListCopy)
1370 DBG_ASSERT(pPageUser, "SdrPage::~SdrPage: corrupt PageUser list (!)");
1371 pPageUser->PageInDestruction(*this);
1374 // Clear the vector. This means that user do not need to call RemovePageUser()
1375 // when they get called from PageInDestruction().
1376 maPageUsers.clear();
1378 mpLayerAdmin.reset();
1380 TRG_ClearMasterPage();
1382 mpViewContact.reset();
1383 mpSdrPageProperties.reset();
1386 void SdrPage::lateInit(const SdrPage& rSrcPage)
1388 assert(!mpViewContact);
1389 assert(!mxUnoPage.is());
1391 // copy all the local parameters to make this instance
1392 // a valid copy of source page before copying and inserting
1393 // the contained objects
1394 mbMaster = rSrcPage.mbMaster;
1395 mbPageBorderOnlyLeftRight = rSrcPage.mbPageBorderOnlyLeftRight;
1396 mnWidth = rSrcPage.mnWidth;
1397 mnHeight = rSrcPage.mnHeight;
1398 mnBorderLeft = rSrcPage.mnBorderLeft;
1399 mnBorderUpper = rSrcPage.mnBorderUpper;
1400 mnBorderRight = rSrcPage.mnBorderRight;
1401 mnBorderLower = rSrcPage.mnBorderLower;
1402 mbBackgroundFullSize = rSrcPage.mbBackgroundFullSize;
1403 m_nPageNum = rSrcPage.m_nPageNum;
1405 if(rSrcPage.TRG_HasMasterPage())
1407 TRG_SetMasterPage(rSrcPage.TRG_GetMasterPage());
1408 TRG_SetMasterPageVisibleLayers(rSrcPage.TRG_GetMasterPageVisibleLayers());
1410 else
1412 TRG_ClearMasterPage();
1415 mbObjectsNotPersistent = rSrcPage.mbObjectsNotPersistent;
1418 mpSdrPageProperties.reset(new SdrPageProperties(*this));
1420 if(!IsMasterPage())
1422 mpSdrPageProperties->PutItemSet(rSrcPage.getSdrPageProperties().GetItemSet());
1425 mpSdrPageProperties->SetStyleSheet(rSrcPage.getSdrPageProperties().GetStyleSheet());
1428 // Now copy the contained objects
1429 if(0 != rSrcPage.GetObjCount())
1431 CopyObjects(rSrcPage);
1435 rtl::Reference<SdrPage> SdrPage::CloneSdrPage(SdrModel& rTargetModel) const
1437 rtl::Reference<SdrPage> pClonedPage(new SdrPage(rTargetModel));
1438 pClonedPage->lateInit(*this);
1439 return pClonedPage;
1442 void SdrPage::SetSize(const Size& aSiz)
1444 bool bChanged(false);
1446 if(aSiz.Width() != mnWidth)
1448 mnWidth = aSiz.Width();
1449 bChanged = true;
1452 if(aSiz.Height() != mnHeight)
1454 mnHeight = aSiz.Height();
1455 bChanged = true;
1458 if(bChanged)
1460 SetChanged();
1464 Size SdrPage::GetSize() const
1466 return Size(mnWidth,mnHeight);
1469 tools::Long SdrPage::GetWidth() const
1471 return mnWidth;
1474 void SdrPage::SetOrientation(Orientation eOri)
1476 // square: handle like portrait format
1477 Size aSiz(GetSize());
1478 if (aSiz.Width()!=aSiz.Height()) {
1479 if ((eOri==Orientation::Portrait) == (aSiz.Width()>aSiz.Height())) {
1480 // coverity[swapped_arguments : FALSE] - this is in the correct order
1481 SetSize(Size(aSiz.Height(),aSiz.Width()));
1486 Orientation SdrPage::GetOrientation() const
1488 // square: handle like portrait format
1489 Orientation eRet=Orientation::Portrait;
1490 Size aSiz(GetSize());
1491 if (aSiz.Width()>aSiz.Height()) eRet=Orientation::Landscape;
1492 return eRet;
1495 tools::Long SdrPage::GetHeight() const
1497 return mnHeight;
1500 void SdrPage::SetBorder(sal_Int32 nLft, sal_Int32 nUpp, sal_Int32 nRgt, sal_Int32 nLwr)
1502 bool bChanged(false);
1504 if(mnBorderLeft != nLft)
1506 mnBorderLeft = nLft;
1507 bChanged = true;
1510 if(mnBorderUpper != nUpp)
1512 mnBorderUpper = nUpp;
1513 bChanged = true;
1516 if(mnBorderRight != nRgt)
1518 mnBorderRight = nRgt;
1519 bChanged = true;
1522 if(mnBorderLower != nLwr)
1524 mnBorderLower = nLwr;
1525 bChanged = true;
1528 if(bChanged)
1530 SetChanged();
1534 void SdrPage::SetLeftBorder(sal_Int32 nBorder)
1536 if(mnBorderLeft != nBorder)
1538 mnBorderLeft = nBorder;
1539 SetChanged();
1543 void SdrPage::SetUpperBorder(sal_Int32 nBorder)
1545 if(mnBorderUpper != nBorder)
1547 mnBorderUpper = nBorder;
1548 SetChanged();
1552 void SdrPage::SetRightBorder(sal_Int32 nBorder)
1554 if(mnBorderRight != nBorder)
1556 mnBorderRight=nBorder;
1557 SetChanged();
1561 void SdrPage::SetLowerBorder(sal_Int32 nBorder)
1563 if(mnBorderLower != nBorder)
1565 mnBorderLower=nBorder;
1566 SetChanged();
1570 sal_Int32 SdrPage::GetLeftBorder() const
1572 return mnBorderLeft;
1575 sal_Int32 SdrPage::GetUpperBorder() const
1577 return mnBorderUpper;
1580 sal_Int32 SdrPage::GetRightBorder() const
1582 return mnBorderRight;
1585 sal_Int32 SdrPage::GetLowerBorder() const
1587 return mnBorderLower;
1590 void SdrPage::SetBackgroundFullSize(bool const bIn)
1592 if (bIn != mbBackgroundFullSize)
1594 mbBackgroundFullSize = bIn;
1595 SetChanged();
1599 bool SdrPage::IsBackgroundFullSize() const
1601 return mbBackgroundFullSize;
1604 // #i68775# React on PageNum changes (from Model in most cases)
1605 void SdrPage::SetPageNum(sal_uInt16 nNew)
1607 if(nNew != m_nPageNum)
1609 // change
1610 m_nPageNum = nNew;
1612 // notify visualisations, also notifies e.g. buffered MasterPages
1613 ActionChanged();
1617 sal_uInt16 SdrPage::GetPageNum() const
1619 if (!mbInserted)
1620 return 0;
1622 if (mbMaster) {
1623 if (getSdrModelFromSdrPage().IsMPgNumsDirty())
1624 getSdrModelFromSdrPage().RecalcPageNums(true);
1625 } else {
1626 if (getSdrModelFromSdrPage().IsPagNumsDirty())
1627 getSdrModelFromSdrPage().RecalcPageNums(false);
1629 return m_nPageNum;
1632 void SdrPage::SetChanged()
1634 // For test purposes, use the new ViewContact for change
1635 // notification now.
1636 ActionChanged();
1637 getSdrModelFromSdrPage().SetChanged();
1640 SdrPage* SdrPage::getSdrPageFromSdrObjList() const
1642 return const_cast< SdrPage* >(this);
1645 // MasterPage interface
1647 void SdrPage::TRG_SetMasterPage(SdrPage& rNew)
1649 if(mpMasterPageDescriptor && &(mpMasterPageDescriptor->GetUsedPage()) == &rNew)
1650 return;
1652 if(mpMasterPageDescriptor)
1653 TRG_ClearMasterPage();
1655 mpMasterPageDescriptor.reset(new sdr::MasterPageDescriptor(*this, rNew));
1656 GetViewContact().ActionChanged();
1659 void SdrPage::TRG_ClearMasterPage()
1661 if(mpMasterPageDescriptor)
1663 SetChanged();
1665 // the flushViewObjectContacts() will do needed invalidates by deleting the involved VOCs
1666 mpMasterPageDescriptor->GetUsedPage().GetViewContact().flushViewObjectContacts();
1668 mpMasterPageDescriptor.reset();
1672 SdrPage& SdrPage::TRG_GetMasterPage() const
1674 DBG_ASSERT(mpMasterPageDescriptor != nullptr, "TRG_GetMasterPage(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
1675 return mpMasterPageDescriptor->GetUsedPage();
1678 const SdrLayerIDSet& SdrPage::TRG_GetMasterPageVisibleLayers() const
1680 DBG_ASSERT(mpMasterPageDescriptor != nullptr, "TRG_GetMasterPageVisibleLayers(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
1681 return mpMasterPageDescriptor->GetVisibleLayers();
1684 void SdrPage::TRG_SetMasterPageVisibleLayers(const SdrLayerIDSet& rNew)
1686 DBG_ASSERT(mpMasterPageDescriptor != nullptr, "TRG_SetMasterPageVisibleLayers(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
1687 mpMasterPageDescriptor->SetVisibleLayers(rNew);
1690 sdr::contact::ViewContact& SdrPage::TRG_GetMasterPageDescriptorViewContact() const
1692 DBG_ASSERT(mpMasterPageDescriptor != nullptr, "TRG_GetMasterPageDescriptorViewContact(): No MasterPage available. Use TRG_HasMasterPage() before access (!)");
1693 return mpMasterPageDescriptor->GetViewContact();
1696 // used from SdrModel::RemoveMasterPage
1697 void SdrPage::TRG_ImpMasterPageRemoved(const SdrPage& rRemovedPage)
1699 if(TRG_HasMasterPage())
1701 if(&TRG_GetMasterPage() == &rRemovedPage)
1703 TRG_ClearMasterPage();
1708 void SdrPage::MakePageObjectsNamesUnique()
1710 std::unordered_set<OUString> aNameSet;
1711 for (const rtl::Reference<SdrObject>& pObj : *this)
1713 if (!pObj->GetName().isEmpty())
1715 pObj->MakeNameUnique(aNameSet);
1716 SdrObjList* pSdrObjList = pObj->GetSubList(); // group
1717 if (pSdrObjList)
1719 SdrObject* pListObj;
1720 SdrObjListIter aIter(pSdrObjList, SdrIterMode::DeepWithGroups);
1721 while (aIter.IsMore())
1723 pListObj = aIter.Next();
1724 pListObj->MakeNameUnique(aNameSet);
1731 const SdrPageGridFrameList* SdrPage::GetGridFrameList(const SdrPageView* /*pPV*/, const tools::Rectangle* /*pRect*/) const
1733 return nullptr;
1736 const SdrLayerAdmin& SdrPage::GetLayerAdmin() const
1738 return *mpLayerAdmin;
1741 SdrLayerAdmin& SdrPage::GetLayerAdmin()
1743 return *mpLayerAdmin;
1746 void SdrPage::SetInserted( bool bIns )
1748 if( mbInserted == bIns )
1749 return;
1751 mbInserted = bIns;
1753 // #i120437# go over whole hierarchy, not only over object level null (seen from grouping)
1754 SdrObjListIter aIter(this, SdrIterMode::DeepNoGroups);
1756 while ( aIter.IsMore() )
1758 SdrObject* pObj = aIter.Next();
1759 if ( auto pOleObj = dynamic_cast<SdrOle2Obj* >(pObj) )
1761 if( mbInserted )
1762 pOleObj->Connect();
1763 else
1764 pOleObj->Disconnect();
1769 void SdrPage::SetUnoPage(uno::Reference<drawing::XDrawPage> const& xNewPage)
1771 mxUnoPage = xNewPage;
1774 uno::Reference< uno::XInterface > const & SdrPage::getUnoPage()
1776 if( !mxUnoPage.is() )
1778 // create one
1779 mxUnoPage = createUnoPage();
1782 return mxUnoPage;
1785 uno::Reference< uno::XInterface > SdrPage::createUnoPage()
1787 return cppu::getXWeak(new SvxDrawPage(this));
1790 SfxStyleSheet* SdrPage::GetTextStyleSheetForObject( SdrObject* pObj ) const
1792 return pObj->GetStyleSheet();
1795 /** returns an averaged background color of this page */
1796 // #i75566# GetBackgroundColor -> GetPageBackgroundColor and bScreenDisplay hint value
1797 Color SdrPage::GetPageBackgroundColor( SdrPageView const * pView, bool bScreenDisplay ) const
1799 Color aColor;
1801 if(bScreenDisplay && (!pView || pView->GetApplicationDocumentColor() == COL_AUTO))
1803 if (const SfxViewShell* pViewShell = SfxViewShell::Current())
1804 aColor = pViewShell->GetColorConfigColor(svtools::DOCCOLOR);
1805 else
1807 svtools::ColorConfig aColorConfig;
1808 aColor = aColorConfig.GetColorValue( svtools::DOCCOLOR ).nColor;
1811 else
1813 aColor = pView->GetApplicationDocumentColor();
1816 const SfxItemSet* pBackgroundFill = &getSdrPageProperties().GetItemSet();
1818 if(!IsMasterPage() && TRG_HasMasterPage())
1820 if(drawing::FillStyle_NONE == pBackgroundFill->Get(XATTR_FILLSTYLE).GetValue())
1822 // See unomodel.cxx: "It is guaranteed, that after a standard page the corresponding notes page follows."
1823 bool notesPage = GetPageNum() % 2 == 0;
1825 if (!comphelper::LibreOfficeKit::isActive() || !notesPage || !getSdrModelFromSdrPage().IsImpress())
1826 pBackgroundFill = &TRG_GetMasterPage().getSdrPageProperties().GetItemSet();
1827 else
1830 See sdrmasterpagedescriptor.cxx: e.g. the Notes MasterPage has no StyleSheet set (and there maybe others).
1833 // This is a notes page. Try to get itemset from standard page's master.
1834 if (getSdrModelFromSdrPage().GetPage(GetPageNum() - 1))
1835 pBackgroundFill = &getSdrModelFromSdrPage().GetPage(GetPageNum() - 1)->TRG_GetMasterPage().getSdrPageProperties().GetItemSet();
1836 else
1837 pBackgroundFill = &TRG_GetMasterPage().getSdrPageProperties().GetItemSet();
1842 if (auto oColor = GetDraftFillColor(*pBackgroundFill))
1843 aColor = *oColor;
1845 return aColor;
1848 /** *deprecated, use GetBackgroundColor with SdrPageView */
1849 Color SdrPage::GetPageBackgroundColor() const
1850 // #i75566# GetBackgroundColor -> GetPageBackgroundColor
1852 return GetPageBackgroundColor( nullptr );
1855 /** this method returns true if the object from the ViewObjectContact should
1856 be visible on this page while rendering.
1857 bEdit selects if visibility test is for an editing view or a final render,
1858 like printing.
1860 bool SdrPage::checkVisibility(
1861 const sdr::contact::ViewObjectContact& /*rOriginal*/,
1862 const sdr::contact::DisplayInfo& /*rDisplayInfo*/,
1863 bool /*bEdit*/)
1865 // this will be handled in the application if needed
1866 return true;
1869 void SdrPage::dumpAsXml(xmlTextWriterPtr pWriter) const
1871 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SdrPage"));
1872 SdrObjList::dumpAsXml(pWriter);
1874 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("width"));
1875 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("value"), "%s",
1876 BAD_CAST(OString::number(mnWidth).getStr()));
1877 (void)xmlTextWriterEndElement(pWriter);
1878 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("height"));
1879 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("value"), "%s",
1880 BAD_CAST(OString::number(mnHeight).getStr()));
1881 (void)xmlTextWriterEndElement(pWriter);
1883 if (mpSdrPageProperties)
1885 mpSdrPageProperties->dumpAsXml(pWriter);
1888 (void)xmlTextWriterEndElement(pWriter);
1891 // DrawContact support: Methods for handling Page changes
1892 void SdrPage::ActionChanged()
1894 // Do necessary ViewContact actions
1895 GetViewContact().ActionChanged();
1897 // #i48535# also handle MasterPage change
1898 if(TRG_HasMasterPage())
1900 TRG_GetMasterPageDescriptorViewContact().ActionChanged();
1904 SdrPageProperties& SdrPage::getSdrPageProperties()
1906 return *mpSdrPageProperties;
1909 const SdrPageProperties& SdrPage::getSdrPageProperties() const
1911 return *mpSdrPageProperties;
1914 const SdrPageProperties* SdrPage::getCorrectSdrPageProperties() const
1916 if(mpMasterPageDescriptor)
1918 return mpMasterPageDescriptor->getCorrectSdrPageProperties();
1920 else
1922 return &getSdrPageProperties();
1926 rtl::Reference<sdr::annotation::Annotation> SdrPage::createAnnotation()
1928 assert(false);
1929 return nullptr;
1932 void SdrPage::addAnnotation(rtl::Reference<sdr::annotation::Annotation> const& /*xAnnotation*/, int /*nIndex*/)
1934 assert(false);
1937 void SdrPage::addAnnotationNoNotify(rtl::Reference<sdr::annotation::Annotation> const& /*xAnnotation*/, int /*nIndex*/)
1939 assert(false);
1942 void SdrPage::removeAnnotation(rtl::Reference<sdr::annotation::Annotation> const& /*xAnnotation*/)
1944 assert(false);
1947 void SdrPage::removeAnnotationNoNotify(rtl::Reference<sdr::annotation::Annotation> const& /*xAnnotation*/)
1949 assert(false);
1952 std::vector<rtl::Reference<sdr::annotation::Annotation>> const& SdrPage::getAnnotations() const
1954 return maAnnotations;
1957 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */