1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
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()
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)
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
146 for(size_t nObjNum
= pOL
->GetObjCount(); nObjNum
> 0 && bDelAll
;)
149 SdrObject
* pObj
= pOL
->GetObj(nObjNum
);
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
))
163 if(pObj
->GetLayer() != nDelID
)
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;)
184 SdrObject
* pObj
= pOL
->GetObj(nObjNum
);
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
))
195 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteObject(*pObj
, true));
196 pOL
->RemoveObject(nObjNum
);
200 ImpDelLayerDelObjs(pSubOL
, nDelID
);
205 if(pObj
->GetLayer() == nDelID
)
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
);
223 sal_uInt16
nLayerNum(rLA
.GetLayerPos(pLayer
));
224 SdrLayerID nDelID
= pLayer
->GetID();
226 const bool bUndo
= IsUndoEnabled();
228 BegUndo(SvxResId(STR_UndoDelLayer
));
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
++)
240 SdrPage
* pPage
= bMaPg
? GetModel().GetMasterPage(nPgNum
) : GetModel().GetPage(nPgNum
);
241 const size_t nObjCount(pPage
->GetObjCount());
243 // make sure OrdNums are correct
245 pPage
->GetObj(0)->GetOrdNum();
247 for(size_t nObjNum(nObjCount
); nObjNum
> 0;)
250 SdrObject
* pObj
= pPage
->GetObj(nObjNum
);
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
))
260 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteObject(*pObj
, true));
261 pPage
->RemoveObject(nObjNum
);
265 ImpDelLayerDelObjs(pSubOL
, nDelID
);
270 if(pObj
->GetLayer() == nDelID
)
273 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteObject(*pObj
, true));
274 pPage
->RemoveObject(nObjNum
);
284 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteLayer(nLayerNum
, rLA
, GetModel()));
285 // coverity[leaked_storage] - ownership transferred to UndoDeleteLayer
286 rLA
.RemoveLayer(nLayerNum
).release();
291 rLA
.RemoveLayer(nLayerNum
);
294 GetModel().SetChanged();
298 void SdrEditView::EndUndo()
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();
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();
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
] );
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();
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();
447 if (!m_bRotateFreeAllowed
) return false;
448 return !m_bMoveProtect
&& m_bMoveAllowed
;
450 return !m_bResizeProtect
&& m_bContortionPossible
;
454 bool SdrEditView::IsDistortAllowed(bool bNoContortion
) const
456 ForcePossibilities();
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.
490 if (!m_bPossibilitiesDirty
)
493 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
494 ImpResetPossibilityFlags();
495 rMarkList
.ForceSort();
496 const size_t nMarkCount
= rMarkList
.GetMarkCount();
499 m_bReverseOrderPossible
= (nMarkCount
>= 2);
501 size_t nMovableCount
=0;
502 m_bGroupPossible
=nMarkCount
>=2;
503 m_bCombinePossible
=nMarkCount
>=2;
506 // check bCombinePossible more thoroughly
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();
565 if (pPV
->IsReadOnly()) m_bReadOnly
=true;
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
;
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;
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;
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;
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
);
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();
660 m_bGrpEnterPossible
=bTemp
;
662 if (!m_bMoveAllowed
) return;
664 // Don't allow moving glued connectors.
665 // Currently only implemented for single selection.
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();
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
)) {
698 SdrPageView
* pPV
= GetSdrPageView();
702 bFnd
= aObjRect
.Overlaps(pPV
->GetPageRect());
707 pM
->GetPageView()->GetObjList()->RemoveObject(pObj
->GetOrdNum());
708 pPV
->GetObjList()->InsertObject(pObj
, SAL_MAX_SIZE
);
709 pM
->SetPageView(pPV
);
710 InvalidateAllWin(aObjRect
);
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)
727 const bool bUndo
= IsUndoEnabled();
730 const size_t nMarkCount(rMark
.GetMarkCount());
734 std::vector
< E3DModifySceneSnapRectUpdater
* > aUpdaters
;
738 for(size_t nm
= nMarkCount
; nm
> 0;)
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;)
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
766 aUpdaters
.push_back(new E3DModifySceneSnapRectUpdater(pObj
));
771 // tdf#108863 and tdf#108889 don't delete objects before EndUndo()
775 pOL
->RemoveObject(nOrdNum
);
778 // fire scene updaters
779 while(!aUpdaters
.empty())
781 delete aUpdaters
.back();
782 aUpdaters
.pop_back();
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())
808 // moved breaking action and undo start outside loop
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());
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
);
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();
877 while(!aParents
.empty() && !rMarkList
.GetMarkCount())
879 // iterate over remembered parents
880 SdrObject
* pParent
= aParents
.back();
883 if(pParent
->GetSubList() && 0 == pParent
->GetSubList()->GetObjCount())
885 // we detected an empty parent, a candidate to leave group/3DScene
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
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
));
919 aSourceObjectsForCopy
.InsertEntry(aM
);
921 aSourceObjectsForCopy
.ForceSort();
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()));
938 pM
->GetPageView()->GetObjList()->InsertObjectThenMakeNameUnique(pO
.get(), aNameSet
);
941 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoCopyObject(*pO
));
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
);
958 // New mechanism to re-create the connections of cloned connectors
959 aCloneList
.CopyConnections();
964 OStringBuffer
aStr("SdrEditView::CopyMarkedObj(): Error when cloning ");
966 if(nCloneErrCnt
== 1)
968 aStr
.append("a drawing object.");
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());
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
)) {
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();
1027 void SdrEditView::ReplaceObjectAtView(SdrObject
* pOldObj
, SdrPageView
& rPV
, SdrObject
* pNewObj
, bool bMark
)
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 (!)");
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);
1046 pSdrView
->SdrEndTextEdit();
1049 SdrObjList
* pOL
=pOldObj
->getParentSdrObjListFromSdrObject();
1050 const bool bUndo
= IsUndoEnabled();
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();
1080 void SdrEditView::EndTextEditCurrentView(bool bDontDeleteReally
)
1084 SdrView
* pSdrView
= dynamic_cast<SdrView
*>(this);
1086 pSdrView
->SdrEndTextEdit(bDontDeleteReally
);
1090 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */