1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
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/strings.hrc>
33 #include <svx/dialmgr.hxx>
34 #include <svx/e3dsceneupdater.hxx>
35 #include <rtl/strbuf.hxx>
36 #include <svx/svdview.hxx>
37 #include <clonelist.hxx>
38 #include <svx/svdogrp.hxx>
39 #include <svx/scene3d.hxx>
40 #include <svx/xfillit0.hxx>
41
42
43 using namespace com::sun::star;
44
ImpResetPossibilityFlags()45 void SdrEditView::ImpResetPossibilityFlags()
46 {
47 m_bReadOnly =false;
48
49 m_bGroupPossible =false;
50 m_bUnGroupPossible =false;
51 m_bGrpEnterPossible =false;
52 m_bToTopPossible =false;
53 m_bToBtmPossible =false;
54 m_bReverseOrderPossible =false;
55
56 m_bImportMtfPossible =false;
57 m_bCombinePossible =false;
58 m_bDismantlePossible =false;
59 m_bCombineNoPolyPolyPossible =false;
60 m_bDismantleMakeLinesPossible=false;
61 m_bOrthoDesiredOnMarked =false;
62
63 m_bOneOrMoreMovable =false;
64 m_bMoreThanOneNoMovRot =false;
65 m_bContortionPossible =false;
66 m_bMoveAllowed =false;
67 m_bResizeFreeAllowed =false;
68 m_bResizePropAllowed =false;
69 m_bRotateFreeAllowed =false;
70 m_bRotate90Allowed =false;
71 m_bMirrorFreeAllowed =false;
72 m_bMirror45Allowed =false;
73 m_bMirror90Allowed =false;
74 m_bTransparenceAllowed =false;
75 m_bCropAllowed =false;
76 m_bGradientAllowed =false;
77 m_bShearAllowed =false;
78 m_bEdgeRadiusAllowed =false;
79 m_bCanConvToPath =false;
80 m_bCanConvToPoly =false;
81 m_bCanConvToContour =false;
82 m_bMoveProtect =false;
83 m_bResizeProtect =false;
84 }
85
ImpClearVars()86 void SdrEditView::ImpClearVars()
87 {
88 ImpResetPossibilityFlags();
89 m_bPossibilitiesDirty=true; // << Purify didn't like this
90 }
91
SdrEditView(SdrModel & rSdrModel,OutputDevice * pOut)92 SdrEditView::SdrEditView(
93 SdrModel& rSdrModel,
94 OutputDevice* pOut)
95 : SdrMarkView(rSdrModel, pOut)
96 {
97 ImpClearVars();
98 }
99
~SdrEditView()100 SdrEditView::~SdrEditView()
101 {
102 }
103
InsertNewLayer(const OUString & rName,sal_uInt16 nPos)104 void SdrEditView::InsertNewLayer(const OUString& rName, sal_uInt16 nPos)
105 {
106 SdrLayerAdmin& rLA=mpModel->GetLayerAdmin();
107 sal_uInt16 nMax=rLA.GetLayerCount();
108 if (nPos>nMax) nPos=nMax;
109 rLA.NewLayer(rName,nPos);
110
111 if( GetModel()->IsUndoEnabled() )
112 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewLayer(nPos,rLA,*mpModel));
113
114 mpModel->SetChanged();
115 }
116
ImpDelLayerCheck(SdrObjList const * pOL,SdrLayerID nDelID) const117 bool SdrEditView::ImpDelLayerCheck(SdrObjList const * pOL, SdrLayerID nDelID) const
118 {
119 bool bDelAll(true);
120
121 for(size_t nObjNum = pOL->GetObjCount(); nObjNum > 0 && bDelAll;)
122 {
123 nObjNum--;
124 SdrObject* pObj = pOL->GetObj(nObjNum);
125 SdrObjList* pSubOL = pObj->GetSubList();
126
127 // explicitly test for group objects and 3d scenes
128 if(pSubOL && (dynamic_cast<const SdrObjGroup*>(pObj) != nullptr || dynamic_cast< const E3dScene* >(pObj) != nullptr))
129 {
130 if(!ImpDelLayerCheck(pSubOL, nDelID))
131 {
132 bDelAll = false;
133 }
134 }
135 else
136 {
137 if(pObj->GetLayer() != nDelID)
138 {
139 bDelAll = false;
140 }
141 }
142 }
143
144 return bDelAll;
145 }
146
ImpDelLayerDelObjs(SdrObjList * pOL,SdrLayerID nDelID)147 void SdrEditView::ImpDelLayerDelObjs(SdrObjList* pOL, SdrLayerID nDelID)
148 {
149 const size_t nObjCount(pOL->GetObjCount());
150 // make sure OrdNums are correct
151 pOL->GetObj(0)->GetOrdNum();
152
153 const bool bUndo = GetModel()->IsUndoEnabled();
154
155 for(size_t nObjNum = nObjCount; nObjNum > 0;)
156 {
157 nObjNum--;
158 SdrObject* pObj = pOL->GetObj(nObjNum);
159 SdrObjList* pSubOL = pObj->GetSubList();
160
161
162 // explicitly test for group objects and 3d scenes
163 if(pSubOL && (dynamic_cast<const SdrObjGroup*>( pObj) != nullptr || dynamic_cast<const E3dScene* >(pObj) != nullptr))
164 {
165 if(ImpDelLayerCheck(pSubOL, nDelID))
166 {
167 if( bUndo )
168 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true));
169 pOL->RemoveObject(nObjNum);
170
171 if( !bUndo )
172 SdrObject::Free( pObj );
173 }
174 else
175 {
176 ImpDelLayerDelObjs(pSubOL, nDelID);
177 }
178 }
179 else
180 {
181 if(pObj->GetLayer() == nDelID)
182 {
183 if( bUndo )
184 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true));
185 pOL->RemoveObject(nObjNum);
186 if( !bUndo )
187 SdrObject::Free( pObj );
188 }
189 }
190 }
191 }
192
DeleteLayer(const OUString & rName)193 void SdrEditView::DeleteLayer(const OUString& rName)
194 {
195 SdrLayerAdmin& rLA = mpModel->GetLayerAdmin();
196 SdrLayer* pLayer = rLA.GetLayer(rName);
197
198 if(pLayer)
199 {
200 sal_uInt16 nLayerNum(rLA.GetLayerPos(pLayer));
201 SdrLayerID nDelID = pLayer->GetID();
202
203 const bool bUndo = IsUndoEnabled();
204 if( bUndo )
205 BegUndo(SvxResId(STR_UndoDelLayer));
206
207 bool bMaPg(true);
208
209 for(sal_uInt16 nPageKind(0); nPageKind < 2; nPageKind++)
210 {
211 // MasterPages and DrawPages
212 sal_uInt16 nPgCount(bMaPg ? mpModel->GetMasterPageCount() : mpModel->GetPageCount());
213
214 for(sal_uInt16 nPgNum(0); nPgNum < nPgCount; nPgNum++)
215 {
216 // over all pages
217 SdrPage* pPage = bMaPg ? mpModel->GetMasterPage(nPgNum) : mpModel->GetPage(nPgNum);
218 const size_t nObjCount(pPage->GetObjCount());
219
220 // make sure OrdNums are correct
221 if(nObjCount)
222 pPage->GetObj(0)->GetOrdNum();
223
224 for(size_t nObjNum(nObjCount); nObjNum > 0;)
225 {
226 nObjNum--;
227 SdrObject* pObj = pPage->GetObj(nObjNum);
228 SdrObjList* pSubOL = pObj->GetSubList();
229
230 // explicitly test for group objects and 3d scenes
231 if(pSubOL && (dynamic_cast<const SdrObjGroup*>(pObj) != nullptr || dynamic_cast<const E3dScene* >(pObj) != nullptr))
232 {
233 if(ImpDelLayerCheck(pSubOL, nDelID))
234 {
235 if( bUndo )
236 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true));
237 pPage->RemoveObject(nObjNum);
238 if( !bUndo )
239 SdrObject::Free(pObj);
240 }
241 else
242 {
243 ImpDelLayerDelObjs(pSubOL, nDelID);
244 }
245 }
246 else
247 {
248 if(pObj->GetLayer() == nDelID)
249 {
250 if( bUndo )
251 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj, true));
252 pPage->RemoveObject(nObjNum);
253 if( !bUndo )
254 SdrObject::Free(pObj);
255 }
256 }
257 }
258 }
259 bMaPg = false;
260 }
261
262 if( bUndo )
263 {
264 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteLayer(nLayerNum, rLA, *mpModel));
265 rLA.RemoveLayer(nLayerNum).release();
266 EndUndo();
267 }
268 else
269 {
270 rLA.RemoveLayer(nLayerNum);
271 }
272
273 mpModel->SetChanged();
274 }
275 }
276
277
EndUndo()278 void SdrEditView::EndUndo()
279 {
280 // #i13033#
281 // Comparison changed to 1L since EndUndo() is called later now
282 // and EndUndo WILL change count to count-1
283 if(1 == mpModel->GetUndoBracketLevel())
284 {
285 ImpBroadcastEdgesOfMarkedNodes();
286 }
287
288 // #i13033#
289 // moved to bottom to still have access to UNDOs inside of
290 // ImpBroadcastEdgesOfMarkedNodes()
291 mpModel->EndUndo();
292 }
293
ImpBroadcastEdgesOfMarkedNodes()294 void SdrEditView::ImpBroadcastEdgesOfMarkedNodes()
295 {
296 std::vector<SdrObject*>::const_iterator iterPos;
297 const std::vector<SdrObject*>& rAllMarkedObjects = GetTransitiveHullOfMarkedObjects();
298
299 // #i13033#
300 // New mechanism to search for necessary disconnections for
301 // changed connectors inside the transitive hull of all at
302 // the beginning of UNDO selected objects
303 for(size_t a(0); a < rAllMarkedObjects.size(); a++)
304 {
305 SdrEdgeObj* pEdge = dynamic_cast<SdrEdgeObj*>( rAllMarkedObjects[a] );
306
307 if(pEdge)
308 {
309 SdrObject* pObj1 = pEdge->GetConnectedNode(false);
310 SdrObject* pObj2 = pEdge->GetConnectedNode(true);
311
312 if(pObj1 && !pEdge->CheckNodeConnection(false))
313 {
314 iterPos = std::find(rAllMarkedObjects.begin(),rAllMarkedObjects.end(),pObj1);
315
316 if (iterPos == rAllMarkedObjects.end())
317 {
318 if( IsUndoEnabled() )
319 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pEdge));
320 pEdge->DisconnectFromNode(false);
321 }
322 }
323
324 if(pObj2 && !pEdge->CheckNodeConnection(true))
325 {
326 iterPos = std::find(rAllMarkedObjects.begin(),rAllMarkedObjects.end(),pObj2);
327
328 if (iterPos == rAllMarkedObjects.end())
329 {
330 if( IsUndoEnabled() )
331 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pEdge));
332 pEdge->DisconnectFromNode(true);
333 }
334 }
335 }
336 }
337
338 const size_t nMarkedEdgeCnt = GetMarkedEdgesOfMarkedNodes().GetMarkCount();
339
340 for (size_t i=0; i<nMarkedEdgeCnt; ++i) {
341 SdrMark* pEM = GetMarkedEdgesOfMarkedNodes().GetMark(i);
342 SdrObject* pEdgeTmp=pEM->GetMarkedSdrObj();
343 SdrEdgeObj* pEdge=dynamic_cast<SdrEdgeObj*>( pEdgeTmp );
344 if (pEdge!=nullptr) {
345 pEdge->SetEdgeTrackDirty();
346 }
347 }
348 }
349
350
351 // Possibilities
352
353
MarkListHasChanged()354 void SdrEditView::MarkListHasChanged()
355 {
356 SdrMarkView::MarkListHasChanged();
357 m_bPossibilitiesDirty=true;
358 }
359
ModelHasChanged()360 void SdrEditView::ModelHasChanged()
361 {
362 SdrMarkView::ModelHasChanged();
363 m_bPossibilitiesDirty=true;
364 }
365
IsResizeAllowed(bool bProp) const366 bool SdrEditView::IsResizeAllowed(bool bProp) const
367 {
368 ForcePossibilities();
369 if (m_bResizeProtect) return false;
370 if (bProp) return m_bResizePropAllowed;
371 return m_bResizeFreeAllowed;
372 }
373
IsRotateAllowed(bool b90Deg) const374 bool SdrEditView::IsRotateAllowed(bool b90Deg) const
375 {
376 ForcePossibilities();
377 if (m_bMoveProtect) return false;
378 if (b90Deg) return m_bRotate90Allowed;
379 return m_bRotateFreeAllowed;
380 }
381
IsMirrorAllowed(bool b45Deg,bool b90Deg) const382 bool SdrEditView::IsMirrorAllowed(bool b45Deg, bool b90Deg) const
383 {
384 ForcePossibilities();
385 if (m_bMoveProtect) return false;
386 if (b90Deg) return m_bMirror90Allowed;
387 if (b45Deg) return m_bMirror45Allowed;
388 return m_bMirrorFreeAllowed;
389 }
390
IsTransparenceAllowed() const391 bool SdrEditView::IsTransparenceAllowed() const
392 {
393 ForcePossibilities();
394 return m_bTransparenceAllowed;
395 }
396
IsCropAllowed() const397 bool SdrEditView::IsCropAllowed() const
398 {
399 ForcePossibilities();
400 return m_bCropAllowed;
401 }
402
IsGradientAllowed() const403 bool SdrEditView::IsGradientAllowed() const
404 {
405 ForcePossibilities();
406 return m_bGradientAllowed;
407 }
408
IsShearAllowed() const409 bool SdrEditView::IsShearAllowed() const
410 {
411 ForcePossibilities();
412 if (m_bResizeProtect) return false;
413 return m_bShearAllowed;
414 }
415
IsEdgeRadiusAllowed() const416 bool SdrEditView::IsEdgeRadiusAllowed() const
417 {
418 ForcePossibilities();
419 return m_bEdgeRadiusAllowed;
420 }
421
IsCrookAllowed(bool bNoContortion) const422 bool SdrEditView::IsCrookAllowed(bool bNoContortion) const
423 {
424 // CrookMode missing here (no rotations allowed when shearing ...)
425 ForcePossibilities();
426 if (bNoContortion) {
427 if (!m_bRotateFreeAllowed) return false;
428 return !m_bMoveProtect && m_bMoveAllowed;
429 } else {
430 return !m_bResizeProtect && m_bContortionPossible;
431 }
432 }
433
IsDistortAllowed(bool bNoContortion) const434 bool SdrEditView::IsDistortAllowed(bool bNoContortion) const
435 {
436 ForcePossibilities();
437 if (bNoContortion) {
438 return false;
439 } else {
440 return !m_bResizeProtect && m_bContortionPossible;
441 }
442 }
443
IsCombinePossible(bool bNoPolyPoly) const444 bool SdrEditView::IsCombinePossible(bool bNoPolyPoly) const
445 {
446 ForcePossibilities();
447 if (bNoPolyPoly) return m_bCombineNoPolyPolyPossible;
448 else return m_bCombinePossible;
449 }
450
IsDismantlePossible(bool bMakeLines) const451 bool SdrEditView::IsDismantlePossible(bool bMakeLines) const
452 {
453 ForcePossibilities();
454 if (bMakeLines) return m_bDismantleMakeLinesPossible;
455 else return m_bDismantlePossible;
456 }
457
CheckPossibilities()458 void SdrEditView::CheckPossibilities()
459 {
460 if (mbSomeObjChgdFlag)
461 {
462 m_bPossibilitiesDirty = true;
463
464 // This call IS necessary to correct the MarkList, in which
465 // no longer to the model belonging objects still can reside.
466 // These ones need to be removed.
467 CheckMarked();
468 }
469
470 if (m_bPossibilitiesDirty)
471 {
472 ImpResetPossibilityFlags();
473 SortMarkedObjects();
474 const size_t nMarkCount = GetMarkedObjectCount();
475 if (nMarkCount != 0)
476 {
477 m_bReverseOrderPossible = (nMarkCount >= 2);
478
479 size_t nMovableCount=0;
480 m_bGroupPossible=nMarkCount>=2;
481 m_bCombinePossible=nMarkCount>=2;
482 if (nMarkCount==1)
483 {
484 // check bCombinePossible more thoroughly
485 // still missing ...
486 const SdrObject* pObj=GetMarkedObjectByIndex(0);
487 //const SdrPathObj* pPath=dynamic_cast<SdrPathObj*>( pObj );
488 bool bGroup=pObj->GetSubList()!=nullptr;
489 bool bHasText=pObj->GetOutlinerParaObject()!=nullptr;
490 if (bGroup || bHasText) {
491 m_bCombinePossible=true;
492 }
493 }
494 m_bCombineNoPolyPolyPossible=m_bCombinePossible;
495 // accept transformations for now
496 m_bMoveAllowed =true;
497 m_bResizeFreeAllowed=true;
498 m_bResizePropAllowed=true;
499 m_bRotateFreeAllowed=true;
500 m_bRotate90Allowed =true;
501 m_bMirrorFreeAllowed=true;
502 m_bMirror45Allowed =true;
503 m_bMirror90Allowed =true;
504 m_bShearAllowed =true;
505 m_bEdgeRadiusAllowed=false;
506 m_bContortionPossible=true;
507 m_bCanConvToContour = true;
508
509 // these ones are only allowed when single object is selected
510 m_bTransparenceAllowed = (nMarkCount == 1);
511 m_bGradientAllowed = (nMarkCount == 1);
512 m_bCropAllowed = (nMarkCount == 1);
513 if(m_bGradientAllowed)
514 {
515 // gradient depends on fill style
516 const SdrMark* pM = GetSdrMarkByIndex(0);
517 const SdrObject* pObj = pM->GetMarkedSdrObj();
518
519 // may be group object, so get merged ItemSet
520 const SfxItemSet& rSet = pObj->GetMergedItemSet();
521 SfxItemState eState = rSet.GetItemState(XATTR_FILLSTYLE, false);
522
523 if(SfxItemState::DONTCARE != eState)
524 {
525 // If state is not DONTCARE, test the item
526 drawing::FillStyle eFillStyle = rSet.Get(XATTR_FILLSTYLE).GetValue();
527
528 if(eFillStyle != drawing::FillStyle_GRADIENT)
529 {
530 m_bGradientAllowed = false;
531 }
532 }
533 }
534
535 bool bNoMovRotFound=false;
536 const SdrPageView* pPV0=nullptr;
537
538 for (size_t nm=0; nm<nMarkCount; ++nm) {
539 const SdrMark* pM=GetSdrMarkByIndex(nm);
540 const SdrObject* pObj=pM->GetMarkedSdrObj();
541 const SdrPageView* pPV=pM->GetPageView();
542 if (pPV!=pPV0) {
543 if (pPV->IsReadOnly()) m_bReadOnly=true;
544 pPV0=pPV;
545 }
546
547 SdrObjTransformInfoRec aInfo;
548 pObj->TakeObjInfo(aInfo);
549 bool bMovPrt=pObj->IsMoveProtect();
550 bool bSizPrt=pObj->IsResizeProtect();
551 if (!bMovPrt && aInfo.bMoveAllowed) nMovableCount++; // count MovableObjs
552 if (bMovPrt) m_bMoveProtect=true;
553 if (bSizPrt) m_bResizeProtect=true;
554
555 // not allowed when not allowed at one object
556 if(!aInfo.bTransparenceAllowed)
557 m_bTransparenceAllowed = false;
558
559 // If one of these can't do something, none can
560 if (!aInfo.bMoveAllowed ) m_bMoveAllowed =false;
561 if (!aInfo.bResizeFreeAllowed) m_bResizeFreeAllowed=false;
562 if (!aInfo.bResizePropAllowed) m_bResizePropAllowed=false;
563 if (!aInfo.bRotateFreeAllowed) m_bRotateFreeAllowed=false;
564 if (!aInfo.bRotate90Allowed ) m_bRotate90Allowed =false;
565 if (!aInfo.bMirrorFreeAllowed) m_bMirrorFreeAllowed=false;
566 if (!aInfo.bMirror45Allowed ) m_bMirror45Allowed =false;
567 if (!aInfo.bMirror90Allowed ) m_bMirror90Allowed =false;
568 if (!aInfo.bShearAllowed ) m_bShearAllowed =false;
569 if (aInfo.bEdgeRadiusAllowed) m_bEdgeRadiusAllowed=true;
570 if (aInfo.bNoContortion ) m_bContortionPossible=false;
571 // For Crook with Contortion: all objects have to be
572 // Movable and Rotatable, except for a maximum of 1 of them
573 if (!m_bMoreThanOneNoMovRot) {
574 if (!aInfo.bMoveAllowed || !aInfo.bResizeFreeAllowed) {
575 m_bMoreThanOneNoMovRot=bNoMovRotFound;
576 bNoMovRotFound=true;
577 }
578 }
579
580 // Must be resizable to allow cropping
581 if (!aInfo.bResizeFreeAllowed && !aInfo.bResizePropAllowed)
582 m_bCropAllowed = false;
583
584 // if one member cannot be converted, no conversion is possible
585 if(!aInfo.bCanConvToContour)
586 m_bCanConvToContour = false;
587
588 // Ungroup
589 if (!m_bUnGroupPossible) m_bUnGroupPossible=pObj->GetSubList()!=nullptr;
590 // ConvertToCurve: If at least one can be converted, that is fine.
591 if (aInfo.bCanConvToPath ) m_bCanConvToPath =true;
592 if (aInfo.bCanConvToPoly ) m_bCanConvToPoly =true;
593
594 // Combine/Dismantle
595 if(m_bCombinePossible)
596 {
597 m_bCombinePossible = ImpCanConvertForCombine(pObj);
598 m_bCombineNoPolyPolyPossible = m_bCombinePossible;
599 }
600
601 if (!m_bDismantlePossible) m_bDismantlePossible = ImpCanDismantle(pObj, false);
602 if (!m_bDismantleMakeLinesPossible) m_bDismantleMakeLinesPossible = ImpCanDismantle(pObj, true);
603 // check OrthoDesiredOnMarked
604 if (!m_bOrthoDesiredOnMarked && !aInfo.bNoOrthoDesired) m_bOrthoDesiredOnMarked=true;
605 // check ImportMtf
606
607 if (!m_bImportMtfPossible)
608 {
609 const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(pObj);
610 if (pSdrGrafObj != nullptr)
611 {
612 if ((pSdrGrafObj->HasGDIMetaFile() && !pSdrGrafObj->IsEPS()) ||
613 pSdrGrafObj->isEmbeddedVectorGraphicData() ||
614 pSdrGrafObj->isEmbeddedPdfData())
615 {
616 m_bImportMtfPossible = true;
617 }
618 }
619
620 const SdrOle2Obj* pSdrOle2Obj = dynamic_cast< const SdrOle2Obj* >(pObj);
621 if (pSdrOle2Obj)
622 {
623 m_bImportMtfPossible = pSdrOle2Obj->GetObjRef().is();
624 }
625 }
626 }
627
628 m_bOneOrMoreMovable=nMovableCount!=0;
629 m_bGrpEnterPossible=m_bUnGroupPossible;
630 }
631 ImpCheckToTopBtmPossible();
632 static_cast<SdrPolyEditView*>(this)->ImpCheckPolyPossibilities();
633 m_bPossibilitiesDirty=false;
634
635 if (m_bReadOnly) {
636 bool bTemp=m_bGrpEnterPossible;
637 ImpResetPossibilityFlags();
638 m_bReadOnly=true;
639 m_bGrpEnterPossible=bTemp;
640 }
641 if (m_bMoveAllowed) {
642 // Don't allow moving glued connectors.
643 // Currently only implemented for single selection.
644 if (nMarkCount==1) {
645 SdrObject* pObj=GetMarkedObjectByIndex(0);
646 SdrEdgeObj* pEdge=dynamic_cast<SdrEdgeObj*>( pObj );
647 if (pEdge!=nullptr) {
648 SdrObject* pNode1=pEdge->GetConnectedNode(true);
649 SdrObject* pNode2=pEdge->GetConnectedNode(false);
650 if (pNode1!=nullptr || pNode2!=nullptr) m_bMoveAllowed=false;
651 }
652 }
653 }
654 }
655 }
656
657
ForceMarkedObjToAnotherPage()658 void SdrEditView::ForceMarkedObjToAnotherPage()
659 {
660 bool bFlg=false;
661 for (size_t nm=0; nm<GetMarkedObjectCount(); ++nm) {
662 SdrMark* pM=GetSdrMarkByIndex(nm);
663 SdrObject* pObj=pM->GetMarkedSdrObj();
664 tools::Rectangle aObjRect(pObj->GetCurrentBoundRect());
665 tools::Rectangle aPgRect(pM->GetPageView()->GetPageRect());
666 if (!aObjRect.IsOver(aPgRect)) {
667 bool bFnd=false;
668 SdrPageView* pPV = GetSdrPageView();
669
670 if(pPV)
671 {
672 bFnd = aObjRect.IsOver(pPV->GetPageRect());
673 }
674
675 if(bFnd)
676 {
677 pM->GetPageView()->GetObjList()->RemoveObject(pObj->GetOrdNum());
678 pPV->GetObjList()->InsertObject(pObj, SAL_MAX_SIZE);
679 pM->SetPageView(pPV);
680 InvalidateAllWin(aObjRect);
681 bFlg=true;
682 }
683 }
684 }
685 if (bFlg) {
686 MarkListHasChanged();
687 }
688 }
689
DeleteMarkedList(SdrMarkList const & rMark)690 std::vector<SdrObject*> SdrEditView::DeleteMarkedList(SdrMarkList const& rMark)
691 {
692 std::vector<SdrObject*> ret;
693 if (rMark.GetMarkCount()!=0)
694 {
695 rMark.ForceSort();
696
697 const bool bUndo = IsUndoEnabled();
698 if( bUndo )
699 BegUndo();
700 const size_t nMarkCount(rMark.GetMarkCount());
701
702 if(nMarkCount)
703 {
704 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
705
706 if( bUndo )
707 {
708 for(size_t nm = nMarkCount; nm > 0;)
709 {
710 --nm;
711 SdrMark* pM = rMark.GetMark(nm);
712 SdrObject* pObj = pM->GetMarkedSdrObj();
713
714 // extra undo actions for changed connector which now may hold its laid out path (SJ)
715 AddUndoActions(CreateConnectorUndo( *pObj ));
716
717 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj));
718 }
719 }
720
721 // make sure, OrderNums are correct:
722 rMark.GetMark(0)->GetMarkedSdrObj()->GetOrdNum();
723
724 for(size_t nm = nMarkCount; nm > 0;)
725 {
726 --nm;
727 SdrMark* pM = rMark.GetMark(nm);
728 SdrObject* pObj = pM->GetMarkedSdrObj();
729 SdrObjList* pOL = pObj->getParentSdrObjListFromSdrObject();
730 const size_t nOrdNum(pObj->GetOrdNumDirect());
731
732 bool bIs3D = dynamic_cast< E3dObject* >(pObj);
733 // set up a scene updater if object is a 3d object
734 if(bIs3D)
735 {
736 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pObj));
737 }
738
739 pOL->RemoveObject(nOrdNum);
740
741 if( !bUndo )
742 {
743 // tdf#108863 don't delete objects before EndUndo()
744 ret.push_back(pObj);
745 }
746 }
747
748 // fire scene updaters
749 while(!aUpdaters.empty())
750 {
751 delete aUpdaters.back();
752 aUpdaters.pop_back();
753 }
754 }
755
756 if( bUndo )
757 EndUndo();
758 }
759 return ret;
760 }
761
lcl_LazyDelete(std::vector<SdrObject * > & rLazyDelete)762 static void lcl_LazyDelete(std::vector<SdrObject*> & rLazyDelete)
763 {
764 // now delete removed scene objects
765 while (!rLazyDelete.empty())
766 {
767 SdrObject::Free( rLazyDelete.back() );
768 rLazyDelete.pop_back();
769 }
770 }
771
DeleteMarkedObj()772 void SdrEditView::DeleteMarkedObj()
773 {
774 // #i110981# return when nothing is to be done at all
775 if(!GetMarkedObjectCount())
776 {
777 return;
778 }
779
780 // moved breaking action and undo start outside loop
781 BrkAction();
782 BegUndo(SvxResId(STR_EditDelete),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::Delete);
783
784 std::vector<SdrObject*> lazyDeleteObjects;
785 // remove as long as something is selected. This allows to schedule objects for
786 // removal for a next run as needed
787 while(GetMarkedObjectCount())
788 {
789 // vector to remember the parents which may be empty after object removal
790 std::vector< SdrObject* > aParents;
791
792 {
793 const SdrMarkList& rMarkList = GetMarkedObjectList();
794 const size_t nCount(rMarkList.GetMarkCount());
795
796 for(size_t a = 0; a < nCount; ++a)
797 {
798 // in the first run, add all found parents, but only once
799 SdrMark* pMark(rMarkList.GetMark(a));
800 SdrObject* pObject(pMark->GetMarkedSdrObj());
801 SdrObject* pParent(pObject->getParentSdrObjectFromSdrObject());
802
803 if(pParent)
804 {
805 if(!aParents.empty())
806 {
807 std::vector< SdrObject* >::iterator aFindResult =
808 std::find(aParents.begin(), aParents.end(), pParent);
809
810 if(aFindResult == aParents.end())
811 {
812 aParents.push_back(pParent);
813 }
814 }
815 else
816 {
817 aParents.push_back(pParent);
818 }
819 }
820 }
821
822 if(!aParents.empty())
823 {
824 // in a 2nd run, remove all objects which may already be scheduled for
825 // removal. I am not sure if this can happen, but theoretically
826 // a to-be-removed object may already be the group/3DScene itself
827 for(size_t a = 0; a < nCount; ++a)
828 {
829 SdrMark* pMark = rMarkList.GetMark(a);
830 SdrObject* pObject = pMark->GetMarkedSdrObj();
831
832 std::vector< SdrObject* >::iterator aFindResult =
833 std::find(aParents.begin(), aParents.end(), pObject);
834
835 if(aFindResult != aParents.end())
836 {
837 aParents.erase(aFindResult);
838 }
839 }
840 }
841 }
842
843 // original stuff: remove selected objects. Handle clear will
844 // do something only once
845 auto temp(DeleteMarkedList(GetMarkedObjectList()));
846 for (auto p : temp)
847 {
848 lazyDeleteObjects.push_back(p);
849 }
850 GetMarkedObjectListWriteAccess().Clear();
851 maHdlList.Clear();
852
853 while(!aParents.empty() && !GetMarkedObjectCount())
854 {
855 // iterate over remembered parents
856 SdrObject* pParent = aParents.back();
857 aParents.pop_back();
858
859 if(pParent->GetSubList() && 0 == pParent->GetSubList()->GetObjCount())
860 {
861 // we detected an empty parent, a candidate to leave group/3DScene
862 // if entered
863 if(GetSdrPageView()->GetCurrentGroup()
864 && GetSdrPageView()->GetCurrentGroup() == pParent)
865 {
866 GetSdrPageView()->LeaveOneGroup();
867 }
868
869 // schedule empty parent for removal
870 GetMarkedObjectListWriteAccess().InsertEntry(
871 SdrMark(pParent, GetSdrPageView()));
872 }
873 }
874 }
875
876 // end undo and change messaging moved at the end
877 EndUndo();
878 MarkListHasChanged();
879
880 lcl_LazyDelete(lazyDeleteObjects);
881 }
882
CopyMarkedObj()883 void SdrEditView::CopyMarkedObj()
884 {
885 SortMarkedObjects();
886
887 SdrMarkList aSourceObjectsForCopy(GetMarkedObjectList());
888 // The following loop is used instead of MarkList::Merge(), to be
889 // able to flag the MarkEntries.
890 const size_t nEdgeCnt = GetEdgesOfMarkedNodes().GetMarkCount();
891 for (size_t nEdgeNum=0; nEdgeNum<nEdgeCnt; ++nEdgeNum) {
892 SdrMark aM(*GetEdgesOfMarkedNodes().GetMark(nEdgeNum));
893 aM.SetUser(1);
894 aSourceObjectsForCopy.InsertEntry(aM);
895 }
896 aSourceObjectsForCopy.ForceSort();
897
898 // #i13033#
899 // New mechanism to re-create the connections of cloned connectors
900 CloneList aCloneList;
901
902 const bool bUndo = IsUndoEnabled();
903
904 GetMarkedObjectListWriteAccess().Clear();
905 size_t nCloneErrCnt=0;
906 std::unordered_set<rtl::OUString> aNameSet;
907 const size_t nMarkCount=aSourceObjectsForCopy.GetMarkCount();
908 for (size_t nm=0; nm<nMarkCount; ++nm) {
909 SdrMark* pM=aSourceObjectsForCopy.GetMark(nm);
910 SdrObject* pSource(pM->GetMarkedSdrObj());
911 SdrObject* pO(pSource->CloneSdrObject(pSource->getSdrModelFromSdrObject()));
912 if (pO!=nullptr) {
913 pM->GetPageView()->GetObjList()->InsertObjectThenMakeNameUnique(pO, aNameSet);
914
915 if( bUndo )
916 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoCopyObject(*pO));
917
918 SdrMark aME(*pM);
919 aME.SetMarkedSdrObj(pO);
920 aCloneList.AddPair(pM->GetMarkedSdrObj(), pO);
921
922 if (pM->GetUser()==0)
923 {
924 // otherwise it is only an Edge we have to copy as well
925 GetMarkedObjectListWriteAccess().InsertEntry(aME);
926 }
927 } else {
928 nCloneErrCnt++;
929 }
930 }
931
932 // #i13033#
933 // New mechanism to re-create the connections of cloned connectors
934 aCloneList.CopyConnections();
935
936 if(nCloneErrCnt)
937 {
938 #ifdef DBG_UTIL
939 OStringBuffer aStr("SdrEditView::CopyMarkedObj(): Error when cloning ");
940
941 if(nCloneErrCnt == 1)
942 {
943 aStr.append("a drawing object.");
944 }
945 else
946 {
947 aStr.append(static_cast<sal_Int32>(nCloneErrCnt));
948 aStr.append(" drawing objects.");
949 }
950
951 aStr.append(" This object's/These objects's connections will not be copied.");
952 OSL_FAIL(aStr.getStr());
953 #endif
954 }
955 MarkListHasChanged();
956 }
957
958
InsertObjectAtView(SdrObject * pObj,SdrPageView & rPV,SdrInsertFlags nOptions)959 bool SdrEditView::InsertObjectAtView(SdrObject* pObj, SdrPageView& rPV, SdrInsertFlags nOptions)
960 {
961 if (nOptions & SdrInsertFlags::SETDEFLAYER) {
962 SdrLayerID nLayer=rPV.GetPage()->GetLayerAdmin().GetLayerID(maActualLayer);
963 if (nLayer==SDRLAYER_NOTFOUND) nLayer=SdrLayerID(0);
964 if (rPV.GetLockedLayers().IsSet(nLayer) || !rPV.GetVisibleLayers().IsSet(nLayer)) {
965 SdrObject::Free( pObj ); // Layer locked or invisible
966 return false;
967 }
968 pObj->NbcSetLayer(nLayer);
969 }
970 if (nOptions & SdrInsertFlags::SETDEFATTR) {
971 if (mpDefaultStyleSheet!=nullptr) pObj->NbcSetStyleSheet(mpDefaultStyleSheet, false);
972 pObj->SetMergedItemSet(maDefaultAttr);
973 }
974 if (!pObj->IsInserted()) {
975 rPV.GetObjList()->InsertObject(pObj, SAL_MAX_SIZE);
976 }
977 if( IsUndoEnabled())
978 {
979 EndTextEditAllViews();
980 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pObj));
981 }
982
983 if (!(nOptions & SdrInsertFlags::DONTMARK)) {
984 if (!(nOptions & SdrInsertFlags::ADDMARK)) UnmarkAllObj();
985 MarkObj(pObj,&rPV);
986 }
987 return true;
988 }
989
ReplaceObjectAtView(SdrObject * pOldObj,SdrPageView & rPV,SdrObject * pNewObj,bool bMark)990 void SdrEditView::ReplaceObjectAtView(SdrObject* pOldObj, SdrPageView& rPV, SdrObject* pNewObj, bool bMark)
991 {
992 if(IsTextEdit())
993 {
994 #ifdef DBG_UTIL
995 if(dynamic_cast< SdrTextObj* >(pOldObj) && static_cast< SdrTextObj* >(pOldObj)->IsTextEditActive())
996 {
997 OSL_ENSURE(false, "OldObject is in TextEdit mode, this has to be ended before replacing it using SdrEndTextEdit (!)");
998 }
999
1000 if(dynamic_cast< SdrTextObj* >(pNewObj) && static_cast< SdrTextObj* >(pNewObj)->IsTextEditActive())
1001 {
1002 OSL_ENSURE(false, "NewObject is in TextEdit mode, this has to be ended before replacing it using SdrEndTextEdit (!)");
1003 }
1004 #endif
1005
1006 // #i123468# emergency repair situation, needs to cast up to a class derived from
1007 // this one; (aw080 has a mechanism for that and the view hierarchy is secured to
1008 // always be a SdrView)
1009 SdrView *pSdrView = dynamic_cast<SdrView*>(this);
1010 if (pSdrView)
1011 pSdrView->SdrEndTextEdit();
1012 }
1013
1014 SdrObjList* pOL=pOldObj->getParentSdrObjListFromSdrObject();
1015 const bool bUndo = IsUndoEnabled();
1016 if( bUndo )
1017 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoReplaceObject(*pOldObj,*pNewObj));
1018
1019 if( IsObjMarked( pOldObj ) )
1020 MarkObj( pOldObj, &rPV, true /*unmark!*/ );
1021
1022 pOL->ReplaceObject(pNewObj,pOldObj->GetOrdNum());
1023
1024 if( !bUndo )
1025 SdrObject::Free( pOldObj );
1026
1027 if (bMark) MarkObj(pNewObj,&rPV);
1028 }
1029
1030
IsUndoEnabled() const1031 bool SdrEditView::IsUndoEnabled() const
1032 {
1033 return mpModel->IsUndoEnabled();
1034 }
1035
EndTextEditAllViews() const1036 void SdrEditView::EndTextEditAllViews() const
1037 {
1038 size_t nViews = mpModel->GetListenerCount();
1039 for (size_t nView = 0; nView < nViews; ++nView)
1040 {
1041 SdrObjEditView* pView = dynamic_cast<SdrObjEditView*>(mpModel->GetListener(nView));
1042 if (!pView)
1043 continue;
1044
1045 if (pView->IsTextEdit())
1046 pView->SdrEndTextEdit();
1047 }
1048 }
1049
1050 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1051