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