bump product version to 5.0.4.1
[LibreOffice.git] / svx / source / svdraw / svdedtv.cxx
blobc9a567a2914cc071d96f22b53bd26b46efc6c95f
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 <vcl/metaact.hxx>
21 #include <svx/svdedtv.hxx>
22 #include <svx/svdundo.hxx>
23 #include <svx/svdograf.hxx>
24 #include <svx/svdopath.hxx>
25 #include <svx/svdoole2.hxx>
26 #include <svx/svdopage.hxx>
27 #include <svx/svdoedge.hxx>
28 #include <svx/svdlayer.hxx>
29 #include <svx/svdpagv.hxx>
30 #include <svx/svdpage.hxx>
31 #include <svx/svdpoev.hxx>
32 #include "svx/svdstr.hrc"
33 #include "svdglob.hxx"
34 #include <svx/e3dsceneupdater.hxx>
35 #include <rtl/strbuf.hxx>
36 #include <svx/svdview.hxx>
37 #include <clonelist.hxx>
39 using namespace com::sun::star;
41 void SdrEditView::ImpResetPossibilityFlags()
43 bReadOnly =false;
45 bGroupPossible =false;
46 bUnGroupPossible =false;
47 bGrpEnterPossible =false;
48 bDeletePossible =false;
49 bToTopPossible =false;
50 bToBtmPossible =false;
51 bReverseOrderPossible =false;
53 bImportMtfPossible =false;
54 bCombinePossible =false;
55 bDismantlePossible =false;
56 bCombineNoPolyPolyPossible =false;
57 bDismantleMakeLinesPossible=false;
58 bOrthoDesiredOnMarked =false;
60 bMoreThanOneNotMovable =false;
61 bOneOrMoreMovable =false;
62 bMoreThanOneNoMovRot =false;
63 bContortionPossible =false;
64 bAllPolys =false;
65 bOneOrMorePolys =false;
66 bMoveAllowed =false;
67 bResizeFreeAllowed =false;
68 bResizePropAllowed =false;
69 bRotateFreeAllowed =false;
70 bRotate90Allowed =false;
71 bMirrorFreeAllowed =false;
72 bMirror45Allowed =false;
73 bMirror90Allowed =false;
74 bTransparenceAllowed =false;
75 bCropAllowed =false;
76 bGradientAllowed =false;
77 bShearAllowed =false;
78 bEdgeRadiusAllowed =false;
79 bCanConvToPath =false;
80 bCanConvToPoly =false;
81 bCanConvToContour =false;
82 bCanConvToPathLineToArea=false;
83 bCanConvToPolyLineToArea=false;
84 bMoveProtect =false;
85 bResizeProtect =false;
88 void SdrEditView::ImpClearVars()
90 ImpResetPossibilityFlags();
91 bPossibilitiesDirty=true; // << Purify didn't like this
92 bBundleVirtObj=false;
95 SdrEditView::SdrEditView(SdrModel* pModel1, OutputDevice* pOut):
96 SdrMarkView(pModel1,pOut)
98 ImpClearVars();
101 SdrEditView::~SdrEditView()
107 SdrLayer* SdrEditView::InsertNewLayer(const OUString& rName, sal_uInt16 nPos)
109 SdrLayerAdmin& rLA=pMod->GetLayerAdmin();
110 sal_uInt16 nMax=rLA.GetLayerCount();
111 if (nPos>nMax) nPos=nMax;
112 SdrLayer* pNewLayer=rLA.NewLayer(rName,nPos);
114 if( GetModel()->IsUndoEnabled() )
115 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewLayer(nPos,rLA,*pMod));
117 pMod->SetChanged();
118 return pNewLayer;
121 #include <svx/svdogrp.hxx>
122 #include <svx/scene3d.hxx>
124 bool SdrEditView::ImpDelLayerCheck(SdrObjList* pOL, SdrLayerID nDelID) const
126 bool bDelAll(true);
128 for(size_t nObjNum = pOL->GetObjCount(); nObjNum > 0 && bDelAll;)
130 nObjNum--;
131 SdrObject* pObj = pOL->GetObj(nObjNum);
132 SdrObjList* pSubOL = pObj->GetSubList();
134 // explicitly test for group objects and 3d scenes
135 if(pSubOL && (pObj->ISA(SdrObjGroup) || pObj->ISA(E3dScene)))
137 if(!ImpDelLayerCheck(pSubOL, nDelID))
139 bDelAll = false;
142 else
144 if(pObj->GetLayer() != nDelID)
146 bDelAll = false;
151 return bDelAll;
154 void SdrEditView::ImpDelLayerDelObjs(SdrObjList* pOL, SdrLayerID nDelID)
156 const size_t nObjAnz(pOL->GetObjCount());
157 // make sure OrdNums are correct
158 pOL->GetObj(0)->GetOrdNum();
160 const bool bUndo = GetModel()->IsUndoEnabled();
162 for(size_t nObjNum = nObjAnz; nObjNum > 0;)
164 nObjNum--;
165 SdrObject* pObj = pOL->GetObj(nObjNum);
166 SdrObjList* pSubOL = pObj->GetSubList();
169 // explicitly test for group objects and 3d scenes
170 if(pSubOL && (pObj->ISA(SdrObjGroup) || pObj->ISA(E3dScene)))
172 if(ImpDelLayerCheck(pSubOL, nDelID))
174 if( bUndo )
175 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true));
176 pOL->RemoveObject(nObjNum);
178 if( !bUndo )
179 SdrObject::Free( pObj );
181 else
183 ImpDelLayerDelObjs(pSubOL, nDelID);
186 else
188 if(pObj->GetLayer() == nDelID)
190 if( bUndo )
191 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true));
192 pOL->RemoveObject(nObjNum);
193 if( !bUndo )
194 SdrObject::Free( pObj );
200 void SdrEditView::DeleteLayer(const OUString& rName)
202 SdrLayerAdmin& rLA = pMod->GetLayerAdmin();
203 SdrLayer* pLayer = rLA.GetLayer(rName, true);
204 sal_uInt16 nLayerNum(rLA.GetLayerPos(pLayer));
206 if(SDRLAYER_NOTFOUND != nLayerNum)
209 SdrLayerID nDelID = pLayer->GetID();
211 const bool bUndo = IsUndoEnabled();
212 if( bUndo )
213 BegUndo(ImpGetResStr(STR_UndoDelLayer));
215 bool bMaPg(true);
217 for(sal_uInt16 nPageKind(0); nPageKind < 2; nPageKind++)
219 // MasterPages and DrawPages
220 sal_uInt16 nPgAnz(bMaPg ? pMod->GetMasterPageCount() : pMod->GetPageCount());
222 for(sal_uInt16 nPgNum(0); nPgNum < nPgAnz; nPgNum++)
224 // over all pages
225 SdrPage* pPage = (bMaPg) ? pMod->GetMasterPage(nPgNum) : pMod->GetPage(nPgNum);
226 const size_t nObjAnz(pPage->GetObjCount());
228 // make sure OrdNums are correct
229 if(nObjAnz)
230 pPage->GetObj(0)->GetOrdNum();
232 for(size_t nObjNum(nObjAnz); nObjNum > 0;)
234 nObjNum--;
235 SdrObject* pObj = pPage->GetObj(nObjNum);
236 SdrObjList* pSubOL = pObj->GetSubList();
238 // explicitly test for group objects and 3d scenes
239 if(pSubOL && (pObj->ISA(SdrObjGroup) || pObj->ISA(E3dScene)))
241 if(ImpDelLayerCheck(pSubOL, nDelID))
243 if( bUndo )
244 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true));
245 pPage->RemoveObject(nObjNum);
246 if( !bUndo )
247 SdrObject::Free(pObj);
249 else
251 ImpDelLayerDelObjs(pSubOL, nDelID);
254 else
256 if(pObj->GetLayer() == nDelID)
258 if( bUndo )
259 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true));
260 pPage->RemoveObject(nObjNum);
261 if( !bUndo )
262 SdrObject::Free(pObj);
267 bMaPg = false;
270 if( bUndo )
272 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteLayer(nLayerNum, rLA, *pMod));
273 rLA.RemoveLayer(nLayerNum);
274 EndUndo();
276 else
278 delete rLA.RemoveLayer(nLayerNum);
281 pMod->SetChanged();
287 void SdrEditView::EndUndo()
289 // #i13033#
290 // Comparison changed to 1L since EndUndo() is called later now
291 // and EndUndo WILL change count to count-1
292 if(1L == pMod->GetUndoBracketLevel())
294 ImpBroadcastEdgesOfMarkedNodes();
297 // #i13033#
298 // moved to bottom to still have access to UNDOs inside of
299 // ImpBroadcastEdgesOfMarkedNodes()
300 pMod->EndUndo();
303 void SdrEditView::ImpBroadcastEdgesOfMarkedNodes()
305 std::vector<SdrObject*>::const_iterator iterPos;
306 const std::vector<SdrObject*>& rAllMarkedObjects = GetTransitiveHullOfMarkedObjects();
308 // #i13033#
309 // New mechanism to search for necessary disconnections for
310 // changed connectors inside the transitive hull of all at
311 // the beginning of UNDO selected objects
312 for(sal_uInt32 a(0L); a < rAllMarkedObjects.size(); a++)
314 SdrEdgeObj* pEdge = PTR_CAST(SdrEdgeObj, rAllMarkedObjects[a]);
316 if(pEdge)
318 SdrObject* pObj1 = pEdge->GetConnectedNode(false);
319 SdrObject* pObj2 = pEdge->GetConnectedNode(true);
321 if(pObj1 && !pEdge->CheckNodeConnection(false))
323 iterPos = std::find(rAllMarkedObjects.begin(),rAllMarkedObjects.end(),pObj1);
325 if (iterPos == rAllMarkedObjects.end())
327 if( IsUndoEnabled() )
328 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pEdge));
329 pEdge->DisconnectFromNode(false);
333 if(pObj2 && !pEdge->CheckNodeConnection(true))
335 iterPos = std::find(rAllMarkedObjects.begin(),rAllMarkedObjects.end(),pObj2);
337 if (iterPos == rAllMarkedObjects.end())
339 if( IsUndoEnabled() )
340 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pEdge));
341 pEdge->DisconnectFromNode(true);
347 const size_t nMarkedEdgeAnz = GetMarkedEdgesOfMarkedNodes().GetMarkCount();
349 for (size_t i=0; i<nMarkedEdgeAnz; ++i) {
350 SdrMark* pEM = GetMarkedEdgesOfMarkedNodes().GetMark(i);
351 SdrObject* pEdgeTmp=pEM->GetMarkedSdrObj();
352 SdrEdgeObj* pEdge=PTR_CAST(SdrEdgeObj,pEdgeTmp);
353 if (pEdge!=NULL) {
354 pEdge->SetEdgeTrackDirty();
360 // Possibilities
363 void SdrEditView::MarkListHasChanged()
365 SdrMarkView::MarkListHasChanged();
366 bPossibilitiesDirty=true;
369 void SdrEditView::ModelHasChanged()
371 SdrMarkView::ModelHasChanged();
372 bPossibilitiesDirty=true;
375 bool SdrEditView::IsResizeAllowed(bool bProp) const
377 ForcePossibilities();
378 if (bResizeProtect) return false;
379 if (bProp) return bResizePropAllowed;
380 return bResizeFreeAllowed;
383 bool SdrEditView::IsRotateAllowed(bool b90Deg) const
385 ForcePossibilities();
386 if (bMoveProtect) return false;
387 if (b90Deg) return bRotate90Allowed;
388 return bRotateFreeAllowed;
391 bool SdrEditView::IsMirrorAllowed(bool b45Deg, bool b90Deg) const
393 ForcePossibilities();
394 if (bMoveProtect) return false;
395 if (b90Deg) return bMirror90Allowed;
396 if (b45Deg) return bMirror45Allowed;
397 return bMirrorFreeAllowed && !bMoveProtect;
400 bool SdrEditView::IsTransparenceAllowed() const
402 ForcePossibilities();
403 return bTransparenceAllowed;
406 bool SdrEditView::IsCropAllowed() const
408 ForcePossibilities();
409 return bCropAllowed;
412 bool SdrEditView::IsGradientAllowed() const
414 ForcePossibilities();
415 return bGradientAllowed;
418 bool SdrEditView::IsShearAllowed() const
420 ForcePossibilities();
421 if (bResizeProtect) return false;
422 return bShearAllowed;
425 bool SdrEditView::IsEdgeRadiusAllowed() const
427 ForcePossibilities();
428 return bEdgeRadiusAllowed;
431 bool SdrEditView::IsCrookAllowed(bool bNoContortion) const
433 // CrookMode missing here (no rotations allowed when shearing ...)
434 ForcePossibilities();
435 if (bNoContortion) {
436 if (!bRotateFreeAllowed) return false;
437 return !bMoveProtect && bMoveAllowed;
438 } else {
439 return !bResizeProtect && bContortionPossible;
443 bool SdrEditView::IsDistortAllowed(bool bNoContortion) const
445 ForcePossibilities();
446 if (bNoContortion) {
447 return false;
448 } else {
449 return !bResizeProtect && bContortionPossible;
453 bool SdrEditView::IsCombinePossible(bool bNoPolyPoly) const
455 ForcePossibilities();
456 if (bNoPolyPoly) return bCombineNoPolyPolyPossible;
457 else return bCombinePossible;
460 bool SdrEditView::IsDismantlePossible(bool bMakeLines) const
462 ForcePossibilities();
463 if (bMakeLines) return bDismantleMakeLinesPossible;
464 else return bDismantlePossible;
467 void SdrEditView::CheckPossibilities()
469 if (bSomeObjChgdFlag) bPossibilitiesDirty=true;
471 if(bSomeObjChgdFlag)
473 // This call IS necessary to correct the MarkList, in which
474 // no longer to the model belonging objects still can reside.
475 // These ones need to be removed.
476 CheckMarked();
479 if (bPossibilitiesDirty) {
480 ImpResetPossibilityFlags();
481 SortMarkedObjects();
482 const size_t nMarkCount=GetMarkedObjectCount();
483 if (nMarkCount!=0) {
484 bReverseOrderPossible=nMarkCount>=2;
486 size_t nMovableCount=0;
487 bGroupPossible=nMarkCount>=2;
488 bCombinePossible=nMarkCount>=2;
489 if (nMarkCount==1) {
490 // check bCombinePossible more thoroughly
491 // still missing ...
492 const SdrObject* pObj=GetMarkedObjectByIndex(0);
493 //const SdrPathObj* pPath=PTR_CAST(SdrPathObj,pObj);
494 bool bGroup=pObj->GetSubList()!=NULL;
495 bool bHasText=pObj->GetOutlinerParaObject()!=NULL;
496 if (bGroup || bHasText) {
497 bCombinePossible=true;
500 bCombineNoPolyPolyPossible=bCombinePossible;
501 bDeletePossible=true;
502 // accept transformations for now
503 bMoveAllowed =true;
504 bResizeFreeAllowed=true;
505 bResizePropAllowed=true;
506 bRotateFreeAllowed=true;
507 bRotate90Allowed =true;
508 bMirrorFreeAllowed=true;
509 bMirror45Allowed =true;
510 bMirror90Allowed =true;
511 bShearAllowed =true;
512 bEdgeRadiusAllowed=false;
513 bContortionPossible=true;
514 bCanConvToContour = true;
516 // these ones are only allowed when single object is selected
517 bTransparenceAllowed = (nMarkCount == 1);
518 bGradientAllowed = (nMarkCount == 1);
519 bCropAllowed = (nMarkCount == 1);
520 if(bGradientAllowed)
522 // gradient depends on fill style
523 const SdrMark* pM = GetSdrMarkByIndex(0);
524 const SdrObject* pObj = pM->GetMarkedSdrObj();
526 // may be group object, so get merged ItemSet
527 const SfxItemSet& rSet = pObj->GetMergedItemSet();
528 SfxItemState eState = rSet.GetItemState(XATTR_FILLSTYLE, false);
530 if(SfxItemState::DONTCARE != eState)
532 // If state is not DONTCARE, test the item
533 drawing::FillStyle eFillStyle = static_cast<const XFillStyleItem&>(rSet.Get(XATTR_FILLSTYLE)).GetValue();
535 if(eFillStyle != drawing::FillStyle_GRADIENT)
537 bGradientAllowed = false;
542 bool bNoMovRotFound=false;
543 const SdrPageView* pPV0=NULL;
545 for (size_t nm=0; nm<nMarkCount; ++nm) {
546 const SdrMark* pM=GetSdrMarkByIndex(nm);
547 const SdrObject* pObj=pM->GetMarkedSdrObj();
548 const SdrPageView* pPV=pM->GetPageView();
549 if (pPV!=pPV0) {
550 if (pPV->IsReadOnly()) bReadOnly=true;
551 pPV0=pPV;
554 SdrObjTransformInfoRec aInfo;
555 pObj->TakeObjInfo(aInfo);
556 bool bMovPrt=pObj->IsMoveProtect();
557 bool bSizPrt=pObj->IsResizeProtect();
558 if (!bMovPrt && aInfo.bMoveAllowed) nMovableCount++; // count MovableObjs
559 if (bMovPrt) bMoveProtect=true;
560 if (bSizPrt) bResizeProtect=true;
562 // not allowed when not allowed at one object
563 if(!aInfo.bTransparenceAllowed)
564 bTransparenceAllowed = false;
566 // If one of these can't do something, none can
567 if (!aInfo.bMoveAllowed ) bMoveAllowed =false;
568 if (!aInfo.bResizeFreeAllowed) bResizeFreeAllowed=false;
569 if (!aInfo.bResizePropAllowed) bResizePropAllowed=false;
570 if (!aInfo.bRotateFreeAllowed) bRotateFreeAllowed=false;
571 if (!aInfo.bRotate90Allowed ) bRotate90Allowed =false;
572 if (!aInfo.bMirrorFreeAllowed) bMirrorFreeAllowed=false;
573 if (!aInfo.bMirror45Allowed ) bMirror45Allowed =false;
574 if (!aInfo.bMirror90Allowed ) bMirror90Allowed =false;
575 if (!aInfo.bShearAllowed ) bShearAllowed =false;
576 if (aInfo.bEdgeRadiusAllowed) bEdgeRadiusAllowed=true;
577 if (aInfo.bNoContortion ) bContortionPossible=false;
578 // For Crook with Contortion: all objects have to be
579 // Movable and Rotatable, except for a maximum of 1 of them
580 if (!bMoreThanOneNoMovRot) {
581 if (!aInfo.bMoveAllowed || !aInfo.bResizeFreeAllowed) {
582 bMoreThanOneNoMovRot=bNoMovRotFound;
583 bNoMovRotFound=true;
587 // Must be resizeable to allow cropping
588 if (!aInfo.bResizeFreeAllowed && !aInfo.bResizePropAllowed)
589 bCropAllowed = false;
591 // if one member cannot be converted, no conversion is possible
592 if(!aInfo.bCanConvToContour)
593 bCanConvToContour = false;
595 // Ungroup
596 if (!bUnGroupPossible) bUnGroupPossible=pObj->GetSubList()!=NULL;
597 // ConvertToCurve: If at least one can be converted, that is fine.
598 if (aInfo.bCanConvToPath ) bCanConvToPath =true;
599 if (aInfo.bCanConvToPoly ) bCanConvToPoly =true;
600 if (aInfo.bCanConvToPathLineToArea) bCanConvToPathLineToArea=true;
601 if (aInfo.bCanConvToPolyLineToArea) bCanConvToPolyLineToArea=true;
603 // Combine/Dismantle
604 if(bCombinePossible)
606 bCombinePossible = ImpCanConvertForCombine(pObj);
607 bCombineNoPolyPolyPossible = bCombinePossible;
610 if (!bDismantlePossible) bDismantlePossible = ImpCanDismantle(pObj, false);
611 if (!bDismantleMakeLinesPossible) bDismantleMakeLinesPossible = ImpCanDismantle(pObj, true);
612 // check OrthoDesiredOnMarked
613 if (!bOrthoDesiredOnMarked && !aInfo.bNoOrthoDesired) bOrthoDesiredOnMarked=true;
614 // check ImportMtf
616 if (!bImportMtfPossible)
618 const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(pObj);
619 const SdrOle2Obj* pSdrOle2Obj = dynamic_cast< const SdrOle2Obj* >(pObj);
621 if(pSdrGrafObj && ((pSdrGrafObj->HasGDIMetaFile() && !pSdrGrafObj->IsEPS()) || pSdrGrafObj->isEmbeddedSvg()))
623 bImportMtfPossible = true;
626 if(pSdrOle2Obj)
628 bImportMtfPossible = pSdrOle2Obj->GetObjRef().is();
633 bMoreThanOneNotMovable=nMovableCount<nMarkCount-1;
634 bOneOrMoreMovable=nMovableCount!=0;
635 bGrpEnterPossible=bUnGroupPossible;
637 ImpCheckToTopBtmPossible();
638 static_cast<SdrPolyEditView*>(this)->ImpCheckPolyPossibilities();
639 bPossibilitiesDirty=false;
641 if (bReadOnly) {
642 bool bMerker1=bGrpEnterPossible;
643 ImpResetPossibilityFlags();
644 bReadOnly=true;
645 bGrpEnterPossible=bMerker1;
647 if (bMoveAllowed) {
648 // Don't allow moving glued connectors.
649 // Currently only implemented for single selection.
650 if (nMarkCount==1) {
651 SdrObject* pObj=GetMarkedObjectByIndex(0);
652 SdrEdgeObj* pEdge=PTR_CAST(SdrEdgeObj,pObj);
653 if (pEdge!=NULL) {
654 SdrObject* pNode1=pEdge->GetConnectedNode(true);
655 SdrObject* pNode2=pEdge->GetConnectedNode(false);
656 if (pNode1!=NULL || pNode2!=NULL) bMoveAllowed=false;
665 void SdrEditView::ForceMarkedObjToAnotherPage()
667 bool bFlg=false;
668 for (size_t nm=0; nm<GetMarkedObjectCount(); ++nm) {
669 SdrMark* pM=GetSdrMarkByIndex(nm);
670 SdrObject* pObj=pM->GetMarkedSdrObj();
671 Rectangle aObjRect(pObj->GetCurrentBoundRect());
672 Rectangle aPgRect(pM->GetPageView()->GetPageRect());
673 if (!aObjRect.IsOver(aPgRect)) {
674 bool bFnd=false;
675 SdrPageView* pPV = GetSdrPageView();
677 if(pPV)
679 bFnd = aObjRect.IsOver(pPV->GetPageRect());
682 if(bFnd)
684 pM->GetPageView()->GetObjList()->RemoveObject(pObj->GetOrdNum());
685 SdrInsertReason aReason(SDRREASON_VIEWCALL);
686 pPV->GetObjList()->InsertObject(pObj, SAL_MAX_SIZE, &aReason);
687 pM->SetPageView(pPV);
688 InvalidateAllWin(aObjRect);
689 bFlg=true;
693 if (bFlg) {
694 MarkListHasChanged();
698 void SdrEditView::DeleteMarkedList(const SdrMarkList& rMark)
700 if (rMark.GetMarkCount()!=0)
702 rMark.ForceSort();
704 const bool bUndo = IsUndoEnabled();
705 if( bUndo )
706 BegUndo();
707 const size_t nMarkCount(rMark.GetMarkCount());
709 if(nMarkCount)
711 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
713 if( bUndo )
715 for(size_t nm = nMarkCount; nm > 0;)
717 --nm;
718 SdrMark* pM = rMark.GetMark(nm);
719 SdrObject* pObj = pM->GetMarkedSdrObj();
721 // extra undo actions for changed connector which now may hold its laid out path (SJ)
722 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pObj ) );
723 AddUndoActions( vConnectorUndoActions );
725 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj));
729 // make sure, OrderNums are correct:
730 rMark.GetMark(0)->GetMarkedSdrObj()->GetOrdNum();
732 std::vector< SdrObject* > aRemoved3DObjects;
734 for(size_t nm = nMarkCount; nm > 0;)
736 --nm;
737 SdrMark* pM = rMark.GetMark(nm);
738 SdrObject* pObj = pM->GetMarkedSdrObj();
739 SdrObjList* pOL = pObj->GetObjList();
740 const size_t nOrdNum(pObj->GetOrdNumDirect());
742 bool bIs3D = dynamic_cast< E3dObject* >(pObj);
743 // set up a scene updater if object is a 3d object
744 if(bIs3D)
746 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pObj));
749 pOL->RemoveObject(nOrdNum);
751 if( !bUndo )
753 if( bIs3D )
754 aRemoved3DObjects.push_back( pObj ); // may be needed later
755 else
756 SdrObject::Free(pObj);
760 // fire scene updaters
761 while(!aUpdaters.empty())
763 delete aUpdaters.back();
764 aUpdaters.pop_back();
767 if( !bUndo )
769 // now delete removed scene objects
770 while(!aRemoved3DObjects.empty())
772 SdrObject::Free( aRemoved3DObjects.back() );
773 aRemoved3DObjects.pop_back();
778 if( bUndo )
779 EndUndo();
783 void SdrEditView::DeleteMarkedObj()
785 // #i110981# return when nothing is to be done at all
786 if(!GetMarkedObjectCount())
788 return;
791 // moved breaking action and undo start outside loop
792 BrkAction();
793 BegUndo(ImpGetResStr(STR_EditDelete),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_DELETE);
795 // remove as long as something is selected. This allows to schedule objects for
796 // removal for a next run as needed
797 while(GetMarkedObjectCount())
799 // vector to remember the parents which may be empty after object removal
800 std::vector< SdrObject* > aParents;
803 const SdrMarkList& rMarkList = GetMarkedObjectList();
804 const size_t nCount(rMarkList.GetMarkCount());
806 for(size_t a = 0; a < nCount; ++a)
808 // in the first run, add all found parents, but only once
809 SdrMark* pMark = rMarkList.GetMark(a);
810 SdrObject* pObject = pMark->GetMarkedSdrObj();
811 SdrObject* pParent = pObject->GetObjList()->GetOwnerObj();
813 if(pParent)
815 if(!aParents.empty())
817 std::vector< SdrObject* >::iterator aFindResult =
818 std::find(aParents.begin(), aParents.end(), pParent);
820 if(aFindResult == aParents.end())
822 aParents.push_back(pParent);
825 else
827 aParents.push_back(pParent);
832 if(!aParents.empty())
834 // in a 2nd run, remove all objects which may already be scheduled for
835 // removal. I am not sure if this can happen, but theoretically
836 // a to-be-removed object may already be the group/3DScene itself
837 for(size_t a = 0; a < nCount; ++a)
839 SdrMark* pMark = rMarkList.GetMark(a);
840 SdrObject* pObject = pMark->GetMarkedSdrObj();
842 std::vector< SdrObject* >::iterator aFindResult =
843 std::find(aParents.begin(), aParents.end(), pObject);
845 if(aFindResult != aParents.end())
847 aParents.erase(aFindResult);
853 // original stuff: remove selected objects. Handle clear will
854 // do something only once
855 DeleteMarkedList(GetMarkedObjectList());
856 GetMarkedObjectListWriteAccess().Clear();
857 maHdlList.Clear();
859 while(aParents.size() && !GetMarkedObjectCount())
861 // iterate over remembered parents
862 SdrObject* pParent = aParents.back();
863 aParents.pop_back();
865 if(pParent->GetSubList() && 0 == pParent->GetSubList()->GetObjCount())
867 // we detected an empty parent, a candidate to leave group/3DScene
868 // if entered
869 if(GetSdrPageView()->GetAktGroup()
870 && GetSdrPageView()->GetAktGroup() == pParent)
872 GetSdrPageView()->LeaveOneGroup();
875 // schedule empty parent for removal
876 GetMarkedObjectListWriteAccess().InsertEntry(
877 SdrMark(pParent, GetSdrPageView()));
882 // end undo and change messaging moved at the end
883 EndUndo();
884 MarkListHasChanged();
887 void SdrEditView::CopyMarkedObj()
889 SortMarkedObjects();
891 SdrMarkList aSourceObjectsForCopy(GetMarkedObjectList());
892 // The following loop is used instead of MarkList::Merge(), to be
893 // able to flag the MarkEntries.
894 const size_t nEdgeAnz = GetEdgesOfMarkedNodes().GetMarkCount();
895 for (size_t nEdgeNum=0; nEdgeNum<nEdgeAnz; ++nEdgeNum) {
896 SdrMark aM(*GetEdgesOfMarkedNodes().GetMark(nEdgeNum));
897 aM.SetUser(1);
898 aSourceObjectsForCopy.InsertEntry(aM);
900 aSourceObjectsForCopy.ForceSort();
902 // #i13033#
903 // New mechanism to re-create the connections of cloned connectors
904 CloneList aCloneList;
906 const bool bUndo = IsUndoEnabled();
908 GetMarkedObjectListWriteAccess().Clear();
909 size_t nCloneErrCnt=0;
910 const size_t nMarkCount=aSourceObjectsForCopy.GetMarkCount();
911 for (size_t nm=0; nm<nMarkCount; ++nm) {
912 SdrMark* pM=aSourceObjectsForCopy.GetMark(nm);
913 SdrObject* pO=pM->GetMarkedSdrObj()->Clone();
914 if (pO!=NULL) {
915 SdrInsertReason aReason(SDRREASON_VIEWCALL);
916 pM->GetPageView()->GetObjList()->InsertObject(pO, SAL_MAX_SIZE, &aReason);
918 if( bUndo )
919 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoCopyObject(*pO));
921 SdrMark aME(*pM);
922 aME.SetMarkedSdrObj(pO);
923 aCloneList.AddPair(pM->GetMarkedSdrObj(), pO);
925 if (pM->GetUser()==0)
927 // otherwise it is only an Edge we have to copy as well
928 GetMarkedObjectListWriteAccess().InsertEntry(aME);
930 } else {
931 nCloneErrCnt++;
935 // #i13033#
936 // New mechanism to re-create the connections of cloned connectors
937 aCloneList.CopyConnections();
939 if(nCloneErrCnt)
941 #ifdef DBG_UTIL
942 OStringBuffer aStr("SdrEditView::CopyMarkedObj(): Error when cloning ");
944 if(nCloneErrCnt == 1)
946 aStr.append("a drawing object.");
948 else
950 aStr.append(static_cast<sal_Int32>(nCloneErrCnt));
951 aStr.append(" drawing objects.");
954 aStr.append(" This object's/These objects's connections will not be copied.");
955 OSL_FAIL(aStr.getStr());
956 #endif
958 MarkListHasChanged();
963 bool SdrEditView::InsertObjectAtView(SdrObject* pObj, SdrPageView& rPV, SdrInsertFlags nOptions)
965 if (nOptions & SdrInsertFlags::SETDEFLAYER) {
966 SdrLayerID nLayer=rPV.GetPage()->GetLayerAdmin().GetLayerID(aAktLayer,true);
967 if (nLayer==SDRLAYER_NOTFOUND) nLayer=0;
968 if (rPV.GetLockedLayers().IsSet(nLayer) || !rPV.GetVisibleLayers().IsSet(nLayer)) {
969 SdrObject::Free( pObj ); // Layer locked or invisible
970 return false;
972 pObj->NbcSetLayer(nLayer);
974 if (nOptions & SdrInsertFlags::SETDEFATTR) {
975 if (pDefaultStyleSheet!=NULL) pObj->NbcSetStyleSheet(pDefaultStyleSheet, false);
976 pObj->SetMergedItemSet(aDefaultAttr);
978 if (!pObj->IsInserted()) {
979 SdrInsertReason aReason(SDRREASON_VIEWCALL);
980 if (nOptions & SdrInsertFlags::NOBROADCAST) {
981 rPV.GetObjList()->NbcInsertObject(pObj, SAL_MAX_SIZE, &aReason);
982 } else {
983 rPV.GetObjList()->InsertObject(pObj, SAL_MAX_SIZE, &aReason);
986 if( IsUndoEnabled() )
987 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pObj));
989 if (!(nOptions & SdrInsertFlags::DONTMARK)) {
990 if (!(nOptions & SdrInsertFlags::ADDMARK)) UnmarkAllObj();
991 MarkObj(pObj,&rPV);
993 return true;
996 void SdrEditView::ReplaceObjectAtView(SdrObject* pOldObj, SdrPageView& rPV, SdrObject* pNewObj, bool bMark)
998 if(IsTextEdit())
1000 #ifdef DBG_UTIL
1001 if(dynamic_cast< SdrTextObj* >(pOldObj) && static_cast< SdrTextObj* >(pOldObj)->IsTextEditActive())
1003 OSL_ENSURE(false, "OldObject is in TextEdit mode, this has to be ended before replacing it usnig SdrEndTextEdit (!)");
1006 if(dynamic_cast< SdrTextObj* >(pNewObj) && static_cast< SdrTextObj* >(pNewObj)->IsTextEditActive())
1008 OSL_ENSURE(false, "NewObject is in TextEdit mode, this has to be ended before replacing it usnig SdrEndTextEdit (!)");
1010 #endif
1012 // #i123468# emergency repair situation, needs to cast up to a class derived from
1013 // this one; (aw080 has a mechanism for that and the view hierarchy is secured to
1014 // always be a SdrView)
1015 SdrView *pSdrView = dynamic_cast<SdrView*>(this);
1016 if (pSdrView)
1017 pSdrView->SdrEndTextEdit();
1020 SdrObjList* pOL=pOldObj->GetObjList();
1021 const bool bUndo = IsUndoEnabled();
1022 if( bUndo )
1023 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoReplaceObject(*pOldObj,*pNewObj));
1025 if( IsObjMarked( pOldObj ) )
1026 MarkObj( pOldObj, &rPV, true /*unmark!*/ );
1028 pOL->ReplaceObject(pNewObj,pOldObj->GetOrdNum());
1030 if( !bUndo )
1031 SdrObject::Free( pOldObj );
1033 if (bMark) MarkObj(pNewObj,&rPV);
1038 bool SdrEditView::IsUndoEnabled() const
1040 return pMod->IsUndoEnabled();
1043 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */