tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / svx / source / svdraw / svdedtv.cxx
blob15fff60a8490d51ebb803ddf333107561fdc839f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/svdedtv.hxx>
21 #include <svx/svdundo.hxx>
22 #include <svx/svdograf.hxx>
23 #include <svx/svdoole2.hxx>
24 #include <svx/svdoedge.hxx>
25 #include <svx/svdlayer.hxx>
26 #include <svx/svdpagv.hxx>
27 #include <svx/svdpage.hxx>
28 #include <svx/svdpoev.hxx>
29 #include <svx/strings.hrc>
30 #include <svx/dialmgr.hxx>
31 #include <svx/e3dsceneupdater.hxx>
32 #include <rtl/strbuf.hxx>
33 #include <svx/svdview.hxx>
34 #include <clonelist.hxx>
35 #include <svx/svdogrp.hxx>
36 #include <svx/xfillit0.hxx>
37 #include <osl/diagnose.h>
38 #include <sfx2/viewsh.hxx>
40 #include <com/sun/star/lang/XServiceInfo.hpp>
42 using namespace com::sun::star;
44 void SdrEditView::ImpResetPossibilityFlags()
46 m_bReadOnly =false;
48 m_bGroupPossible =false;
49 m_bUnGroupPossible =false;
50 m_bGrpEnterPossible =false;
51 m_bToTopPossible =false;
52 m_bToBtmPossible =false;
53 m_bReverseOrderPossible =false;
55 m_bImportMtfPossible =false;
56 m_bCombinePossible =false;
57 m_bDismantlePossible =false;
58 m_bCombineNoPolyPolyPossible =false;
59 m_bDismantleMakeLinesPossible=false;
60 m_bOrthoDesiredOnMarked =false;
62 m_bOneOrMoreMovable =false;
63 m_bMoreThanOneNoMovRot =false;
64 m_bContortionPossible =false;
65 m_bMoveAllowed =false;
66 m_bResizeFreeAllowed =false;
67 m_bResizePropAllowed =false;
68 m_bRotateFreeAllowed =false;
69 m_bRotate90Allowed =false;
70 m_bMirrorFreeAllowed =false;
71 m_bMirror45Allowed =false;
72 m_bMirror90Allowed =false;
73 m_bTransparenceAllowed =false;
74 m_bCropAllowed =false;
75 m_bGradientAllowed =false;
76 m_bShearAllowed =false;
77 m_bEdgeRadiusAllowed =false;
78 m_bCanConvToPath =false;
79 m_bCanConvToPoly =false;
80 m_bCanConvToContour =false;
81 m_bMoveProtect =false;
82 m_bResizeProtect =false;
85 SdrEditView::SdrEditView(SdrModel& rSdrModel, OutputDevice* pOut)
86 : SdrMarkView(rSdrModel, pOut)
87 , m_bPossibilitiesDirty(true)
88 , m_bReadOnly(false)
89 , m_bGroupPossible(false)
90 , m_bUnGroupPossible(false)
91 , m_bGrpEnterPossible(false)
92 , m_bToTopPossible(false)
93 , m_bToBtmPossible(false)
94 , m_bReverseOrderPossible(false)
95 , m_bImportMtfPossible(false)
96 , m_bCombinePossible(false)
97 , m_bDismantlePossible(false)
98 , m_bCombineNoPolyPolyPossible(false)
99 , m_bDismantleMakeLinesPossible(false)
100 , m_bOrthoDesiredOnMarked(false)
101 , m_bOneOrMoreMovable(false)
102 , m_bMoreThanOneNoMovRot(false)
103 , m_bContortionPossible(false)
104 , m_bMoveAllowed(false)
105 , m_bResizeFreeAllowed(false)
106 , m_bResizePropAllowed(false)
107 , m_bRotateFreeAllowed(false)
108 , m_bRotate90Allowed(false)
109 , m_bMirrorFreeAllowed(false)
110 , m_bMirror45Allowed(false)
111 , m_bMirror90Allowed(false)
112 , m_bShearAllowed(false)
113 , m_bEdgeRadiusAllowed(false)
114 , m_bTransparenceAllowed(false)
115 , m_bCropAllowed(false)
116 , m_bGradientAllowed(false)
117 , m_bCanConvToPath(false)
118 , m_bCanConvToPoly(false)
119 , m_bCanConvToContour(false)
120 , m_bMoveProtect(false)
121 , m_bResizeProtect(false)
125 SdrEditView::~SdrEditView()
129 void SdrEditView::InsertNewLayer(const OUString& rName, sal_uInt16 nPos)
131 SdrLayerAdmin& rLA = GetModel().GetLayerAdmin();
132 sal_uInt16 nMax=rLA.GetLayerCount();
133 if (nPos>nMax) nPos=nMax;
134 rLA.NewLayer(rName,nPos);
136 if( GetModel().IsUndoEnabled() )
137 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoNewLayer(nPos,rLA, GetModel()));
139 GetModel().SetChanged();
142 bool SdrEditView::ImpDelLayerCheck(SdrObjList const * pOL, SdrLayerID nDelID) const
144 bool bDelAll(true);
146 for(size_t nObjNum = pOL->GetObjCount(); nObjNum > 0 && bDelAll;)
148 nObjNum--;
149 SdrObject* pObj = pOL->GetObj(nObjNum);
150 assert(pObj);
151 SdrObjList* pSubOL = pObj->GetSubList();
153 // explicitly test for group objects and 3d scenes
154 if(pSubOL && (dynamic_cast<const SdrObjGroup*>(pObj) != nullptr || DynCastE3dScene(pObj)))
156 if(!ImpDelLayerCheck(pSubOL, nDelID))
158 bDelAll = false;
161 else
163 if(pObj->GetLayer() != nDelID)
165 bDelAll = false;
170 return bDelAll;
173 void SdrEditView::ImpDelLayerDelObjs(SdrObjList* pOL, SdrLayerID nDelID)
175 const size_t nObjCount(pOL->GetObjCount());
176 // make sure OrdNums are correct
177 pOL->GetObj(0)->GetOrdNum();
179 const bool bUndo = GetModel().IsUndoEnabled();
181 for(size_t nObjNum = nObjCount; nObjNum > 0;)
183 nObjNum--;
184 SdrObject* pObj = pOL->GetObj(nObjNum);
185 assert(pObj);
186 SdrObjList* pSubOL = pObj->GetSubList();
189 // explicitly test for group objects and 3d scenes
190 if(pSubOL && (dynamic_cast<const SdrObjGroup*>( pObj) != nullptr || DynCastE3dScene(pObj)))
192 if(ImpDelLayerCheck(pSubOL, nDelID))
194 if( bUndo )
195 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true));
196 pOL->RemoveObject(nObjNum);
198 else
200 ImpDelLayerDelObjs(pSubOL, nDelID);
203 else
205 if(pObj->GetLayer() == nDelID)
207 if( bUndo )
208 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true));
209 pOL->RemoveObject(nObjNum);
215 void SdrEditView::DeleteLayer(const OUString& rName)
217 SdrLayerAdmin& rLA = GetModel().GetLayerAdmin();
218 SdrLayer* pLayer = rLA.GetLayer(rName);
220 if(!pLayer)
221 return;
223 sal_uInt16 nLayerNum(rLA.GetLayerPos(pLayer));
224 SdrLayerID nDelID = pLayer->GetID();
226 const bool bUndo = IsUndoEnabled();
227 if( bUndo )
228 BegUndo(SvxResId(STR_UndoDelLayer));
230 bool bMaPg(true);
232 for(sal_uInt16 nPageKind(0); nPageKind < 2; nPageKind++)
234 // MasterPages and DrawPages
235 sal_uInt16 nPgCount(bMaPg ? GetModel().GetMasterPageCount() : GetModel().GetPageCount());
237 for(sal_uInt16 nPgNum(0); nPgNum < nPgCount; nPgNum++)
239 // over all pages
240 SdrPage* pPage = bMaPg ? GetModel().GetMasterPage(nPgNum) : GetModel().GetPage(nPgNum);
241 const size_t nObjCount(pPage->GetObjCount());
243 // make sure OrdNums are correct
244 if(nObjCount)
245 pPage->GetObj(0)->GetOrdNum();
247 for(size_t nObjNum(nObjCount); nObjNum > 0;)
249 nObjNum--;
250 SdrObject* pObj = pPage->GetObj(nObjNum);
251 assert(pObj);
252 SdrObjList* pSubOL = pObj->GetSubList();
254 // explicitly test for group objects and 3d scenes
255 if(pSubOL && (dynamic_cast<const SdrObjGroup*>(pObj) != nullptr || DynCastE3dScene(pObj)))
257 if(ImpDelLayerCheck(pSubOL, nDelID))
259 if( bUndo )
260 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true));
261 pPage->RemoveObject(nObjNum);
263 else
265 ImpDelLayerDelObjs(pSubOL, nDelID);
268 else
270 if(pObj->GetLayer() == nDelID)
272 if( bUndo )
273 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true));
274 pPage->RemoveObject(nObjNum);
279 bMaPg = false;
282 if( bUndo )
284 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteLayer(nLayerNum, rLA, GetModel()));
285 // coverity[leaked_storage] - ownership transferred to UndoDeleteLayer
286 rLA.RemoveLayer(nLayerNum).release();
287 EndUndo();
289 else
291 rLA.RemoveLayer(nLayerNum);
294 GetModel().SetChanged();
298 void SdrEditView::EndUndo()
300 // #i13033#
301 // Comparison changed to 1L since EndUndo() is called later now
302 // and EndUndo WILL change count to count-1
303 if(1 == GetModel().GetUndoBracketLevel())
305 ImpBroadcastEdgesOfMarkedNodes();
308 // #i13033#
309 // moved to bottom to still have access to UNDOs inside of
310 // ImpBroadcastEdgesOfMarkedNodes()
311 GetModel().EndUndo();
314 void SdrEditView::ImpBroadcastEdgesOfMarkedNodes()
316 std::vector<SdrObject*>::const_iterator iterPos;
317 const std::vector<SdrObject*>& rAllMarkedObjects = GetTransitiveHullOfMarkedObjects();
319 // #i13033#
320 // New mechanism to search for necessary disconnections for
321 // changed connectors inside the transitive hull of all at
322 // the beginning of UNDO selected objects
323 for(size_t a(0); a < rAllMarkedObjects.size(); a++)
325 SdrEdgeObj* pEdge = dynamic_cast<SdrEdgeObj*>( rAllMarkedObjects[a] );
327 if(pEdge)
329 SdrObject* pObj1 = pEdge->GetConnectedNode(false);
330 SdrObject* pObj2 = pEdge->GetConnectedNode(true);
332 if(pObj1 && !pEdge->CheckNodeConnection(false))
334 iterPos = std::find(rAllMarkedObjects.begin(),rAllMarkedObjects.end(),pObj1);
336 if (iterPos == rAllMarkedObjects.end())
338 if( IsUndoEnabled() )
339 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pEdge));
340 pEdge->DisconnectFromNode(false);
344 if(pObj2 && !pEdge->CheckNodeConnection(true))
346 iterPos = std::find(rAllMarkedObjects.begin(),rAllMarkedObjects.end(),pObj2);
348 if (iterPos == rAllMarkedObjects.end())
350 if( IsUndoEnabled() )
351 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pEdge));
352 pEdge->DisconnectFromNode(true);
358 const size_t nMarkedEdgeCnt = GetMarkedEdgesOfMarkedNodes().GetMarkCount();
360 for (size_t i=0; i<nMarkedEdgeCnt; ++i) {
361 SdrMark* pEM = GetMarkedEdgesOfMarkedNodes().GetMark(i);
362 SdrObject* pEdgeTmp=pEM->GetMarkedSdrObj();
363 SdrEdgeObj* pEdge=dynamic_cast<SdrEdgeObj*>( pEdgeTmp );
364 if (pEdge!=nullptr) {
365 pEdge->SetEdgeTrackDirty();
371 // Possibilities
374 void SdrEditView::MarkListHasChanged()
376 SdrMarkView::MarkListHasChanged();
377 m_bPossibilitiesDirty=true;
380 void SdrEditView::ModelHasChanged()
382 SdrMarkView::ModelHasChanged();
383 m_bPossibilitiesDirty=true;
386 bool SdrEditView::IsResizeAllowed(bool bProp) const
388 ForcePossibilities();
389 if (m_bResizeProtect) return false;
390 if (bProp) return m_bResizePropAllowed;
391 return m_bResizeFreeAllowed;
394 bool SdrEditView::IsRotateAllowed(bool b90Deg) const
396 ForcePossibilities();
397 if (m_bMoveProtect) return false;
398 if (b90Deg) return m_bRotate90Allowed;
399 return m_bRotateFreeAllowed;
402 bool SdrEditView::IsMirrorAllowed(bool b45Deg, bool b90Deg) const
404 ForcePossibilities();
405 if (m_bMoveProtect) return false;
406 if (b90Deg) return m_bMirror90Allowed;
407 if (b45Deg) return m_bMirror45Allowed;
408 return m_bMirrorFreeAllowed;
411 bool SdrEditView::IsTransparenceAllowed() const
413 ForcePossibilities();
414 return m_bTransparenceAllowed;
417 bool SdrEditView::IsCropAllowed() const
419 ForcePossibilities();
420 return m_bCropAllowed;
423 bool SdrEditView::IsGradientAllowed() const
425 ForcePossibilities();
426 return m_bGradientAllowed;
429 bool SdrEditView::IsShearAllowed() const
431 ForcePossibilities();
432 if (m_bResizeProtect) return false;
433 return m_bShearAllowed;
436 bool SdrEditView::IsEdgeRadiusAllowed() const
438 ForcePossibilities();
439 return m_bEdgeRadiusAllowed;
442 bool SdrEditView::IsCrookAllowed(bool bNoContortion) const
444 // CrookMode missing here (no rotations allowed when shearing ...)
445 ForcePossibilities();
446 if (bNoContortion) {
447 if (!m_bRotateFreeAllowed) return false;
448 return !m_bMoveProtect && m_bMoveAllowed;
449 } else {
450 return !m_bResizeProtect && m_bContortionPossible;
454 bool SdrEditView::IsDistortAllowed(bool bNoContortion) const
456 ForcePossibilities();
457 if (bNoContortion) {
458 return false;
459 } else {
460 return !m_bResizeProtect && m_bContortionPossible;
464 bool SdrEditView::IsCombinePossible(bool bNoPolyPoly) const
466 ForcePossibilities();
467 if (bNoPolyPoly) return m_bCombineNoPolyPolyPossible;
468 else return m_bCombinePossible;
471 bool SdrEditView::IsDismantlePossible(bool bMakeLines) const
473 ForcePossibilities();
474 if (bMakeLines) return m_bDismantleMakeLinesPossible;
475 else return m_bDismantlePossible;
478 void SdrEditView::CheckPossibilities()
480 if (mbSomeObjChgdFlag)
482 m_bPossibilitiesDirty = true;
484 // This call IS necessary to correct the MarkList, in which
485 // no longer to the model belonging objects still can reside.
486 // These ones need to be removed.
487 CheckMarked();
490 if (!m_bPossibilitiesDirty)
491 return;
493 const SdrMarkList& rMarkList = GetMarkedObjectList();
494 ImpResetPossibilityFlags();
495 rMarkList.ForceSort();
496 const size_t nMarkCount = rMarkList.GetMarkCount();
497 if (nMarkCount != 0)
499 m_bReverseOrderPossible = (nMarkCount >= 2);
501 size_t nMovableCount=0;
502 m_bGroupPossible=nMarkCount>=2;
503 m_bCombinePossible=nMarkCount>=2;
504 if (nMarkCount==1)
506 // check bCombinePossible more thoroughly
507 // still missing ...
508 const SdrObject* pObj=rMarkList.GetMark(0)->GetMarkedSdrObj();
509 //const SdrPathObj* pPath=dynamic_cast<SdrPathObj*>( pObj );
510 bool bGroup=pObj->GetSubList()!=nullptr;
511 bool bHasText=pObj->GetOutlinerParaObject()!=nullptr;
512 if (bGroup || bHasText) {
513 m_bCombinePossible=true;
516 m_bCombineNoPolyPolyPossible=m_bCombinePossible;
517 // accept transformations for now
518 m_bMoveAllowed =true;
519 m_bResizeFreeAllowed=true;
520 m_bResizePropAllowed=true;
521 m_bRotateFreeAllowed=true;
522 m_bRotate90Allowed =true;
523 m_bMirrorFreeAllowed=true;
524 m_bMirror45Allowed =true;
525 m_bMirror90Allowed =true;
526 m_bShearAllowed =true;
527 m_bEdgeRadiusAllowed=false;
528 m_bContortionPossible=true;
529 m_bCanConvToContour = true;
531 // these ones are only allowed when single object is selected
532 m_bTransparenceAllowed = (nMarkCount == 1);
533 m_bGradientAllowed = (nMarkCount == 1);
534 m_bCropAllowed = (nMarkCount == 1);
535 if(m_bGradientAllowed)
537 // gradient depends on fill style
538 const SdrMark* pM = rMarkList.GetMark(0);
539 const SdrObject* pObj = pM->GetMarkedSdrObj();
541 // may be group object, so get merged ItemSet
542 const SfxItemSet& rSet = pObj->GetMergedItemSet();
543 SfxItemState eState = rSet.GetItemState(XATTR_FILLSTYLE, false);
545 if(SfxItemState::INVALID != eState)
547 // If state is not DONTCARE, test the item
548 drawing::FillStyle eFillStyle = rSet.Get(XATTR_FILLSTYLE).GetValue();
550 if(eFillStyle != drawing::FillStyle_GRADIENT)
552 m_bGradientAllowed = false;
557 bool bNoMovRotFound=false;
558 const SdrPageView* pPV0=nullptr;
560 for (size_t nm=0; nm<nMarkCount; ++nm) {
561 const SdrMark* pM=rMarkList.GetMark(nm);
562 const SdrObject* pObj=pM->GetMarkedSdrObj();
563 const SdrPageView* pPV=pM->GetPageView();
564 if (pPV!=pPV0) {
565 if (pPV->IsReadOnly()) m_bReadOnly=true;
566 pPV0=pPV;
569 SdrObjTransformInfoRec aInfo;
570 pObj->TakeObjInfo(aInfo);
571 bool bMovPrt=pObj->IsMoveProtect();
572 bool bSizPrt=pObj->IsResizeProtect();
573 if (!bMovPrt && aInfo.bMoveAllowed) nMovableCount++; // count MovableObjs
574 if (bMovPrt) m_bMoveProtect=true;
575 if (bSizPrt) m_bResizeProtect=true;
577 // not allowed when not allowed at one object
578 if(!aInfo.bTransparenceAllowed)
579 m_bTransparenceAllowed = false;
581 // If one of these can't do something, none can
582 if (!aInfo.bMoveAllowed ) m_bMoveAllowed =false;
583 if (!aInfo.bResizeFreeAllowed) m_bResizeFreeAllowed=false;
584 if (!aInfo.bResizePropAllowed) m_bResizePropAllowed=false;
585 if (!aInfo.bRotateFreeAllowed) m_bRotateFreeAllowed=false;
586 if (!aInfo.bRotate90Allowed ) m_bRotate90Allowed =false;
587 if (!aInfo.bMirrorFreeAllowed) m_bMirrorFreeAllowed=false;
588 if (!aInfo.bMirror45Allowed ) m_bMirror45Allowed =false;
589 if (!aInfo.bMirror90Allowed ) m_bMirror90Allowed =false;
590 if (!aInfo.bShearAllowed ) m_bShearAllowed =false;
591 if (aInfo.bEdgeRadiusAllowed) m_bEdgeRadiusAllowed=true;
592 if (aInfo.bNoContortion ) m_bContortionPossible=false;
593 // For Crook with Contortion: all objects have to be
594 // Movable and Rotatable, except for a maximum of 1 of them
595 if (!m_bMoreThanOneNoMovRot) {
596 if (!aInfo.bMoveAllowed || !aInfo.bResizeFreeAllowed) {
597 m_bMoreThanOneNoMovRot=bNoMovRotFound;
598 bNoMovRotFound=true;
602 // Must be resizable to allow cropping
603 if (!aInfo.bResizeFreeAllowed && !aInfo.bResizePropAllowed)
604 m_bCropAllowed = false;
606 // if one member cannot be converted, no conversion is possible
607 if(!aInfo.bCanConvToContour)
608 m_bCanConvToContour = false;
610 // Ungroup
611 if (!m_bUnGroupPossible) m_bUnGroupPossible=pObj->GetSubList()!=nullptr;
612 // ConvertToCurve: If at least one can be converted, that is fine.
613 if (aInfo.bCanConvToPath ) m_bCanConvToPath =true;
614 if (aInfo.bCanConvToPoly ) m_bCanConvToPoly =true;
616 // Combine/Dismantle
617 if(m_bCombinePossible)
619 m_bCombinePossible = ImpCanConvertForCombine(pObj);
620 m_bCombineNoPolyPolyPossible = m_bCombinePossible;
623 if (!m_bDismantlePossible) m_bDismantlePossible = ImpCanDismantle(pObj, false);
624 if (!m_bDismantleMakeLinesPossible) m_bDismantleMakeLinesPossible = ImpCanDismantle(pObj, true);
625 // check OrthoDesiredOnMarked
626 if (!m_bOrthoDesiredOnMarked && !aInfo.bNoOrthoDesired) m_bOrthoDesiredOnMarked=true;
627 // check ImportMtf
629 if (!m_bImportMtfPossible)
631 const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(pObj);
632 if (pSdrGrafObj != nullptr)
634 if ((pSdrGrafObj->HasGDIMetaFile() && !pSdrGrafObj->IsEPS()) ||
635 pSdrGrafObj->isEmbeddedVectorGraphicData())
637 m_bImportMtfPossible = true;
641 const SdrOle2Obj* pSdrOle2Obj = dynamic_cast< const SdrOle2Obj* >(pObj);
642 if (pSdrOle2Obj)
644 m_bImportMtfPossible = pSdrOle2Obj->GetObjRef().is();
649 m_bOneOrMoreMovable=nMovableCount!=0;
650 m_bGrpEnterPossible=m_bUnGroupPossible;
652 ImpCheckToTopBtmPossible();
653 static_cast<SdrPolyEditView*>(this)->ImpCheckPolyPossibilities();
654 m_bPossibilitiesDirty=false;
656 if (m_bReadOnly || SfxViewShell::IsCurrentLokViewReadOnly() ) {
657 bool bTemp=m_bGrpEnterPossible;
658 ImpResetPossibilityFlags();
659 m_bReadOnly=true;
660 m_bGrpEnterPossible=bTemp;
662 if (!m_bMoveAllowed) return;
664 // Don't allow moving glued connectors.
665 // Currently only implemented for single selection.
666 if (nMarkCount==1) {
667 SdrObject* pObj=rMarkList.GetMark(0)->GetMarkedSdrObj();
668 SdrEdgeObj* pEdge=dynamic_cast<SdrEdgeObj*>( pObj );
669 if (pEdge!=nullptr) {
670 SdrObject* pNode1=pEdge->GetConnectedNode(true);
671 SdrObject* pNode2=pEdge->GetConnectedNode(false);
672 if (pNode1!=nullptr || pNode2!=nullptr) m_bMoveAllowed=false;
676 // Don't allow enter Diagrams
677 if (1 == nMarkCount && m_bGrpEnterPossible)
679 SdrObject* pCandidate(rMarkList.GetMark(0)->GetMarkedSdrObj());
681 if(nullptr != pCandidate && pCandidate->isDiagram())
682 m_bGrpEnterPossible = false;
687 void SdrEditView::ForceMarkedObjToAnotherPage()
689 const SdrMarkList& rMarkList = GetMarkedObjectList();
690 bool bFlg=false;
691 for (size_t nm=0; nm<rMarkList.GetMarkCount(); ++nm) {
692 SdrMark* pM=rMarkList.GetMark(nm);
693 SdrObject* pObj=pM->GetMarkedSdrObj();
694 tools::Rectangle aObjRect(pObj->GetCurrentBoundRect());
695 tools::Rectangle aPgRect(pM->GetPageView()->GetPageRect());
696 if (!aObjRect.Overlaps(aPgRect)) {
697 bool bFnd=false;
698 SdrPageView* pPV = GetSdrPageView();
700 if(pPV)
702 bFnd = aObjRect.Overlaps(pPV->GetPageRect());
705 if(bFnd)
707 pM->GetPageView()->GetObjList()->RemoveObject(pObj->GetOrdNum());
708 pPV->GetObjList()->InsertObject(pObj, SAL_MAX_SIZE);
709 pM->SetPageView(pPV);
710 InvalidateAllWin(aObjRect);
711 bFlg=true;
715 if (bFlg) {
716 MarkListHasChanged();
720 std::vector<rtl::Reference<SdrObject>> SdrEditView::DeleteMarkedList(SdrMarkList const& rMark)
722 std::vector<rtl::Reference<SdrObject>> ret;
723 if (rMark.GetMarkCount()!=0)
725 rMark.ForceSort();
727 const bool bUndo = IsUndoEnabled();
728 if( bUndo )
729 BegUndo();
730 const size_t nMarkCount(rMark.GetMarkCount());
732 if(nMarkCount)
734 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
736 if( bUndo )
738 for(size_t nm = nMarkCount; nm > 0;)
740 --nm;
741 SdrMark* pM = rMark.GetMark(nm);
742 SdrObject* pObj = pM->GetMarkedSdrObj();
744 // extra undo actions for changed connector which now may hold its laid out path (SJ)
745 AddUndoActions(CreateConnectorUndo( *pObj ));
747 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteObject(*pObj));
751 // make sure, OrderNums are correct:
752 rMark.GetMark(0)->GetMarkedSdrObj()->GetOrdNum();
754 for(size_t nm = nMarkCount; nm > 0;)
756 --nm;
757 SdrMark* pM = rMark.GetMark(nm);
758 SdrObject* pObj = pM->GetMarkedSdrObj();
759 SdrObjList* pOL = pObj->getParentSdrObjListFromSdrObject();
760 const size_t nOrdNum(pObj->GetOrdNumDirect());
762 bool bIs3D = DynCastE3dObject(pObj);
763 // set up a scene updater if object is a 3d object
764 if(bIs3D)
766 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pObj));
769 if( !bUndo )
771 // tdf#108863 and tdf#108889 don't delete objects before EndUndo()
772 ret.push_back(pObj);
775 pOL->RemoveObject(nOrdNum);
778 // fire scene updaters
779 while(!aUpdaters.empty())
781 delete aUpdaters.back();
782 aUpdaters.pop_back();
786 if( bUndo )
787 EndUndo();
789 return ret;
792 static void lcl_LazyDelete(std::vector<rtl::Reference<SdrObject>> & rLazyDelete)
794 // now delete removed scene objects
795 while (!rLazyDelete.empty())
796 rLazyDelete.pop_back();
799 void SdrEditView::DeleteMarkedObj()
801 const SdrMarkList& rMarkList = GetMarkedObjectList();
802 // #i110981# return when nothing is to be done at all
803 if(!rMarkList.GetMarkCount())
805 return;
808 // moved breaking action and undo start outside loop
809 BrkAction();
810 BegUndo(SvxResId(STR_EditDelete),rMarkList.GetMarkDescription(),SdrRepeatFunc::Delete);
812 std::vector<rtl::Reference<SdrObject>> lazyDeleteObjects;
813 // remove as long as something is selected. This allows to schedule objects for
814 // removal for a next run as needed
815 while(rMarkList.GetMarkCount())
817 // vector to remember the parents which may be empty after object removal
818 std::vector< SdrObject* > aParents;
821 const size_t nCount(rMarkList.GetMarkCount());
823 for(size_t a = 0; a < nCount; ++a)
825 // in the first run, add all found parents, but only once
826 SdrMark* pMark(rMarkList.GetMark(a));
827 SdrObject* pObject(pMark->GetMarkedSdrObj());
828 SdrObject* pParent(pObject->getParentSdrObjectFromSdrObject());
830 if(pParent)
832 if(!aParents.empty())
834 std::vector< SdrObject* >::iterator aFindResult =
835 std::find(aParents.begin(), aParents.end(), pParent);
837 if(aFindResult == aParents.end())
839 aParents.push_back(pParent);
842 else
844 aParents.push_back(pParent);
849 if(!aParents.empty())
851 // in a 2nd run, remove all objects which may already be scheduled for
852 // removal. I am not sure if this can happen, but theoretically
853 // a to-be-removed object may already be the group/3DScene itself
854 for(size_t a = 0; a < nCount; ++a)
856 SdrMark* pMark = rMarkList.GetMark(a);
857 SdrObject* pObject = pMark->GetMarkedSdrObj();
859 std::vector< SdrObject* >::iterator aFindResult =
860 std::find(aParents.begin(), aParents.end(), pObject);
862 if(aFindResult != aParents.end())
864 aParents.erase(aFindResult);
870 // original stuff: remove selected objects. Handle clear will
871 // do something only once
872 auto temp(DeleteMarkedList(rMarkList));
873 lazyDeleteObjects.insert(lazyDeleteObjects.end(), temp.begin(), temp.end());
874 GetMarkedObjectListWriteAccess().Clear();
875 maHdlList.Clear();
877 while(!aParents.empty() && !rMarkList.GetMarkCount())
879 // iterate over remembered parents
880 SdrObject* pParent = aParents.back();
881 aParents.pop_back();
883 if(pParent->GetSubList() && 0 == pParent->GetSubList()->GetObjCount())
885 // we detected an empty parent, a candidate to leave group/3DScene
886 // if entered
887 if(GetSdrPageView()->GetCurrentGroup()
888 && GetSdrPageView()->GetCurrentGroup() == pParent)
890 GetSdrPageView()->LeaveOneGroup();
893 // schedule empty parent for removal
894 GetMarkedObjectListWriteAccess().InsertEntry(
895 SdrMark(pParent, GetSdrPageView()));
900 // end undo and change messaging moved at the end
901 EndUndo();
902 MarkListHasChanged();
904 lcl_LazyDelete(lazyDeleteObjects);
907 void SdrEditView::CopyMarkedObj()
909 const SdrMarkList& rMarkList = GetMarkedObjectList();
910 rMarkList.ForceSort();
912 SdrMarkList aSourceObjectsForCopy(rMarkList);
913 // The following loop is used instead of MarkList::Merge(), to be
914 // able to flag the MarkEntries.
915 const size_t nEdgeCnt = GetEdgesOfMarkedNodes().GetMarkCount();
916 for (size_t nEdgeNum=0; nEdgeNum<nEdgeCnt; ++nEdgeNum) {
917 SdrMark aM(*GetEdgesOfMarkedNodes().GetMark(nEdgeNum));
918 aM.SetUser(1);
919 aSourceObjectsForCopy.InsertEntry(aM);
921 aSourceObjectsForCopy.ForceSort();
923 // #i13033#
924 // New mechanism to re-create the connections of cloned connectors
925 CloneList aCloneList;
927 const bool bUndo = IsUndoEnabled();
929 GetMarkedObjectListWriteAccess().Clear();
930 size_t nCloneErrCnt=0;
931 std::unordered_set<rtl::OUString> aNameSet;
932 const size_t nMarkCount=aSourceObjectsForCopy.GetMarkCount();
933 for (size_t nm=0; nm<nMarkCount; ++nm) {
934 SdrMark* pM=aSourceObjectsForCopy.GetMark(nm);
935 SdrObject* pSource(pM->GetMarkedSdrObj());
936 rtl::Reference<SdrObject> pO(pSource->CloneSdrObject(pSource->getSdrModelFromSdrObject()));
937 if (pO!=nullptr) {
938 pM->GetPageView()->GetObjList()->InsertObjectThenMakeNameUnique(pO.get(), aNameSet);
940 if( bUndo )
941 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoCopyObject(*pO));
943 SdrMark aME(*pM);
944 aME.SetMarkedSdrObj(pO.get());
945 aCloneList.AddPair(pM->GetMarkedSdrObj(), pO.get());
947 if (pM->GetUser()==0)
949 // otherwise it is only an Edge we have to copy as well
950 GetMarkedObjectListWriteAccess().InsertEntry(aME);
952 } else {
953 nCloneErrCnt++;
957 // #i13033#
958 // New mechanism to re-create the connections of cloned connectors
959 aCloneList.CopyConnections();
961 if(nCloneErrCnt)
963 #ifdef DBG_UTIL
964 OStringBuffer aStr("SdrEditView::CopyMarkedObj(): Error when cloning ");
966 if(nCloneErrCnt == 1)
968 aStr.append("a drawing object.");
970 else
972 aStr.append(OString::number(static_cast<sal_Int32>(nCloneErrCnt))
973 + " drawing objects.");
976 aStr.append(" This object's/These objects's connections will not be copied.");
977 OSL_FAIL(aStr.getStr());
978 #endif
980 MarkListHasChanged();
984 bool SdrEditView::InsertObjectAtView(SdrObject* pObj, SdrPageView& rPV, SdrInsertFlags nOptions)
986 if (nOptions & SdrInsertFlags::SETDEFLAYER) {
987 SdrLayerID nLayer=rPV.GetPage()->GetLayerAdmin().GetLayerID(maActualLayer);
988 if (nLayer==SDRLAYER_NOTFOUND) nLayer=SdrLayerID(0);
989 if (rPV.GetLockedLayers().IsSet(nLayer) || !rPV.GetVisibleLayers().IsSet(nLayer)) {
990 return false;
992 pObj->NbcSetLayer(nLayer);
994 if (nOptions & SdrInsertFlags::SETDEFATTR) {
995 if (mpDefaultStyleSheet!=nullptr) pObj->NbcSetStyleSheet(mpDefaultStyleSheet, false);
996 pObj->SetMergedItemSet(maDefaultAttr);
998 if (!pObj->IsInserted()) {
999 rPV.GetObjList()->InsertObject(pObj, SAL_MAX_SIZE);
1002 css::uno::Reference<lang::XServiceInfo> xServices(GetModel().getUnoModel(),
1003 css::uno::UNO_QUERY);
1004 if (xServices.is() && (xServices->supportsService(u"com.sun.star.sheet.SpreadsheetDocument"_ustr) ||
1005 xServices->supportsService(u"com.sun.star.text.TextDocument"_ustr)))
1007 const bool bUndo(IsUndoEnabled());
1008 GetModel().EnableUndo(false);
1009 pObj->MakeNameUnique();
1010 GetModel().EnableUndo(bUndo);
1013 if( IsUndoEnabled())
1015 bool bDontDeleteReally = true;
1016 EndTextEditCurrentView(bDontDeleteReally);
1017 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoNewObject(*pObj));
1020 if (!(nOptions & SdrInsertFlags::DONTMARK)) {
1021 if (!(nOptions & SdrInsertFlags::ADDMARK)) UnmarkAllObj();
1022 MarkObj(pObj,&rPV);
1024 return true;
1027 void SdrEditView::ReplaceObjectAtView(SdrObject* pOldObj, SdrPageView& rPV, SdrObject* pNewObj, bool bMark)
1029 if(IsTextEdit())
1031 #ifdef DBG_UTIL
1032 if(auto pTextObj = DynCastSdrTextObj(pOldObj))
1033 if (pTextObj->IsTextEditActive())
1034 OSL_ENSURE(false, "OldObject is in TextEdit mode, this has to be ended before replacing it using SdrEndTextEdit (!)");
1036 if(auto pTextObj = DynCastSdrTextObj(pNewObj))
1037 if (pTextObj->IsTextEditActive())
1038 OSL_ENSURE(false, "NewObject is in TextEdit mode, this has to be ended before replacing it using SdrEndTextEdit (!)");
1039 #endif
1041 // #i123468# emergency repair situation, needs to cast up to a class derived from
1042 // this one; (aw080 has a mechanism for that and the view hierarchy is secured to
1043 // always be a SdrView)
1044 SdrView *pSdrView = dynamic_cast<SdrView*>(this);
1045 if (pSdrView)
1046 pSdrView->SdrEndTextEdit();
1049 SdrObjList* pOL=pOldObj->getParentSdrObjListFromSdrObject();
1050 const bool bUndo = IsUndoEnabled();
1051 if( bUndo )
1052 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoReplaceObject(*pOldObj,*pNewObj));
1054 if( IsObjMarked( pOldObj ) )
1055 MarkObj( pOldObj, &rPV, true /*unmark!*/ );
1057 pOL->ReplaceObject(pNewObj,pOldObj->GetOrdNum());
1059 if (bMark) MarkObj(pNewObj,&rPV);
1063 bool SdrEditView::IsUndoEnabled() const
1065 return GetModel().IsUndoEnabled();
1068 void SdrEditView::EndTextEditAllViews() const
1070 GetModel().ForAllListeners(
1071 [](SfxListener* pListener)
1073 SdrObjEditView* pView = dynamic_cast<SdrObjEditView*>(pListener);
1074 if (pView && pView->IsTextEdit())
1075 pView->SdrEndTextEdit();
1076 return false;
1080 void SdrEditView::EndTextEditCurrentView(bool bDontDeleteReally)
1082 if (IsTextEdit())
1084 SdrView* pSdrView = dynamic_cast<SdrView*>(this);
1085 if (pSdrView)
1086 pSdrView->SdrEndTextEdit(bDontDeleteReally);
1090 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */