LibreOffice Module svx (master)  1
svdedtv2.cxx
Go to the documentation of this file.
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/svdogrp.hxx>
23 #include <svx/svdoutl.hxx>
24 #include <svx/svdopath.hxx>
25 #include <svx/svdpage.hxx>
26 #include <svx/svdpagv.hxx>
27 #include <svx/svditer.hxx>
28 #include <svx/svdograf.hxx>
29 #include <svx/svdoole2.hxx>
30 #include <svx/dialmgr.hxx>
31 #include <svx/sdooitm.hxx>
32 #include <svx/sdshitm.hxx>
33 #include <svx/xfillit0.hxx>
34 #include <svx/xlineit0.hxx>
35 #include <svx/xtextit0.hxx>
36 #include "svdfmtf.hxx"
37 #include <svdpdf.hxx>
38 #include <svx/svdetc.hxx>
39 #include <editeng/outlobj.hxx>
40 #include <editeng/eeitem.hxx>
43 #include <svx/strings.hrc>
44 #include <svx/svdoashp.hxx>
46 #include <i18nutil/unicode.hxx>
47 #include <sal/log.hxx>
48 #include <tools/debug.hxx>
49 #include <memory>
50 #include <vector>
51 #include <vcl/graph.hxx>
52 #include <svx/svxids.hrc>
53 #include <dstribut_enum.hxx>
54 #include <osl/diagnose.h>
55 
56 using namespace com::sun::star;
57 
59 {
60  return nullptr;
61 }
62 
64 {
65  return nullptr;
66 }
67 
68 void SdrEditView::ObjOrderChanged(SdrObject* /*pObj*/, size_t /*nOldPos*/, size_t /*nNewPos*/)
69 {
70 }
71 
73 {
74  const size_t nCount=GetMarkedObjectCount();
75  if (nCount==0)
76  return;
77 
78  const bool bUndo = IsUndoEnabled();
79 
80  if( bUndo )
81  BegUndo(SvxResId(STR_EditMovToTop),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::MoveToTop);
82 
83  SortMarkedObjects();
84  for (size_t nm=0; nm<nCount; ++nm)
85  { // All Ordnums have to be correct!
86  GetMarkedObjectByIndex(nm)->GetOrdNum();
87  }
88  bool bChg=false;
89  SdrObjList* pOL0=nullptr;
90  size_t nNewPos=0;
91  for (size_t nm=nCount; nm>0;)
92  {
93  --nm;
94  SdrMark* pM=GetSdrMarkByIndex(nm);
95  SdrObject* pObj=pM->GetMarkedSdrObj();
97  if (pOL!=pOL0)
98  {
99  nNewPos = pOL->GetObjCount()-1;
100  pOL0=pOL;
101  }
102  const size_t nNowPos = pObj->GetOrdNumDirect();
103  const tools::Rectangle& rBR=pObj->GetCurrentBoundRect();
104  size_t nCmpPos = nNowPos+1;
105  SdrObject* pMaxObj=GetMaxToTopObj(pObj);
106  if (pMaxObj!=nullptr)
107  {
108  size_t nMaxPos=pMaxObj->GetOrdNum();
109  if (nMaxPos!=0)
110  nMaxPos--;
111  if (nNewPos>nMaxPos)
112  nNewPos=nMaxPos; // neither go faster...
113  if (nNewPos<nNowPos)
114  nNewPos=nNowPos; // nor go in the other direction
115  }
116  bool bEnd=false;
117  while (nCmpPos<nNewPos && !bEnd)
118  {
119  SdrObject* pCmpObj=pOL->GetObj(nCmpPos);
120  if (pCmpObj==nullptr)
121  {
122  OSL_FAIL("MovMarkedToTop(): Reference object not found.");
123  bEnd=true;
124  }
125  else if (pCmpObj==pMaxObj)
126  {
127  nNewPos=nCmpPos;
128  nNewPos--;
129  bEnd=true;
130  }
131  else if (rBR.Overlaps(pCmpObj->GetCurrentBoundRect()))
132  {
133  nNewPos=nCmpPos;
134  bEnd=true;
135  }
136  else
137  {
138  nCmpPos++;
139  }
140  }
141  if (nNowPos!=nNewPos)
142  {
143  bChg=true;
144  pOL->SetObjectOrdNum(nNowPos,nNewPos);
145  if( bUndo )
146  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
147  ObjOrderChanged(pObj,nNowPos,nNewPos);
148  }
149  nNewPos--;
150  }
151 
152  if( bUndo )
153  EndUndo();
154 
155  if (bChg)
156  MarkListHasChanged();
157 }
158 
160 {
161  const size_t nCount=GetMarkedObjectCount();
162  if (nCount==0)
163  return;
164 
165  const bool bUndo = IsUndoEnabled();
166 
167  if( bUndo )
168  BegUndo(SvxResId(STR_EditMovToBtm),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::MoveToBottom);
169 
170  SortMarkedObjects();
171  for (size_t nm=0; nm<nCount; ++nm)
172  { // All Ordnums have to be correct!
173  GetMarkedObjectByIndex(nm)->GetOrdNum();
174  }
175 
176  bool bChg=false;
177  SdrObjList* pOL0=nullptr;
178  size_t nNewPos=0;
179  for (size_t nm=0; nm<nCount; ++nm)
180  {
181  SdrMark* pM=GetSdrMarkByIndex(nm);
182  SdrObject* pObj=pM->GetMarkedSdrObj();
184  if (pOL!=pOL0)
185  {
186  nNewPos=0;
187  pOL0=pOL;
188  }
189  const size_t nNowPos = pObj->GetOrdNumDirect();
190  const tools::Rectangle& rBR=pObj->GetCurrentBoundRect();
191  size_t nCmpPos = nNowPos;
192  if (nCmpPos>0)
193  --nCmpPos;
194  SdrObject* pMaxObj=GetMaxToBtmObj(pObj);
195  if (pMaxObj!=nullptr)
196  {
197  const size_t nMinPos=pMaxObj->GetOrdNum()+1;
198  if (nNewPos<nMinPos)
199  nNewPos=nMinPos; // neither go faster...
200  if (nNewPos>nNowPos)
201  nNewPos=nNowPos; // nor go in the other direction
202  }
203  bool bEnd=false;
204  // nNewPos in this case is the "maximum" position
205  // the object may reach without going faster than the object before
206  // it (multiple selection).
207  while (nCmpPos>nNewPos && !bEnd)
208  {
209  SdrObject* pCmpObj=pOL->GetObj(nCmpPos);
210  if (pCmpObj==nullptr)
211  {
212  OSL_FAIL("MovMarkedToBtm(): Reference object not found.");
213  bEnd=true;
214  }
215  else if (pCmpObj==pMaxObj)
216  {
217  nNewPos=nCmpPos;
218  nNewPos++;
219  bEnd=true;
220  }
221  else if (rBR.Overlaps(pCmpObj->GetCurrentBoundRect()))
222  {
223  nNewPos=nCmpPos;
224  bEnd=true;
225  }
226  else
227  {
228  nCmpPos--;
229  }
230  }
231  if (nNowPos!=nNewPos)
232  {
233  bChg=true;
234  pOL->SetObjectOrdNum(nNowPos,nNewPos);
235  if( bUndo )
236  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
237  ObjOrderChanged(pObj,nNowPos,nNewPos);
238  }
239  nNewPos++;
240  }
241 
242  if(bUndo)
243  EndUndo();
244 
245  if(bChg)
246  MarkListHasChanged();
247 }
248 
250 {
251  PutMarkedInFrontOfObj(nullptr);
252 }
253 
255 {
256  const size_t nCount=GetMarkedObjectCount();
257  if (nCount==0)
258  return;
259 
260  const bool bUndo = IsUndoEnabled();
261  if( bUndo )
262  BegUndo(SvxResId(STR_EditPutToTop),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::PutToTop);
263 
264  SortMarkedObjects();
265 
266  if (pRefObj!=nullptr)
267  {
268  // Make "in front of the object" work, even if the
269  // selected objects are already in front of the other object
270  const size_t nRefMark=TryToFindMarkedObject(pRefObj);
271  SdrMark aRefMark;
272  if (nRefMark!=SAL_MAX_SIZE)
273  {
274  aRefMark=*GetSdrMarkByIndex(nRefMark);
275  GetMarkedObjectListWriteAccess().DeleteMark(nRefMark);
276  }
277  PutMarkedToBtm();
278  if (nRefMark!=SAL_MAX_SIZE)
279  {
280  GetMarkedObjectListWriteAccess().InsertEntry(aRefMark);
281  SortMarkedObjects();
282  }
283  }
284  for (size_t nm=0; nm<nCount; ++nm)
285  { // All Ordnums have to be correct!
286  GetMarkedObjectByIndex(nm)->GetOrdNum();
287  }
288  bool bChg=false;
289  SdrObjList* pOL0=nullptr;
290  size_t nNewPos=0;
291  for (size_t nm=nCount; nm>0;)
292  {
293  --nm;
294  SdrMark* pM=GetSdrMarkByIndex(nm);
295  SdrObject* pObj=pM->GetMarkedSdrObj();
296  if (pObj!=pRefObj)
297  {
299  if (pOL!=pOL0)
300  {
301  nNewPos=pOL->GetObjCount()-1;
302  pOL0=pOL;
303  }
304  const size_t nNowPos=pObj->GetOrdNumDirect();
305  SdrObject* pMaxObj=GetMaxToTopObj(pObj);
306  if (pMaxObj!=nullptr)
307  {
308  size_t nMaxOrd=pMaxObj->GetOrdNum(); // sadly doesn't work any other way
309  if (nMaxOrd>0)
310  nMaxOrd--;
311  if (nNewPos>nMaxOrd)
312  nNewPos=nMaxOrd; // neither go faster...
313  if (nNewPos<nNowPos)
314  nNewPos=nNowPos; // nor go into the other direction
315  }
316  if (pRefObj!=nullptr)
317  {
319  {
320  const size_t nMaxOrd=pRefObj->GetOrdNum(); // sadly doesn't work any other way
321  if (nNewPos>nMaxOrd)
322  nNewPos=nMaxOrd; // neither go faster...
323  if (nNewPos<nNowPos)
324  nNewPos=nNowPos; // nor go into the other direction
325  }
326  else
327  {
328  nNewPos=nNowPos; // different PageView, so don't change
329  }
330  }
331  if (nNowPos!=nNewPos)
332  {
333  bChg=true;
334  pOL->SetObjectOrdNum(nNowPos,nNewPos);
335  if( bUndo )
336  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
337  ObjOrderChanged(pObj,nNowPos,nNewPos);
338  }
339  nNewPos--;
340  } // if (pObj!=pRefObj)
341  } // for loop over all selected objects
342 
343  if( bUndo )
344  EndUndo();
345 
346  if(bChg)
347  MarkListHasChanged();
348 }
349 
351 {
352  PutMarkedBehindObj(nullptr);
353 }
354 
356 {
357  const size_t nCount=GetMarkedObjectCount();
358  if (nCount==0)
359  return;
360 
361  const bool bUndo = IsUndoEnabled();
362 
363  if( bUndo )
364  BegUndo(SvxResId(STR_EditPutToBtm),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::PutToBottom);
365 
366  SortMarkedObjects();
367  if (pRefObj!=nullptr)
368  {
369  // Make "behind the object" work, even if the
370  // selected objects are already behind the other object
371  const size_t nRefMark=TryToFindMarkedObject(pRefObj);
372  SdrMark aRefMark;
373  if (nRefMark!=SAL_MAX_SIZE)
374  {
375  aRefMark=*GetSdrMarkByIndex(nRefMark);
376  GetMarkedObjectListWriteAccess().DeleteMark(nRefMark);
377  }
378  PutMarkedToTop();
379  if (nRefMark!=SAL_MAX_SIZE)
380  {
381  GetMarkedObjectListWriteAccess().InsertEntry(aRefMark);
382  SortMarkedObjects();
383  }
384  }
385  for (size_t nm=0; nm<nCount; ++nm) { // All Ordnums have to be correct!
386  GetMarkedObjectByIndex(nm)->GetOrdNum();
387  }
388  bool bChg=false;
389  SdrObjList* pOL0=nullptr;
390  size_t nNewPos=0;
391  for (size_t nm=0; nm<nCount; ++nm) {
392  SdrMark* pM=GetSdrMarkByIndex(nm);
393  SdrObject* pObj=pM->GetMarkedSdrObj();
394  if (pObj!=pRefObj) {
396  if (pOL!=pOL0) {
397  nNewPos=0;
398  pOL0=pOL;
399  }
400  const size_t nNowPos=pObj->GetOrdNumDirect();
401  SdrObject* pMinObj=GetMaxToBtmObj(pObj);
402  if (pMinObj!=nullptr) {
403  const size_t nMinOrd=pMinObj->GetOrdNum()+1; // sadly doesn't work any differently
404  if (nNewPos<nMinOrd) nNewPos=nMinOrd; // neither go faster...
405  if (nNewPos>nNowPos) nNewPos=nNowPos; // nor go into the other direction
406  }
407  if (pRefObj!=nullptr) {
409  const size_t nMinOrd=pRefObj->GetOrdNum(); // sadly doesn't work any differently
410  if (nNewPos<nMinOrd) nNewPos=nMinOrd; // neither go faster...
411  if (nNewPos>nNowPos) nNewPos=nNowPos; // nor go into the other direction
412  } else {
413  nNewPos=nNowPos; // different PageView, so don't change
414  }
415  }
416  if (nNowPos!=nNewPos) {
417  bChg=true;
418  pOL->SetObjectOrdNum(nNowPos,nNewPos);
419  if( bUndo )
420  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
421  ObjOrderChanged(pObj,nNowPos,nNewPos);
422  }
423  nNewPos++;
424  } // if (pObj!=pRefObj)
425  } // for loop over all selected objects
426 
427  if(bUndo)
428  EndUndo();
429 
430  if(bChg)
431  MarkListHasChanged();
432 
433 }
434 
436 {
437  SortMarkedObjects();
438  const size_t nMarkCount=GetMarkedObjectCount();
439  if (nMarkCount<=0)
440  return;
441 
442  bool bChg=false;
443 
444  bool bUndo = IsUndoEnabled();
445  if( bUndo )
446  BegUndo(SvxResId(STR_EditRevOrder),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::ReverseOrder);
447 
448  size_t a=0;
449  do {
450  // take into account selection across multiple PageViews
451  size_t b=a+1;
452  while (b<nMarkCount && GetSdrPageViewOfMarkedByIndex(b) == GetSdrPageViewOfMarkedByIndex(a)) ++b;
453  --b;
454  SdrObjList* pOL=GetSdrPageViewOfMarkedByIndex(a)->GetObjList();
455  size_t c=b;
456  if (a<c) { // make sure OrdNums aren't dirty
457  GetMarkedObjectByIndex(a)->GetOrdNum();
458  }
459  while (a<c) {
460  SdrObject* pObj1=GetMarkedObjectByIndex(a);
461  SdrObject* pObj2=GetMarkedObjectByIndex(c);
462  const size_t nOrd1=pObj1->GetOrdNumDirect();
463  const size_t nOrd2=pObj2->GetOrdNumDirect();
464  if( bUndo )
465  {
466  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj1,nOrd1,nOrd2));
467  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj2,nOrd2-1,nOrd1));
468  }
469  pOL->SetObjectOrdNum(nOrd1,nOrd2);
470  // Obj 2 has moved forward by one position, so now nOrd2-1
471  pOL->SetObjectOrdNum(nOrd2-1,nOrd1);
472  // use Replace instead of SetOrdNum for performance reasons (recalculation of Ordnums)
473  ++a;
474  --c;
475  bChg=true;
476  }
477  a=b+1;
478  } while (a<nMarkCount);
479 
480  if(bUndo)
481  EndUndo();
482 
483  if(bChg)
484  MarkListHasChanged();
485 }
486 
488 {
489  const size_t nCount=GetMarkedObjectCount();
490  if (nCount==0)
491  return;
492  if (nCount==1)
493  { // special-casing for single selection
494  SdrObject* pObj=GetMarkedObjectByIndex(0);
496  SAL_WARN_IF(!pOL, "svx", "Object somehow has no ObjList");
497  size_t nMax = pOL ? pOL->GetObjCount() : 0;
498  size_t nMin = 0;
499  const size_t nObjNum=pObj->GetOrdNum();
500  SdrObject* pRestrict=GetMaxToTopObj(pObj);
501  if (pRestrict!=nullptr) {
502  const size_t nRestrict=pRestrict->GetOrdNum();
503  if (nRestrict<nMax) nMax=nRestrict;
504  }
505  pRestrict=GetMaxToBtmObj(pObj);
506  if (pRestrict!=nullptr) {
507  const size_t nRestrict=pRestrict->GetOrdNum();
508  if (nRestrict>nMin) nMin=nRestrict;
509  }
510  m_bToTopPossible=nObjNum<nMax-1;
511  m_bToBtmPossible=nObjNum>nMin;
512  } else { // multiple selection
513  SdrObjList* pOL0=nullptr;
514  size_t nPos0 = 0;
515  for (size_t nm = 0; !m_bToBtmPossible && nm<nCount; ++nm) { // check 'send to background'
516  SdrObject* pObj=GetMarkedObjectByIndex(nm);
518  if (pOL!=pOL0) {
519  nPos0 = 0;
520  pOL0=pOL;
521  }
522  const size_t nPos = pObj->GetOrdNum();
523  m_bToBtmPossible = nPos && (nPos-1 > nPos0);
524  nPos0 = nPos;
525  }
526 
527  pOL0=nullptr;
528  nPos0 = SAL_MAX_SIZE;
529  for (size_t nm=nCount; !m_bToTopPossible && nm>0; ) { // check 'bring to front'
530  --nm;
531  SdrObject* pObj=GetMarkedObjectByIndex(nm);
533  if (pOL!=pOL0) {
534  nPos0=pOL->GetObjCount();
535  pOL0=pOL;
536  }
537  const size_t nPos = pObj->GetOrdNum();
538  m_bToTopPossible = nPos+1 < nPos0;
539  nPos0=nPos;
540  }
541  }
542 }
543 
544 
545 // Combine
546 
547 
548 void SdrEditView::ImpCopyAttributes(const SdrObject* pSource, SdrObject* pDest) const
549 {
550  if (pSource!=nullptr) {
551  SdrObjList* pOL=pSource->GetSubList();
552  if (pOL!=nullptr && !pSource->Is3DObj()) { // get first non-group object from group
554  pSource=aIter.Next();
555  }
556  }
557 
558  if(!(pSource && pDest))
559  return;
560 
563  EE_ITEMS_START, EE_ITEMS_END> aSet(mpModel->GetItemPool());
564 
565  aSet.Put(pSource->GetMergedItemSet());
566 
567  pDest->ClearMergedItem();
568  pDest->SetMergedItemSet(aSet);
569 
570  pDest->NbcSetLayer(pSource->GetLayer());
571  pDest->NbcSetStyleSheet(pSource->GetStyleSheet(), true);
572 }
573 
575 {
576  // new condition IsLine() to be able to combine simple Lines
577  bool bIsLine(false);
578 
579  const SdrPathObj* pPath = dynamic_cast< const SdrPathObj*>( pObj );
580 
581  if(pPath)
582  {
583  bIsLine = pPath->IsLine();
584  }
585 
587  pObj->TakeObjInfo(aInfo);
588 
589  return (aInfo.bCanConvToPath || aInfo.bCanConvToPoly || bIsLine);
590 }
591 
593 {
594  SdrObjList* pOL = pObj->GetSubList();
595 
596  if(pOL && !pObj->Is3DObj())
597  {
599 
600  while(aIter.IsMore())
601  {
602  SdrObject* pObj1 = aIter.Next();
603 
604  // all members of a group have to be convertible
605  if(!ImpCanConvertForCombine1(pObj1))
606  {
607  return false;
608  }
609  }
610  }
611  else
612  {
613  if(!ImpCanConvertForCombine1(pObj))
614  {
615  return false;
616  }
617  }
618 
619  return true;
620 }
621 
623 {
624  basegfx::B2DPolyPolygon aRetval;
625  const SdrPathObj* pPath = dynamic_cast<const SdrPathObj*>( pObj );
626 
627  if(pPath && !pObj->GetOutlinerParaObject())
628  {
629  aRetval = pPath->GetPathPoly();
630  }
631  else
632  {
633  SdrObjectUniquePtr pConvObj = pObj->ConvertToPolyObj(true/*bCombine*/, false);
634 
635  if(pConvObj)
636  {
637  SdrObjList* pOL = pConvObj->GetSubList();
638 
639  if(pOL)
640  {
642 
643  while(aIter.IsMore())
644  {
645  SdrObject* pObj1 = aIter.Next();
646  pPath = dynamic_cast<SdrPathObj*>( pObj1 );
647 
648  if(pPath)
649  {
650  aRetval.append(pPath->GetPathPoly());
651  }
652  }
653  }
654  else
655  {
656  pPath = dynamic_cast<SdrPathObj*>( pConvObj.get() );
657 
658  if(pPath)
659  {
660  aRetval = pPath->GetPathPoly();
661  }
662  }
663  }
664  }
665 
666  return aRetval;
667 }
668 
670 {
671  SdrObjList* pOL = pObj->GetSubList();
672 
673  if(pOL && !pObj->Is3DObj())
674  {
675  basegfx::B2DPolyPolygon aRetval;
677 
678  while(aIter.IsMore())
679  {
680  SdrObject* pObj1 = aIter.Next();
681  aRetval.append(ImpGetPolyPolygon1(pObj1));
682  }
683 
684  return aRetval;
685  }
686  else
687  {
688  return ImpGetPolyPolygon1(pObj);
689  }
690 }
691 
693 {
694  const sal_uInt32 nPolyCount(rPolyPolygon.count());
695 
696  if(0 == nPolyCount)
697  {
698  return basegfx::B2DPolygon();
699  }
700  else if(1 == nPolyCount)
701  {
702  return rPolyPolygon.getB2DPolygon(0);
703  }
704  else
705  {
706  basegfx::B2DPolygon aRetval(rPolyPolygon.getB2DPolygon(0));
707 
708  for(sal_uInt32 a(1); a < nPolyCount; a++)
709  {
710  basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a));
711 
712  if(aRetval.count())
713  {
714  if(aCandidate.count())
715  {
716  const basegfx::B2DPoint aCA(aCandidate.getB2DPoint(0));
717  const basegfx::B2DPoint aCB(aCandidate.getB2DPoint(aCandidate.count() - 1));
718  const basegfx::B2DPoint aRA(aRetval.getB2DPoint(0));
719  const basegfx::B2DPoint aRB(aRetval.getB2DPoint(aRetval.count() - 1));
720 
721  const double fRACA(basegfx::B2DVector(aCA - aRA).getLength());
722  const double fRACB(basegfx::B2DVector(aCB - aRA).getLength());
723  const double fRBCA(basegfx::B2DVector(aCA - aRB).getLength());
724  const double fRBCB(basegfx::B2DVector(aCB - aRB).getLength());
725 
726  const double fSmallestRA(std::min(fRACA, fRACB));
727  const double fSmallestRB(std::min(fRBCA, fRBCB));
728 
729  if(fSmallestRA < fSmallestRB)
730  {
731  // flip result
732  aRetval.flip();
733  }
734 
735  const double fSmallestCA(std::min(fRACA, fRBCA));
736  const double fSmallestCB(std::min(fRACB, fRBCB));
737 
738  if(fSmallestCB < fSmallestCA)
739  {
740  // flip candidate
741  aCandidate.flip();
742  }
743 
744  // append candidate to retval
745  aRetval.append(aCandidate);
746  }
747  }
748  else
749  {
750  aRetval = aCandidate;
751  }
752  }
753 
754  return aRetval;
755  }
756 }
757 
758 namespace {
759 
760 // for distribution dialog function
761 struct ImpDistributeEntry
762 {
763  SdrObject* mpObj;
764  sal_Int32 mnPos;
765  sal_Int32 mnLength;
766 };
767 
768 }
769 
770 typedef std::vector<ImpDistributeEntry> ImpDistributeEntryList;
771 
773 {
774  const size_t nMark(GetMarkedObjectCount());
775 
776  if(nMark <= 2)
777  return;
778 
781 
782  switch (SlotID)
783  {
784  case SID_DISTRIBUTE_HLEFT: eHor = SvxDistributeHorizontal::Left; break;
785  case SID_DISTRIBUTE_HCENTER: eHor = SvxDistributeHorizontal::Center; break;
786  case SID_DISTRIBUTE_HDISTANCE: eHor = SvxDistributeHorizontal::Distance; break;
787  case SID_DISTRIBUTE_HRIGHT: eHor = SvxDistributeHorizontal::Right; break;
788  case SID_DISTRIBUTE_VTOP: eVer = SvxDistributeVertical::Top; break;
789  case SID_DISTRIBUTE_VCENTER: eVer = SvxDistributeVertical::Center; break;
790  case SID_DISTRIBUTE_VDISTANCE: eVer = SvxDistributeVertical::Distance; break;
791  case SID_DISTRIBUTE_VBOTTOM: eVer = SvxDistributeVertical::Bottom; break;
792  }
793 
794  ImpDistributeEntryList aEntryList;
795  ImpDistributeEntryList::iterator itEntryList;
796  sal_uInt32 nFullLength;
797 
798  const bool bUndo = IsUndoEnabled();
799  if( bUndo )
800  BegUndo();
801 
803  {
804  // build sorted entry list
805  nFullLength = 0;
806 
807  for( size_t a = 0; a < nMark; ++a )
808  {
809  SdrMark* pMark = GetSdrMarkByIndex(a);
810  ImpDistributeEntry aNew;
811 
812  aNew.mpObj = pMark->GetMarkedSdrObj();
813 
814  switch(eHor)
815  {
817  {
818  aNew.mnPos = aNew.mpObj->GetSnapRect().Left();
819  break;
820  }
822  {
823  aNew.mnPos = (aNew.mpObj->GetSnapRect().Right() + aNew.mpObj->GetSnapRect().Left()) / 2;
824  break;
825  }
827  {
828  aNew.mnLength = aNew.mpObj->GetSnapRect().GetWidth() + 1;
829  nFullLength += aNew.mnLength;
830  aNew.mnPos = (aNew.mpObj->GetSnapRect().Right() + aNew.mpObj->GetSnapRect().Left()) / 2;
831  break;
832  }
834  {
835  aNew.mnPos = aNew.mpObj->GetSnapRect().Right();
836  break;
837  }
838  default: break;
839  }
840 
841  itEntryList = std::find_if(aEntryList.begin(), aEntryList.end(),
842  [&aNew](const ImpDistributeEntry& rEntry) { return rEntry.mnPos >= aNew.mnPos; });
843  if ( itEntryList < aEntryList.end() )
844  aEntryList.insert( itEntryList, aNew );
845  else
846  aEntryList.push_back( aNew );
847  }
848 
850  {
851  // calculate room in-between
852  sal_Int32 nWidth = GetAllMarkedBoundRect().GetWidth() + 1;
853  double fStepWidth = (static_cast<double>(nWidth) - static_cast<double>(nFullLength)) / static_cast<double>(aEntryList.size() - 1);
854  double fStepStart = static_cast<double>(aEntryList[ 0 ].mnPos);
855  fStepStart += fStepWidth + static_cast<double>((aEntryList[ 0 ].mnLength + aEntryList[ 1 ].mnLength) / 2);
856 
857  // move entries 1..n-1
858  for( size_t i = 1, n = aEntryList.size()-1; i < n; ++i )
859  {
860  ImpDistributeEntry& rCurr = aEntryList[ i ];
861  ImpDistributeEntry& rNext = aEntryList[ i + 1];
862  sal_Int32 nDelta = static_cast<sal_Int32>(fStepStart + 0.5) - rCurr.mnPos;
863  if( bUndo )
864  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*rCurr.mpObj));
865  rCurr.mpObj->Move(Size(nDelta, 0));
866  fStepStart += fStepWidth + static_cast<double>((rCurr.mnLength + rNext.mnLength) / 2);
867  }
868  }
869  else
870  {
871  // calculate distances
872  sal_Int32 nWidth = aEntryList[ aEntryList.size() - 1 ].mnPos - aEntryList[ 0 ].mnPos;
873  double fStepWidth = static_cast<double>(nWidth) / static_cast<double>(aEntryList.size() - 1);
874  double fStepStart = static_cast<double>(aEntryList[ 0 ].mnPos);
875  fStepStart += fStepWidth;
876 
877  // move entries 1..n-1
878  for( size_t i = 1 ; i < aEntryList.size()-1 ; ++i )
879  {
880  ImpDistributeEntry& rCurr = aEntryList[ i ];
881  sal_Int32 nDelta = static_cast<sal_Int32>(fStepStart + 0.5) - rCurr.mnPos;
882  if( bUndo )
883  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*rCurr.mpObj));
884  rCurr.mpObj->Move(Size(nDelta, 0));
885  fStepStart += fStepWidth;
886  }
887  }
888 
889  // clear list
890  aEntryList.clear();
891  }
892 
893  if(eVer != SvxDistributeVertical::NONE)
894  {
895  // build sorted entry list
896  nFullLength = 0;
897 
898  for( size_t a = 0; a < nMark; ++a )
899  {
900  SdrMark* pMark = GetSdrMarkByIndex(a);
901  ImpDistributeEntry aNew;
902 
903  aNew.mpObj = pMark->GetMarkedSdrObj();
904 
905  switch(eVer)
906  {
908  {
909  aNew.mnPos = aNew.mpObj->GetSnapRect().Top();
910  break;
911  }
913  {
914  aNew.mnPos = (aNew.mpObj->GetSnapRect().Bottom() + aNew.mpObj->GetSnapRect().Top()) / 2;
915  break;
916  }
918  {
919  aNew.mnLength = aNew.mpObj->GetSnapRect().GetHeight() + 1;
920  nFullLength += aNew.mnLength;
921  aNew.mnPos = (aNew.mpObj->GetSnapRect().Bottom() + aNew.mpObj->GetSnapRect().Top()) / 2;
922  break;
923  }
925  {
926  aNew.mnPos = aNew.mpObj->GetSnapRect().Bottom();
927  break;
928  }
929  default: break;
930  }
931 
932  itEntryList = std::find_if(aEntryList.begin(), aEntryList.end(),
933  [&aNew](const ImpDistributeEntry& rEntry) { return rEntry.mnPos >= aNew.mnPos; });
934  if ( itEntryList < aEntryList.end() )
935  aEntryList.insert( itEntryList, aNew );
936  else
937  aEntryList.push_back( aNew );
938  }
939 
941  {
942  // calculate room in-between
943  sal_Int32 nHeight = GetAllMarkedBoundRect().GetHeight() + 1;
944  double fStepWidth = (static_cast<double>(nHeight) - static_cast<double>(nFullLength)) / static_cast<double>(aEntryList.size() - 1);
945  double fStepStart = static_cast<double>(aEntryList[ 0 ].mnPos);
946  fStepStart += fStepWidth + static_cast<double>((aEntryList[ 0 ].mnLength + aEntryList[ 1 ].mnLength) / 2);
947 
948  // move entries 1..n-1
949  for( size_t i = 1, n = aEntryList.size()-1; i < n; ++i)
950  {
951  ImpDistributeEntry& rCurr = aEntryList[ i ];
952  ImpDistributeEntry& rNext = aEntryList[ i + 1 ];
953  sal_Int32 nDelta = static_cast<sal_Int32>(fStepStart + 0.5) - rCurr.mnPos;
954  if( bUndo )
955  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*rCurr.mpObj));
956  rCurr.mpObj->Move(Size(0, nDelta));
957  fStepStart += fStepWidth + static_cast<double>((rCurr.mnLength + rNext.mnLength) / 2);
958  }
959  }
960  else
961  {
962  // calculate distances
963  sal_Int32 nHeight = aEntryList[ aEntryList.size() - 1 ].mnPos - aEntryList[ 0 ].mnPos;
964  double fStepWidth = static_cast<double>(nHeight) / static_cast<double>(aEntryList.size() - 1);
965  double fStepStart = static_cast<double>(aEntryList[ 0 ].mnPos);
966  fStepStart += fStepWidth;
967 
968  // move entries 1..n-1
969  for(size_t i = 1, n = aEntryList.size()-1; i < n; ++i)
970  {
971  ImpDistributeEntry& rCurr = aEntryList[ i ];
972  sal_Int32 nDelta = static_cast<sal_Int32>(fStepStart + 0.5) - rCurr.mnPos;
973  if( bUndo )
974  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*rCurr.mpObj));
975  rCurr.mpObj->Move(Size(0, nDelta));
976  fStepStart += fStepWidth;
977  }
978  }
979 
980  // clear list
981  aEntryList.clear();
982  }
983 
984  // UNDO-Comment and end of UNDO
985  mpModel->SetUndoComment(SvxResId(STR_DistributeMarkedObjects));
986 
987  if( bUndo )
988  EndUndo();
989 }
990 
992 {
993  // #i73441# check content
994  if(!AreObjectsMarked())
995  return;
996 
997  SdrMarkList aRemove;
998  SortMarkedObjects();
999 
1000  const bool bUndo = IsUndoEnabled();
1001 
1002  if( bUndo )
1003  BegUndo();
1004 
1005  size_t nInsPos = SAL_MAX_SIZE;
1006  const SdrObject* pAttrObj = nullptr;
1007  basegfx::B2DPolyPolygon aMergePolyPolygonA;
1008  basegfx::B2DPolyPolygon aMergePolyPolygonB;
1009 
1010  SdrObjList* pInsOL = nullptr;
1011  SdrPageView* pInsPV = nullptr;
1012  bool bFirstObjectComplete(false);
1013 
1014  // make sure selected objects are contour objects
1015  // since now basegfx::utils::adaptiveSubdivide() is used, it is no longer
1016  // necessary to use ConvertMarkedToPolyObj which will subdivide curves using the old
1017  // mechanisms. In a next step the polygon clipper will even be able to clip curves...
1018  // ConvertMarkedToPolyObj(true);
1019  ConvertMarkedToPathObj(true);
1020  OSL_ENSURE(AreObjectsMarked(), "no more objects selected after preparations (!)");
1021 
1022  for(size_t a=0; a<GetMarkedObjectCount(); ++a)
1023  {
1024  SdrMark* pM = GetSdrMarkByIndex(a);
1025  SdrObject* pObj = pM->GetMarkedSdrObj();
1026 
1027  if(ImpCanConvertForCombine(pObj))
1028  {
1029  if(!pAttrObj)
1030  pAttrObj = pObj;
1031 
1032  nInsPos = pObj->GetOrdNum() + 1;
1033  pInsPV = pM->GetPageView();
1034  pInsOL = pObj->getParentSdrObjListFromSdrObject();
1035 
1036  // #i76891# use single iteration from SJ here which works on SdrObjects and takes
1037  // groups into account by itself
1039 
1040  while(aIter.IsMore())
1041  {
1042  SdrObject* pCandidate = aIter.Next();
1043  SdrPathObj* pPathObj = dynamic_cast<SdrPathObj*>( pCandidate );
1044  if(pPathObj)
1045  {
1046  basegfx::B2DPolyPolygon aTmpPoly(pPathObj->GetPathPoly());
1047 
1048  // #i76891# unfortunately ConvertMarkedToPathObj has converted all
1049  // involved polygon data to curve segments, even if not necessary.
1050  // It is better to try to reduce to more simple polygons.
1051  aTmpPoly = basegfx::utils::simplifyCurveSegments(aTmpPoly);
1052 
1053  // for each part polygon as preparation, remove self-intersections
1054  // correct orientations and get rid of possible neutral polygons.
1055  aTmpPoly = basegfx::utils::prepareForPolygonOperation(aTmpPoly);
1056 
1057  if(!bFirstObjectComplete)
1058  {
1059  // #i111987# Also need to collect ORed source shape when more than
1060  // a single polygon is involved
1061  if(aMergePolyPolygonA.count())
1062  {
1063  aMergePolyPolygonA = basegfx::utils::solvePolygonOperationOr(aMergePolyPolygonA, aTmpPoly);
1064  }
1065  else
1066  {
1067  aMergePolyPolygonA = aTmpPoly;
1068  }
1069  }
1070  else
1071  {
1072  if(aMergePolyPolygonB.count())
1073  {
1074  // to topologically correctly collect the 2nd polygon
1075  // group it is necessary to OR the parts (each is seen as
1076  // XOR-FillRule polygon and they are drawn over each-other)
1077  aMergePolyPolygonB = basegfx::utils::solvePolygonOperationOr(aMergePolyPolygonB, aTmpPoly);
1078  }
1079  else
1080  {
1081  aMergePolyPolygonB = aTmpPoly;
1082  }
1083  }
1084  }
1085  }
1086 
1087  // was there something added to the first polygon?
1088  if(!bFirstObjectComplete && aMergePolyPolygonA.count())
1089  {
1090  bFirstObjectComplete = true;
1091  }
1092 
1093  // move object to temporary delete list
1094  aRemove.InsertEntry(SdrMark(pObj, pM->GetPageView()));
1095  }
1096  }
1097 
1098  switch(eMode)
1099  {
1100  case SdrMergeMode::Merge:
1101  {
1102  // merge all contained parts (OR)
1103  aMergePolyPolygonA = basegfx::utils::solvePolygonOperationOr(aMergePolyPolygonA, aMergePolyPolygonB);
1104  break;
1105  }
1107  {
1108  // Subtract B from A
1109  aMergePolyPolygonA = basegfx::utils::solvePolygonOperationDiff(aMergePolyPolygonA, aMergePolyPolygonB);
1110  break;
1111  }
1113  {
1114  // AND B and A
1115  aMergePolyPolygonA = basegfx::utils::solvePolygonOperationAnd(aMergePolyPolygonA, aMergePolyPolygonB);
1116  break;
1117  }
1118  }
1119 
1120  // #i73441# check insert list before taking actions
1121  if(pInsOL)
1122  {
1123  SdrPathObj* pPath = new SdrPathObj(pAttrObj->getSdrModelFromSdrObject(), SdrObjKind::PathFill, aMergePolyPolygonA);
1124  ImpCopyAttributes(pAttrObj, pPath);
1125  pInsOL->InsertObject(pPath, nInsPos);
1126  if( bUndo )
1127  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath));
1128 
1129  // #i124760# To have a correct selection with only the new object it is necessary to
1130  // unmark all objects first. If not doing so, there may remain invalid pointers to objects
1131  // TTTT:Not needed for aw080 (!)
1132  UnmarkAllObj(pInsPV);
1133 
1134  MarkObj(pPath, pInsPV, false, true);
1135  }
1136 
1137  aRemove.ForceSort();
1138  switch(eMode)
1139  {
1140  case SdrMergeMode::Merge:
1141  {
1142  SetUndoComment(
1143  SvxResId(STR_EditMergeMergePoly),
1144  aRemove.GetMarkDescription());
1145  break;
1146  }
1148  {
1149  SetUndoComment(
1150  SvxResId(STR_EditMergeSubstractPoly),
1151  aRemove.GetMarkDescription());
1152  break;
1153  }
1155  {
1156  SetUndoComment(
1157  SvxResId(STR_EditMergeIntersectPoly),
1158  aRemove.GetMarkDescription());
1159  break;
1160  }
1161  }
1162  DeleteMarkedList(aRemove);
1163 
1164  if( bUndo )
1165  EndUndo();
1166 }
1167 
1169 {
1170  const SdrMarkList& rMarkList = GetMarkedObjectList();
1171  size_t nMarked = rMarkList.GetMarkCount();
1172 
1173  if (nMarked < 2)
1174  return;
1175 
1176  size_t nLastSelected = 0;
1177  sal_Int64 nLastSelectedTime = rMarkList.GetMark(0)->getTimeStamp();
1178  for (size_t a = 1; a < nMarked; ++a)
1179  {
1180  sal_Int64 nCandidateTime = rMarkList.GetMark(a)->getTimeStamp();
1181  if (nCandidateTime > nLastSelectedTime)
1182  {
1183  nLastSelectedTime = nCandidateTime;
1184  nLastSelected = a;
1185  }
1186  }
1187 
1188  SdrObject* pLastSelectedObj = rMarkList.GetMark(nLastSelected)->GetMarkedSdrObj();
1189  Size aLastRectSize(pLastSelectedObj->GetLogicRect().GetSize());
1190 
1191  const bool bUndo = IsUndoEnabled();
1192 
1193  if (bUndo)
1194  BegUndo();
1195 
1196  for (size_t a = 0; a < nMarked; ++a)
1197  {
1198  if (a == nLastSelected)
1199  continue;
1200  SdrMark* pM = rMarkList.GetMark(a);
1201  SdrObject* pObj = pM->GetMarkedSdrObj();
1202  tools::Rectangle aLogicRect(pObj->GetLogicRect());
1203  Size aLogicRectSize(aLogicRect.GetSize());
1204  if (bWidth)
1205  aLogicRectSize.setWidth( aLastRectSize.Width() );
1206  else
1207  aLogicRectSize.setHeight( aLastRectSize.Height() );
1208  aLogicRect.SetSize(aLogicRectSize);
1209  if (bUndo)
1210  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
1211  pObj->SetLogicRect(aLogicRect);
1212  }
1213 
1214  SetUndoComment(
1215  SvxResId(bWidth ? STR_EqualizeWidthMarkedObjects : STR_EqualizeHeightMarkedObjects),
1216  rMarkList.GetMarkDescription());
1217 
1218  if (bUndo)
1219  EndUndo();
1220 }
1221 
1223 {
1224  SdrPageView* pPageView = GetSdrPageView();
1225  if ( !pPageView || pPageView->IsLayerLocked( GetActiveLayer() ) )
1226  return;
1227 
1228  bool bUndo = IsUndoEnabled();
1229 
1230  // Undo-String will be set later
1231  if ( bUndo )
1232  BegUndo();
1233 
1234  SdrOutliner& rDrawOutliner = getSdrModelFromSdrView().GetDrawOutliner();
1235 
1236  SdrObjListIter aIter( GetMarkedObjectList(), SdrIterMode::Flat);
1237  while ( aIter.IsMore() )
1238  {
1239  SdrObject* pObj = aIter.Next();
1240  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( pObj );
1241  const OutlinerParaObject* pOPO = pTextObj ? pTextObj->GetOutlinerParaObject() : nullptr;
1242  if ( pOPO && pTextObj->IsTextFrame()
1243  && pTextObj->GetObjIdentifier() == SdrObjKind::Text // not callouts (OBJ_CAPTION)
1244  && !pTextObj->IsOutlText() // not impress presentation objects
1245  && pTextObj->GetMergedItem(XATTR_FORMTXTSTYLE).GetValue() == XFormTextStyle::NONE // not Fontwork
1246  )
1247  {
1248  // if the last paragraph does not end in paragraph-end punctuation (ignoring whitespace),
1249  // assume this text should be added to the end of the last paragraph, instead of starting a new paragraph.
1250  const sal_Int32 nPara = rDrawOutliner.GetParagraphCount();
1251  const OUString sLastPara = nPara ? rDrawOutliner.GetText( rDrawOutliner.GetParagraph( nPara - 1 ) ) : "";
1252  sal_Int32 n = sLastPara.getLength();
1253  while ( n && unicode::isWhiteSpace( sLastPara[--n] ) )
1254  ;
1255  //TODO: find way to use Locale to identify sentence final punctuation. Copied IsSentenceAtEnd() from autofmt.cxx
1256  const bool bAppend = !n || ( sLastPara[n] != '.' && sLastPara[n] != '?' && sLastPara[n] != '!' );
1257  rDrawOutliner.AddText( *pOPO, bAppend );
1258  }
1259  else
1260  {
1261  // Unmark non-textboxes, because all marked objects are deleted at the end. AdjustMarkHdl later.
1262  MarkObj(pObj, pPageView, /*bUnmark=*/true, /*bImpNoSetMarkHdl=*/true);
1263  }
1264  }
1265 
1266  MarkListHasChanged();
1267  AdjustMarkHdl();
1268 
1269  if ( GetMarkedObjectCount() > 1 )
1270  {
1271  SdrRectObj* pReplacement = new SdrRectObj( getSdrModelFromSdrView(), SdrObjKind::Text );
1272  pReplacement->SetOutlinerParaObject( rDrawOutliner.CreateParaObject() );
1273  pReplacement->SetSnapRect( GetMarkedObjRect() );
1274 
1276  if ( InsertObjectAtView( pReplacement, *pPageView, nFlags ) )
1277  DeleteMarkedObj();
1278  }
1279 
1280  if ( bUndo )
1281  EndUndo();
1282 
1283  return;
1284 }
1285 
1287 {
1288  // #105899# Start of Combine-Undo put to front, else ConvertMarkedToPolyObj would
1289  // create a 2nd Undo-action and Undo-Comment.
1290 
1291  bool bUndo = IsUndoEnabled();
1292 
1293  // Undo-String will be set later
1294  if( bUndo )
1295  BegUndo("", "", bNoPolyPoly ? SdrRepeatFunc::CombineOnePoly : SdrRepeatFunc::CombinePolyPoly);
1296 
1297  // #105899# First, guarantee that all objects are converted to polyobjects,
1298  // especially for SdrGrafObj with bitmap filling this is necessary to not
1299  // lose the bitmap filling.
1300 
1301  // #i12392#
1302  // ConvertMarkedToPolyObj was too strong here, it will lose quality and
1303  // information when curve objects are combined. This can be replaced by
1304  // using ConvertMarkedToPathObj without changing the previous fix.
1305 
1306  // #i21250#
1307  // Instead of simply passing true as LineToArea, use bNoPolyPoly as info
1308  // if this command is a 'Combine' or a 'Connect' command. On Connect it's true.
1309  // To not concert line segments with a set line width to polygons in that case,
1310  // use this info. Do not convert LineToArea on Connect commands.
1311  // ConvertMarkedToPathObj(!bNoPolyPoly);
1312 
1313  // This is used for Combine and Connect. In no case it is necessary to force
1314  // the content to curve, but it is also not good to force to polygons. Thus,
1315  // curve is the less information losing one. Remember: This place is not
1316  // used for merge.
1317  // LineToArea is never necessary, both commands are able to take over the
1318  // set line style and to display it correctly. Thus, i will use a
1319  // ConvertMarkedToPathObj with a false in any case. Only drawback is that
1320  // simple polygons will be changed to curves, but with no information loss.
1321  ConvertMarkedToPathObj(false /* bLineToArea */);
1322 
1323  // continue as before
1324  basegfx::B2DPolyPolygon aPolyPolygon;
1325  SdrObjList* pCurrentOL = nullptr;
1326  SdrMarkList aRemoveBuffer;
1327 
1328  SortMarkedObjects();
1329  size_t nInsPos = SAL_MAX_SIZE;
1330  SdrObjList* pInsOL = nullptr;
1331  SdrPageView* pInsPV = nullptr;
1332  const SdrObject* pAttrObj = nullptr;
1333 
1334  for(size_t a = GetMarkedObjectCount(); a; )
1335  {
1336  --a;
1337  SdrMark* pM = GetSdrMarkByIndex(a);
1338  SdrObject* pObj = pM->GetMarkedSdrObj();
1339  SdrObjList* pThisOL = pObj->getParentSdrObjListFromSdrObject();
1340 
1341  if(pCurrentOL != pThisOL)
1342  {
1343  pCurrentOL = pThisOL;
1344  }
1345 
1346  if(ImpCanConvertForCombine(pObj))
1347  {
1348  // remember objects to be able to copy attributes
1349  pAttrObj = pObj;
1350 
1351  // unfortunately ConvertMarkedToPathObj has converted all
1352  // involved polygon data to curve segments, even if not necessary.
1353  // It is better to try to reduce to more simple polygons.
1354  basegfx::B2DPolyPolygon aTmpPoly(basegfx::utils::simplifyCurveSegments(ImpGetPolyPolygon(pObj)));
1355  aPolyPolygon.insert(0, aTmpPoly);
1356 
1357  if(!pInsOL)
1358  {
1359  nInsPos = pObj->GetOrdNum() + 1;
1360  pInsPV = pM->GetPageView();
1361  pInsOL = pObj->getParentSdrObjListFromSdrObject();
1362  }
1363 
1364  aRemoveBuffer.InsertEntry(SdrMark(pObj, pM->GetPageView()));
1365  }
1366  }
1367 
1368  if(bNoPolyPoly)
1369  {
1370  basegfx::B2DPolygon aCombinedPolygon(ImpCombineToSinglePolygon(aPolyPolygon));
1371  aPolyPolygon.clear();
1372  aPolyPolygon.append(aCombinedPolygon);
1373  }
1374 
1375  const sal_uInt32 nPolyCount(aPolyPolygon.count());
1376 
1377  if (nPolyCount && pAttrObj)
1378  {
1380 
1381  if(nPolyCount > 1)
1382  {
1383  aPolyPolygon.setClosed(true);
1384  }
1385  else
1386  {
1387  // check for Polyline
1388  const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(0));
1389  const sal_uInt32 nPointCount(aPolygon.count());
1390 
1391  if(nPointCount <= 2)
1392  {
1393  eKind = SdrObjKind::PathLine;
1394  }
1395  else
1396  {
1397  if(!aPolygon.isClosed())
1398  {
1399  const basegfx::B2DPoint aPointA(aPolygon.getB2DPoint(0));
1400  const basegfx::B2DPoint aPointB(aPolygon.getB2DPoint(nPointCount - 1));
1401  const double fDistance(basegfx::B2DVector(aPointB - aPointA).getLength());
1402  const double fJoinTolerance(10.0);
1403 
1404  if(fDistance < fJoinTolerance)
1405  {
1406  aPolyPolygon.setClosed(true);
1407  }
1408  else
1409  {
1410  eKind = SdrObjKind::PathLine;
1411  }
1412  }
1413  }
1414  }
1415 
1416  SdrPathObj* pPath = new SdrPathObj(pAttrObj->getSdrModelFromSdrObject(), eKind, aPolyPolygon);
1417 
1418  // attributes of the lowest object
1419  ImpCopyAttributes(pAttrObj, pPath);
1420 
1421  // If LineStyle of pAttrObj is drawing::LineStyle_NONE force to drawing::LineStyle_SOLID to make visible.
1422  const drawing::LineStyle eLineStyle = pAttrObj->GetMergedItem(XATTR_LINESTYLE).GetValue();
1423  const drawing::FillStyle eFillStyle = pAttrObj->GetMergedItem(XATTR_FILLSTYLE).GetValue();
1424 
1425  // Take fill style/closed state of pAttrObj in account when deciding to change the line style
1426  bool bIsClosedPathObj = false;
1427  if (auto pPathObj = dynamic_cast<const SdrPathObj*>(pAttrObj))
1428  if (pPathObj->IsClosed())
1429  bIsClosedPathObj = true;
1430 
1431  if(drawing::LineStyle_NONE == eLineStyle && (drawing::FillStyle_NONE == eFillStyle || !bIsClosedPathObj))
1432  {
1433  pPath->SetMergedItem(XLineStyleItem(drawing::LineStyle_SOLID));
1434  }
1435 
1436  pInsOL->InsertObject(pPath,nInsPos);
1437  if( bUndo )
1438  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath));
1439 
1440  // Here was a severe error: Without UnmarkAllObj, the new object was marked
1441  // additionally to the two ones which are deleted below. As long as those are
1442  // in the UNDO there is no problem, but as soon as they get deleted, the
1443  // MarkList will contain deleted objects -> GPF.
1444  UnmarkAllObj(pInsPV);
1445  MarkObj(pPath, pInsPV, false, true);
1446  }
1447 
1448  // build an UndoComment from the objects actually used
1449  aRemoveBuffer.ForceSort(); // important for remove (see below)
1450  if( bUndo )
1451  SetUndoComment(SvxResId(bNoPolyPoly?STR_EditCombine_OnePoly:STR_EditCombine_PolyPoly),aRemoveBuffer.GetMarkDescription());
1452 
1453  // remove objects actually used from the list
1454  DeleteMarkedList(aRemoveBuffer);
1455  if( bUndo )
1456  EndUndo();
1457 }
1458 
1459 
1460 // Dismantle
1461 
1462 
1463 bool SdrEditView::ImpCanDismantle(const basegfx::B2DPolyPolygon& rPpolyPolygon, bool bMakeLines)
1464 {
1465  bool bCan(false);
1466  const sal_uInt32 nPolygonCount(rPpolyPolygon.count());
1467 
1468  if(nPolygonCount >= 2)
1469  {
1470  // #i69172# dismantle makes sense with 2 or more polygons in a polyPolygon
1471  bCan = true;
1472  }
1473  else if(bMakeLines && 1 == nPolygonCount)
1474  {
1475  // #i69172# ..or with at least 2 edges (curves or lines)
1476  const basegfx::B2DPolygon& aPolygon(rPpolyPolygon.getB2DPolygon(0));
1477  const sal_uInt32 nPointCount(aPolygon.count());
1478 
1479  if(nPointCount > 2)
1480  {
1481  bCan = true;
1482  }
1483  }
1484 
1485  return bCan;
1486 }
1487 
1488 bool SdrEditView::ImpCanDismantle(const SdrObject* pObj, bool bMakeLines)
1489 {
1490  bool bOtherObjs(false); // true=objects other than PathObj's existent
1491  bool bMin1PolyPoly(false); // true=at least 1 tools::PolyPolygon with more than one Polygon existent
1492  SdrObjList* pOL = pObj->GetSubList();
1493 
1494  if(pOL)
1495  {
1496  // group object -- check all members if they're PathObjs
1498 
1499  while(aIter.IsMore() && !bOtherObjs)
1500  {
1501  const SdrObject* pObj1 = aIter.Next();
1502  const SdrPathObj* pPath = dynamic_cast<const SdrPathObj*>( pObj1 );
1503 
1504  if(pPath)
1505  {
1506  if(ImpCanDismantle(pPath->GetPathPoly(), bMakeLines))
1507  {
1508  bMin1PolyPoly = true;
1509  }
1510 
1511  SdrObjTransformInfoRec aInfo;
1512  pObj1->TakeObjInfo(aInfo);
1513 
1514  if(!aInfo.bCanConvToPath)
1515  {
1516  // happens e. g. in the case of FontWork
1517  bOtherObjs = true;
1518  }
1519  }
1520  else
1521  {
1522  bOtherObjs = true;
1523  }
1524  }
1525  }
1526  else
1527  {
1528  const SdrPathObj* pPath = dynamic_cast<const SdrPathObj*>(pObj);
1529  const SdrObjCustomShape* pCustomShape = dynamic_cast<const SdrObjCustomShape*>(pObj);
1530 
1531  // #i37011#
1532  if(pPath)
1533  {
1534  if(ImpCanDismantle(pPath->GetPathPoly(),bMakeLines))
1535  {
1536  bMin1PolyPoly = true;
1537  }
1538 
1539  SdrObjTransformInfoRec aInfo;
1540  pObj->TakeObjInfo(aInfo);
1541 
1542  // new condition IsLine() to be able to break simple Lines
1543  if(!(aInfo.bCanConvToPath || aInfo.bCanConvToPoly) && !pPath->IsLine())
1544  {
1545  // happens e. g. in the case of FontWork
1546  bOtherObjs = true;
1547  }
1548  }
1549  else if(pCustomShape)
1550  {
1551  if(bMakeLines)
1552  {
1553  // allow break command
1554  bMin1PolyPoly = true;
1555  }
1556  }
1557  else
1558  {
1559  bOtherObjs = true;
1560  }
1561  }
1562  return bMin1PolyPoly && !bOtherObjs;
1563 }
1564 
1565 void SdrEditView::ImpDismantleOneObject(const SdrObject* pObj, SdrObjList& rOL, size_t& rPos, SdrPageView* pPV, bool bMakeLines)
1566 {
1567  const SdrPathObj* pSrcPath = dynamic_cast<const SdrPathObj*>( pObj );
1568  const SdrObjCustomShape* pCustomShape = dynamic_cast<const SdrObjCustomShape*>( pObj );
1569 
1570  const bool bUndo = IsUndoEnabled();
1571 
1572  if(pSrcPath)
1573  {
1574  // #i74631# redesigned due to XpolyPolygon removal and explicit constructors
1575  SdrObject* pLast = nullptr; // to be able to apply OutlinerParaObject
1576  const basegfx::B2DPolyPolygon& rPolyPolygon(pSrcPath->GetPathPoly());
1577  const sal_uInt32 nPolyCount(rPolyPolygon.count());
1578 
1579  for(sal_uInt32 a(0); a < nPolyCount; a++)
1580  {
1581  const basegfx::B2DPolygon& rCandidate(rPolyPolygon.getB2DPolygon(a));
1582  const sal_uInt32 nPointCount(rCandidate.count());
1583 
1584  if(!bMakeLines || nPointCount < 2)
1585  {
1586  SdrPathObj* pPath = new SdrPathObj(
1587  pSrcPath->getSdrModelFromSdrObject(),
1588  pSrcPath->GetObjIdentifier(),
1589  basegfx::B2DPolyPolygon(rCandidate));
1590  ImpCopyAttributes(pSrcPath, pPath);
1591  pLast = pPath;
1592  rOL.InsertObject(pPath, rPos);
1593  if( bUndo )
1594  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, true));
1595  MarkObj(pPath, pPV, false, true);
1596  rPos++;
1597  }
1598  else
1599  {
1600  const sal_uInt32 nLoopCount(rCandidate.isClosed() ? nPointCount : nPointCount - 1);
1601 
1602  for(sal_uInt32 b(0); b < nLoopCount; b++)
1603  {
1605  basegfx::B2DPolygon aNewPolygon;
1606  const sal_uInt32 nNextIndex((b + 1) % nPointCount);
1607 
1608  aNewPolygon.append(rCandidate.getB2DPoint(b));
1609 
1610  if(rCandidate.areControlPointsUsed())
1611  {
1612  aNewPolygon.appendBezierSegment(
1613  rCandidate.getNextControlPoint(b),
1614  rCandidate.getPrevControlPoint(nNextIndex),
1615  rCandidate.getB2DPoint(nNextIndex));
1616  eKind = SdrObjKind::PathLine;
1617  }
1618  else
1619  {
1620  aNewPolygon.append(rCandidate.getB2DPoint(nNextIndex));
1621  }
1622 
1623  SdrPathObj* pPath = new SdrPathObj(
1624  pSrcPath->getSdrModelFromSdrObject(),
1625  eKind,
1626  basegfx::B2DPolyPolygon(aNewPolygon));
1627  ImpCopyAttributes(pSrcPath, pPath);
1628  pLast = pPath;
1629  rOL.InsertObject(pPath, rPos);
1630  if( bUndo )
1631  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, true));
1632  MarkObj(pPath, pPV, false, true);
1633  rPos++;
1634  }
1635  }
1636  }
1637 
1638  if(pLast && pSrcPath->GetOutlinerParaObject())
1639  {
1640  pLast->SetOutlinerParaObject(*pSrcPath->GetOutlinerParaObject());
1641  }
1642  }
1643  else if(pCustomShape)
1644  {
1645  if(bMakeLines)
1646  {
1647  // break up custom shape
1648  const SdrObject* pReplacement = pCustomShape->GetSdrObjectFromCustomShape();
1649 
1650  if(pReplacement)
1651  {
1652  SdrObject* pCandidate(pReplacement->CloneSdrObject(pReplacement->getSdrModelFromSdrObject()));
1653  DBG_ASSERT(pCandidate, "SdrEditView::ImpDismantleOneObject: Could not clone SdrObject (!)");
1654 
1655  if(pCustomShape->GetMergedItem(SDRATTR_SHADOW).GetValue())
1656  {
1657  if(dynamic_cast<const SdrObjGroup*>( pReplacement) != nullptr)
1658  {
1659  pCandidate->SetMergedItem(makeSdrShadowItem(true));
1660  }
1661  }
1662 
1663  rOL.InsertObject(pCandidate, rPos);
1664  if( bUndo )
1665  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pCandidate, true));
1666  MarkObj(pCandidate, pPV, false, true);
1667 
1668  if(pCustomShape->HasText() && !pCustomShape->IsTextPath())
1669  {
1670  // #i37011# also create a text object and add at rPos + 1
1672  pCustomShape->getSdrModelFromSdrObject(),
1673  pCustomShape->GetObjInventor(),
1675 
1676  // Copy text content
1677  OutlinerParaObject* pParaObj = pCustomShape->GetOutlinerParaObject();
1678  if(pParaObj)
1679  {
1680  pTextObj->NbcSetOutlinerParaObject(*pParaObj);
1681  }
1682 
1683  // copy all attributes
1684  SfxItemSet aTargetItemSet(pCustomShape->GetMergedItemSet());
1685 
1686  // clear fill and line style
1687  aTargetItemSet.Put(XLineStyleItem(drawing::LineStyle_NONE));
1688  aTargetItemSet.Put(XFillStyleItem(drawing::FillStyle_NONE));
1689 
1690  // get the text bounds and set at text object
1691  tools::Rectangle aTextBounds = pCustomShape->GetSnapRect();
1692  if(pCustomShape->GetTextBounds(aTextBounds))
1693  {
1694  pTextObj->SetSnapRect(aTextBounds);
1695  }
1696 
1697  // if rotated, copy GeoStat, too.
1698  const GeoStat& rSourceGeo = pCustomShape->GetGeoStat();
1699  if(rSourceGeo.nRotationAngle)
1700  {
1701  pTextObj->NbcRotate(
1702  pCustomShape->GetSnapRect().Center(), rSourceGeo.nRotationAngle,
1703  rSourceGeo.mfSinRotationAngle, rSourceGeo.mfCosRotationAngle);
1704  }
1705 
1706  // set modified ItemSet at text object
1707  pTextObj->SetMergedItemSet(aTargetItemSet);
1708 
1709  // insert object
1710  rOL.InsertObject(pTextObj, rPos + 1);
1711  if( bUndo )
1712  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pTextObj, true));
1713  MarkObj(pTextObj, pPV, false, true);
1714  }
1715  }
1716  }
1717  }
1718 }
1719 
1721 {
1722  // temporary MarkList
1723  SdrMarkList aRemoveBuffer;
1724 
1725  SortMarkedObjects();
1726 
1727  const bool bUndo = IsUndoEnabled();
1728 
1729  if( bUndo )
1730  {
1731  // comment is constructed later
1732  BegUndo("", "", bMakeLines ? SdrRepeatFunc::DismantleLines : SdrRepeatFunc::DismantlePolys);
1733  }
1734 
1735  SdrObjList* pOL0=nullptr;
1736  for (size_t nm=GetMarkedObjectCount(); nm>0;) {
1737  --nm;
1738  SdrMark* pM=GetSdrMarkByIndex(nm);
1739  SdrObject* pObj=pM->GetMarkedSdrObj();
1740  SdrPageView* pPV=pM->GetPageView();
1742  if (pOL!=pOL0) { pOL0=pOL; pObj->GetOrdNum(); } // make sure OrdNums are correct!
1743  if (ImpCanDismantle(pObj,bMakeLines)) {
1744  aRemoveBuffer.InsertEntry(SdrMark(pObj,pM->GetPageView()));
1745  const size_t nPos0=pObj->GetOrdNumDirect();
1746  size_t nPos=nPos0+1;
1747  SdrObjList* pSubList=pObj->GetSubList();
1748  if (pSubList!=nullptr && !pObj->Is3DObj()) {
1749  SdrObjListIter aIter(pSubList,SdrIterMode::DeepNoGroups);
1750  while (aIter.IsMore()) {
1751  const SdrObject* pObj1=aIter.Next();
1752  ImpDismantleOneObject(pObj1,*pOL,nPos,pPV,bMakeLines);
1753  }
1754  } else {
1755  ImpDismantleOneObject(pObj,*pOL,nPos,pPV,bMakeLines);
1756  }
1757  if( bUndo )
1758  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj,true));
1759  pOL->RemoveObject(nPos0);
1760 
1761  if( !bUndo )
1762  SdrObject::Free(pObj);
1763  }
1764  }
1765 
1766  if( bUndo )
1767  {
1768  // construct UndoComment from objects actually used
1769  SetUndoComment(SvxResId(bMakeLines?STR_EditDismantle_Lines:STR_EditDismantle_Polys),aRemoveBuffer.GetMarkDescription());
1770  // remove objects actually used from the list
1771  EndUndo();
1772  }
1773 }
1774 
1775 
1776 // Group
1777 
1778 
1780 {
1781  if (!AreObjectsMarked())
1782  return;
1783 
1784  SortMarkedObjects();
1785 
1786  const bool bUndo = IsUndoEnabled();
1787  if( bUndo )
1788  {
1789  BegUndo(SvxResId(STR_EditGroup),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::Group);
1790 
1791  for(size_t nm = GetMarkedObjectCount(); nm>0; )
1792  {
1793  // add UndoActions for all affected objects
1794  --nm;
1795  SdrMark* pM=GetSdrMarkByIndex(nm);
1796  SdrObject* pObj = pM->GetMarkedSdrObj();
1797  AddUndoActions( CreateConnectorUndo( *pObj ) );
1798  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject( *pObj ));
1799  }
1800  }
1801 
1802  SdrMarkList aNewMark;
1803  SdrPageView* pPV = GetSdrPageView();
1804 
1805  if(pPV)
1806  {
1807  SdrObjList* pCurrentLst=pPV->GetObjList();
1808  SdrObjList* pSrcLst=pCurrentLst;
1809  SdrObjList* pSrcLst0=pSrcLst;
1810  // make sure OrdNums are correct
1811  if (pSrcLst->IsObjOrdNumsDirty())
1812  pSrcLst->RecalcObjOrdNums();
1813  SdrObject* pGrp=nullptr;
1814  SdrObjList* pDstLst=nullptr;
1815  // if all selected objects come from foreign object lists.
1816  // the group object is the last one in the list.
1817  size_t nInsPos=pSrcLst->GetObjCount();
1818  bool bNeedInsPos=true;
1819  for (size_t nm=GetMarkedObjectCount(); nm>0;)
1820  {
1821  --nm;
1822  SdrMark* pM=GetSdrMarkByIndex(nm);
1823  if (pM->GetPageView()==pPV)
1824  {
1825  SdrObject* pObj=pM->GetMarkedSdrObj();
1826  if (nullptr==pGrp)
1827  {
1828  pGrp = new SdrObjGroup(pObj->getSdrModelFromSdrObject());
1829  pDstLst=pGrp->GetSubList();
1830  DBG_ASSERT(pDstLst!=nullptr,"Alleged group object doesn't return object list.");
1831  }
1832  pSrcLst=pObj->getParentSdrObjListFromSdrObject();
1833  if (pSrcLst!=pSrcLst0)
1834  {
1835  if (pSrcLst->IsObjOrdNumsDirty())
1836  pSrcLst->RecalcObjOrdNums();
1837  }
1838  bool bForeignList=pSrcLst!=pCurrentLst;
1839  if (!bForeignList && bNeedInsPos)
1840  {
1841  nInsPos=pObj->GetOrdNum(); // this way, all ObjOrdNum of the page are set
1842  nInsPos++;
1843  bNeedInsPos=false;
1844  }
1845  pSrcLst->RemoveObject(pObj->GetOrdNumDirect());
1846  if (!bForeignList)
1847  nInsPos--; // correct InsertPos
1848  pDstLst->InsertObject(pObj,0);
1849  GetMarkedObjectListWriteAccess().DeleteMark(nm);
1850  pSrcLst0=pSrcLst;
1851  }
1852  }
1853  if (pGrp!=nullptr)
1854  {
1855  aNewMark.InsertEntry(SdrMark(pGrp,pPV));
1856  const size_t nCount=pDstLst->GetObjCount();
1857  pCurrentLst->InsertObject(pGrp,nInsPos);
1858  if( bUndo )
1859  {
1860  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pGrp,true)); // no recalculation!
1861  for (size_t no=0; no<nCount; ++no)
1862  {
1863  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pDstLst->GetObj(no)));
1864  }
1865  }
1866  }
1867  }
1868  GetMarkedObjectListWriteAccess().Merge(aNewMark);
1869  MarkListHasChanged();
1870 
1871  if( bUndo )
1872  EndUndo();
1873 }
1874 
1875 
1876 // Ungroup
1877 
1878 
1880 {
1881  SdrMarkList aNewMark;
1882 
1883  const bool bUndo = IsUndoEnabled();
1884  if( bUndo )
1885  BegUndo("", "", SdrRepeatFunc::Ungroup);
1886 
1887  size_t nCount=0;
1888  OUString aName1;
1889  OUString aName;
1890  bool bNameOk=false;
1891  for (size_t nm=GetMarkedObjectCount(); nm>0;) {
1892  --nm;
1893  SdrMark* pM=GetSdrMarkByIndex(nm);
1894  SdrObject* pGrp=pM->GetMarkedSdrObj();
1895  SdrObjList* pSrcLst=pGrp->GetSubList();
1896  if (pSrcLst!=nullptr) {
1897  nCount++;
1898  if (nCount==1) {
1899  aName = pGrp->TakeObjNameSingul(); // retrieve name of group
1900  aName1 = pGrp->TakeObjNamePlural(); // retrieve name of group
1901  bNameOk=true;
1902  } else {
1903  if (nCount==2) aName=aName1; // set plural name
1904  if (bNameOk) {
1905  OUString aStr(pGrp->TakeObjNamePlural()); // retrieve name of group
1906 
1907  if (aStr != aName)
1908  bNameOk = false;
1909  }
1910  }
1911  size_t nDstCnt=pGrp->GetOrdNum();
1912  SdrObjList* pDstLst=pM->GetPageView()->GetObjList();
1913  size_t nObjCount=pSrcLst->GetObjCount();
1914  auto* pGroup(dynamic_cast<SdrObjGroup*>(pGrp));
1915  const bool bIsDiagram(nullptr != pGroup && pGroup->isDiagram());
1916 
1917  // If the Group is a Diagram, it has a filler BG object to guarantee
1918  // the Diagam's dimensions. Identify that shape
1919  if(bIsDiagram && nObjCount)
1920  {
1921  SdrObject* pObj(pSrcLst->GetObj(0));
1922 
1923  if(nullptr != pObj && !pObj->IsGroupObject() &&
1924  !pObj->HasLineStyle() &&
1925  pObj->IsMoveProtect() && pObj->IsResizeProtect())
1926  {
1927  if(pObj->HasFillStyle())
1928  {
1929  // If it has FillStyle it is a useful object representing that possible
1930  // defined fill from oox import. In this case, we should remove the
1931  // Move/Resize protection to allow seamless further processing.
1932 
1933  // Undo of these is handled by SdrUndoGeoObj which holds a SdrObjGeoData,
1934  // create one
1935  if( bUndo )
1936  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
1937 
1938  pObj->SetMoveProtect(false);
1939  pObj->SetResizeProtect(false);
1940  }
1941  else
1942  {
1943  // If it has no FillStyle it is not useful for any further processing
1944  // but only was used as a placeholder, get directly rid of it
1945  if( bUndo )
1946  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj));
1947 
1948  pObj = pSrcLst->RemoveObject(0);
1949 
1950  if( !bUndo )
1951  SdrObject::Free(pObj);
1952 
1953  nObjCount = pSrcLst->GetObjCount();
1954  }
1955  }
1956  }
1957 
1958  // FIRST move contained objects to parent of group, so that
1959  // the contained objects are NOT migrated to the UNDO-ItemPool
1960  // when AddUndo(new SdrUndoDelObj(*pGrp)) is called.
1961  if( bUndo )
1962  {
1963  for (size_t no=nObjCount; no>0;)
1964  {
1965  no--;
1966  SdrObject* pObj=pSrcLst->GetObj(no);
1967  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject(*pObj));
1968  }
1969  }
1970 
1971  for (size_t no=0; no<nObjCount; ++no)
1972  {
1973  SdrObject* pObj=pSrcLst->RemoveObject(0);
1974  pDstLst->InsertObject(pObj,nDstCnt);
1975  if( bUndo )
1976  AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pObj,true));
1977  nDstCnt++;
1978  // No SortCheck when inserting into MarkList, because that would
1979  // provoke a RecalcOrdNums() each time because of pObj->GetOrdNum():
1980  aNewMark.InsertEntry(SdrMark(pObj,pM->GetPageView()),false);
1981  }
1982 
1983  if( bUndo )
1984  {
1985  // Now it is safe to add the delete-UNDO which triggers the
1986  // MigrateItemPool now only for itself, not for the sub-objects.
1987  // nDstCnt is right, because previous inserts move group
1988  // object deeper and increase nDstCnt.
1989  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pGrp));
1990  }
1991  pDstLst->RemoveObject(nDstCnt);
1992 
1993  if( !bUndo )
1994  SdrObject::Free(pGrp);
1995 
1996  GetMarkedObjectListWriteAccess().DeleteMark(nm);
1997  }
1998  }
1999  if (nCount!=0)
2000  {
2001  if (!bNameOk)
2002  aName=SvxResId(STR_ObjNamePluralGRUP); // Use the term "Group Objects," if different objects are grouped.
2003  SetUndoComment(SvxResId(STR_EditUngroup),aName);
2004  }
2005 
2006  if( bUndo )
2007  EndUndo();
2008 
2009  if (nCount!=0)
2010  {
2011  GetMarkedObjectListWriteAccess().Merge(aNewMark,true); // Because of the sorting above, aNewMark is reversed
2012  MarkListHasChanged();
2013  }
2014 }
2015 
2016 
2017 // ConvertToPoly
2018 
2019 
2020 SdrObject* SdrEditView::ImpConvertOneObj(SdrObject* pObj, bool bPath, bool bLineToArea)
2021 {
2022  SdrObjectUniquePtr pNewObj = pObj->ConvertToPolyObj(bPath, bLineToArea);
2023  if (pNewObj)
2024  {
2026  const bool bUndo = IsUndoEnabled();
2027  if( bUndo )
2028  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoReplaceObject(*pObj,*pNewObj));
2029 
2030  // ownership passed into here (despite the UniquePtr indicating that we are returning it)
2031  pOL->ReplaceObject(pNewObj.get(), pObj->GetOrdNum());
2032 
2033  if( !bUndo )
2034  SdrObject::Free(pObj);
2035  }
2036  return pNewObj.release();
2037 }
2038 
2039 void SdrEditView::ImpConvertTo(bool bPath, bool bLineToArea)
2040 {
2041  if (!AreObjectsMarked()) return;
2042 
2043  bool bMrkChg = false;
2044  const size_t nMarkCount=GetMarkedObjectCount();
2045  TranslateId pDscrID;
2046  if(bLineToArea)
2047  {
2048  if(nMarkCount == 1)
2049  pDscrID = STR_EditConvToContour;
2050  else
2051  pDscrID = STR_EditConvToContours;
2052 
2053  BegUndo(SvxResId(pDscrID), GetDescriptionOfMarkedObjects());
2054  }
2055  else
2056  {
2057  if (bPath) {
2058  if (nMarkCount==1) pDscrID=STR_EditConvToCurve;
2059  else pDscrID=STR_EditConvToCurves;
2060  BegUndo(SvxResId(pDscrID),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::ConvertToPath);
2061  } else {
2062  if (nMarkCount==1) pDscrID=STR_EditConvToPoly;
2063  else pDscrID=STR_EditConvToPolys;
2064  BegUndo(SvxResId(pDscrID),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::ConvertToPoly);
2065  }
2066  }
2067  for (size_t nm=nMarkCount; nm>0;) {
2068  --nm;
2069  SdrMark* pM=GetSdrMarkByIndex(nm);
2070  SdrObject* pObj=pM->GetMarkedSdrObj();
2071  SdrPageView* pPV=pM->GetPageView();
2072  if (pObj->IsGroupObject() && !pObj->Is3DObj()) {
2073  SdrObject* pGrp=pObj;
2075  while (aIter.IsMore()) {
2076  pObj=aIter.Next();
2077  ImpConvertOneObj(pObj,bPath,bLineToArea);
2078  }
2079  } else {
2080  SdrObject* pNewObj=ImpConvertOneObj(pObj,bPath,bLineToArea);
2081  if (pNewObj!=nullptr) {
2082  bMrkChg=true;
2083  GetMarkedObjectListWriteAccess().ReplaceMark(SdrMark(pNewObj,pPV),nm);
2084  }
2085  }
2086  }
2087  EndUndo();
2088  if (bMrkChg)
2089  {
2090  AdjustMarkHdl();
2091  MarkListHasChanged();
2092  }
2093 }
2094 
2096 {
2097  ImpConvertTo(true, bLineToArea);
2098 }
2099 
2101 {
2102  ImpConvertTo(false, false/*bLineToArea*/);
2103 }
2104 
2105 namespace
2106 {
2107  GDIMetaFile GetMetaFile(SdrGrafObj const * pGraf)
2108  {
2109  if (pGraf->HasGDIMetaFile())
2111  assert(pGraf->isEmbeddedVectorGraphicData());
2113  }
2114 }
2115 
2116 // Metafile Import
2118 {
2119  const bool bUndo = IsUndoEnabled();
2120 
2121  if( bUndo )
2122  BegUndo("", "", SdrRepeatFunc::ImportMtf);
2123 
2124  SortMarkedObjects();
2125  SdrMarkList aForTheDescription;
2126  SdrMarkList aNewMarked;
2127  for (size_t nm =GetMarkedObjectCount(); nm > 0; )
2128  {
2129  // create Undo objects for all new objects
2130  // check for cancellation between the metafiles
2131  if (pProgrInfo != nullptr)
2132  {
2133  pProgrInfo->SetNextObject();
2134  if (!pProgrInfo->ReportActions(0))
2135  break;
2136  }
2137 
2138  --nm;
2139  SdrMark* pM=GetSdrMarkByIndex(nm);
2140  SdrObject* pObj=pM->GetMarkedSdrObj();
2141  SdrPageView* pPV=pM->GetPageView();
2143  const size_t nInsPos=pObj->GetOrdNum()+1;
2144  size_t nInsCnt=0;
2145  tools::Rectangle aLogicRect;
2146 
2147  SdrGrafObj* pGraf = dynamic_cast<SdrGrafObj*>( pObj );
2148  if (pGraf != nullptr)
2149  {
2150  Graphic aGraphic = pGraf->GetGraphic();
2151  auto const & pVectorGraphicData = aGraphic.getVectorGraphicData();
2152 
2153  if (pVectorGraphicData && pVectorGraphicData->getType() == VectorGraphicDataType::Pdf)
2154  {
2155  auto pPdfium = vcl::pdf::PDFiumLibrary::get();
2156  if (pPdfium)
2157  {
2158  aLogicRect = pGraf->GetLogicRect();
2159  ImpSdrPdfImport aFilter(*mpModel, pObj->GetLayer(), aLogicRect, aGraphic);
2160  if (aGraphic.getPageNumber() < aFilter.GetPageCount())
2161  {
2162  nInsCnt = aFilter.DoImport(*pOL, nInsPos, aGraphic.getPageNumber(), pProgrInfo);
2163  }
2164  }
2165  }
2166  else if (pGraf->HasGDIMetaFile() || pGraf->isEmbeddedVectorGraphicData() )
2167  {
2168  GDIMetaFile aMetaFile(GetMetaFile(pGraf));
2169  if (aMetaFile.GetActionSize())
2170  {
2171  aLogicRect = pGraf->GetLogicRect();
2172  ImpSdrGDIMetaFileImport aFilter(*mpModel, pObj->GetLayer(), aLogicRect);
2173  nInsCnt = aFilter.DoImport(aMetaFile, *pOL, nInsPos, pProgrInfo);
2174  }
2175  }
2176  }
2177 
2178  SdrOle2Obj* pOle2 = dynamic_cast<SdrOle2Obj*>(pObj);
2179  if (pOle2 != nullptr && pOle2->GetGraphic())
2180  {
2181  aLogicRect = pOle2->GetLogicRect();
2182  ImpSdrGDIMetaFileImport aFilter(*mpModel, pObj->GetLayer(), aLogicRect);
2183  nInsCnt = aFilter.DoImport(pOle2->GetGraphic()->GetGDIMetaFile(), *pOL, nInsPos, pProgrInfo);
2184  }
2185 
2186  if (nInsCnt != 0)
2187  {
2188  // transformation
2189  GeoStat aGeoStat(pGraf ? pGraf->GetGeoStat() : pOle2->GetGeoStat());
2190  size_t nObj = nInsPos;
2191 
2192  if (aGeoStat.nShearAngle)
2193  aGeoStat.RecalcTan();
2194 
2195  if (aGeoStat.nRotationAngle)
2196  aGeoStat.RecalcSinCos();
2197 
2198  for (size_t i = 0; i < nInsCnt; i++)
2199  {
2200  if (bUndo)
2201  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pOL->GetObj(nObj)));
2202 
2203  // update new MarkList
2204  SdrObject* pCandidate = pOL->GetObj(nObj);
2205 
2206  // apply original transformation
2207  if (aGeoStat.nShearAngle)
2208  pCandidate->NbcShear(aLogicRect.TopLeft(), aGeoStat.nShearAngle, aGeoStat.mfTanShearAngle, false);
2209 
2210  if (aGeoStat.nRotationAngle)
2211  pCandidate->NbcRotate(aLogicRect.TopLeft(), aGeoStat.nRotationAngle, aGeoStat.mfSinRotationAngle, aGeoStat.mfCosRotationAngle);
2212 
2213  SdrMark aNewMark(pCandidate, pPV);
2214  aNewMarked.InsertEntry(aNewMark);
2215 
2216  nObj++;
2217  }
2218 
2219  aForTheDescription.InsertEntry(*pM);
2220 
2221  if (bUndo)
2222  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj));
2223 
2224  // remove object from selection and delete
2225  GetMarkedObjectListWriteAccess().DeleteMark(TryToFindMarkedObject(pObj));
2226  pOL->RemoveObject(nInsPos-1);
2227 
2228  if (!bUndo)
2229  SdrObject::Free(pObj);
2230  }
2231  }
2232 
2233  if (aNewMarked.GetMarkCount())
2234  {
2235  // create new selection
2236  for (size_t a = 0; a < aNewMarked.GetMarkCount(); ++a)
2237  {
2238  GetMarkedObjectListWriteAccess().InsertEntry(*aNewMarked.GetMark(a));
2239  }
2240 
2241  SortMarkedObjects();
2242  }
2243 
2244  if (bUndo)
2245  {
2246  SetUndoComment(SvxResId(STR_EditImportMtf),aForTheDescription.GetMarkDescription());
2247  EndUndo();
2248  }
2249 }
2250 
2251 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void ImpCheckToTopBtmPossible()
Definition: svdedtv2.cxx:487
void MovMarkedToBtm()
Definition: svdedtv2.cxx:159
GDIMetaFile getMetafileFromEmbeddedVectorGraphicData() const
Definition: svdograf.cxx:866
size_t DoImport(SdrObjList &rDestList, size_t nInsPos, int nPageNumber, SvdProgressInfo *pProgrInfo=nullptr)
Definition: svdpdf.cxx:216
virtual void TakeObjInfo(SdrObjTransformInfoRec &rInfo) const
Definition: svdobj.cxx:654
void append(const basegfx::B2DPoint &rPoint, sal_uInt32 nCount)
size_t GetMarkCount() const
Definition: svdmark.hxx:178
virtual const tools::Rectangle & GetCurrentBoundRect() const
Definition: svdobj.cxx:949
void PutMarkedInFrontOfObj(const SdrObject *pRefObj)
Definition: svdedtv2.cxx:254
constexpr sal_uInt16 SDRATTR_END(SDRATTR_TEXTCOLUMNS_LAST)
void setWidth(tools::Long nWidth)
virtual SdrObjKind GetObjIdentifier() const override
Definition: svdotext.cxx:463
static bool ImpCanDismantle(const basegfx::B2DPolyPolygon &rPpolyPpolygon, bool bMakeLines)
Definition: svdedtv2.cxx:1463
void EqualizeMarkedObjects(bool bWidth)
Definition: svdedtv2.cxx:1168
enum SAL_DLLPUBLIC_RTTI FillStyle
static bool ImpCanConvertForCombine1(const SdrObject *pObj)
Definition: svdedtv2.cxx:574
static basegfx::B2DPolyPolygon ImpGetPolyPolygon1(const SdrObject *pObj)
Definition: svdedtv2.cxx:622
void setClosed(bool bNew)
virtual void NbcRotate(const Point &rRef, Degree100 nAngle, double sn, double cs)
Definition: svdobj.cxx:1463
static bool ImpCanConvertForCombine(const SdrObject *pObj)
Definition: svdedtv2.cxx:592
constexpr TypedWhichId< XFillStyleItem > XATTR_FILLSTYLE(XATTR_FILL_FIRST)
bool IsTextFrame() const
Definition: svdotext.hxx:334
void SetNextObject()
Definition: svdetc.cxx:467
B2DPolyPolygon solvePolygonOperationOr(const B2DPolyPolygon &rCandidateA, const B2DPolyPolygon &rCandidateB)
virtual void NbcShear(const Point &rRef, Degree100 nAngle, double tn, bool bVShear)
Definition: svdobj.cxx:1522
sal_Int64 n
double mfSinRotationAngle
Definition: svdtrans.hxx:206
periodic cubic Spline (ni)
SdrObject * GetObj(size_t nNum) const
Definition: svdpage.cxx:807
void RecalcObjOrdNums()
recalculate order numbers / ZIndex
Definition: svdpage.cxx:230
size_t GetObjCount() const
Definition: svdpage.cxx:801
void PutMarkedBehindObj(const SdrObject *pRefObj)
Definition: svdedtv2.cxx:355
void appendBezierSegment(const basegfx::B2DPoint &rNextControlPoint, const basegfx::B2DPoint &rPrevControlPoint, const basegfx::B2DPoint &rPoint)
static SdrObject * MakeNewObject(SdrModel &rSdrModel, SdrInventor nInventor, SdrObjKind nObjIdentifier, const tools::Rectangle *pSnapRect=nullptr)
Definition: svdobj.cxx:3201
static bool isWhiteSpace(const sal_Unicode ch)
void PutMarkedToTop()
Definition: svdedtv2.cxx:249
constexpr sal_uInt16 EE_ITEMS_END(EE_FEATURE_END)
virtual OUString TakeObjNameSingul() const
Definition: svdobj.cxx:1075
constexpr TypedWhichId< XLineStyleItem > XATTR_LINESTYLE(XATTR_LINE_FIRST)
SdrMark * GetMark(size_t nNum) const
Definition: svdmark.cxx:230
sal_Int32 GetParagraphCount() const
sal_Int64 getTimeStamp() const
Definition: svdmark.hxx:130
open Bezier-curve
static void Free(SdrObject *&_rpObject)
Definition: svdobj.cxx:471
void RecalcTan()
Definition: svdtrans.cxx:456
virtual void InsertObject(SdrObject *pObj, size_t nPos=SAL_MAX_SIZE)
Definition: svdpage.cxx:329
virtual const tools::Rectangle & GetSnapRect() const override
Definition: svdoattr.cxx:49
void SetOutlinerParaObject(std::optional< OutlinerParaObject > pTextObject)
Definition: svdobj.cxx:1796
virtual SdrObjList * GetSubList() const
Definition: svdobj.cxx:738
virtual bool HasText() const override
Definition: svdotxat.cxx:418
constexpr sal_uInt16 SDRATTR_START(XATTR_START)
static basegfx::B2DPolyPolygon ImpGetPolyPolygon(const SdrObject *pObj)
Definition: svdedtv2.cxx:669
SdrObjKind
Definition: svdobjkind.hxx:24
Rectangle objects (rectangle, circle, ...)
Definition: svdorect.hxx:38
bool IsObjOrdNumsDirty() const
Definition: svdpage.hxx:103
Provides information about various ZObject properties.
Definition: svdobj.hxx:195
virtual SdrObject * GetMaxToBtmObj(SdrObject *pObj) const
Definition: svdedtv2.cxx:63
B2DPolygon const & getB2DPolygon(sal_uInt32 nIndex) const
void ClearMergedItem(const sal_uInt16 nWhich=0)
Definition: svdobj.cxx:1987
bool IsMore() const
Definition: svditer.hxx:62
constexpr sal_uInt16 SDRATTR_NOTPERSIST_LAST(SDRATTR_OBJVISIBLE)
sal_Int32 getPageNumber() const
void MovMarkedToTop()
Definition: svdedtv2.cxx:72
The transformation of a rectangle into a polygon, by using angle parameters from GeoStat.
Definition: svdtrans.hxx:201
int nCount
OUString SvxResId(TranslateId aId)
Definition: dialmgr.cxx:24
void ConvertMarkedToPolyObj()
Definition: svdedtv2.cxx:2100
SfxStyleSheet * GetStyleSheet() const
Definition: svdobj.cxx:2242
const GDIMetaFile & GetGDIMetaFile() const
void SetMergedItemSet(const SfxItemSet &rSet, bool bClearAllItems=false)
Definition: svdobj.cxx:1997
B2DPolyPolygon solvePolygonOperationAnd(const B2DPolyPolygon &rCandidateA, const B2DPolyPolygon &rCandidateB)
const GeoStat & GetGeoStat() const
Definition: svdotext.hxx:392
constexpr TypedWhichId< SdrOnOffItem > SDRATTR_SHADOW(SDRATTR_SHADOW_FIRST+0)
B2DPolyPolygon solvePolygonOperationDiff(const B2DPolyPolygon &rCandidateA, const B2DPolyPolygon &rCandidateB)
constexpr TypedWhichId< XFormTextStyleItem > XATTR_FORMTXTSTYLE(XATTR_TEXT_FIRST)
sal_uInt32 GetOrdNumDirect() const
Definition: svdobj.hxx:838
void ConvertMarkedToPathObj(bool bLineToArea)
Definition: svdedtv2.cxx:2095
SdrObjList * GetObjList() const
Return current List.
Definition: svdpagv.hxx:169
SdrObject * GetMarkedSdrObj() const
Definition: svdmark.hxx:68
Everything a View needs to know about a selected object.
Definition: svdmark.hxx:44
static std::shared_ptr< PDFium > & get()
Graphic GetTransformedGraphic(SdrGrafObjTransformsAttrs nTransformFlags=SdrGrafObjTransformsAttrs::ALL) const
Definition: svdograf.cxx:388
#define DBG_ASSERT(sCon, aError)
int i
uno_Any a
const Graphic & GetGraphic() const
Definition: svdograf.cxx:383
bool Overlaps(const tools::Rectangle &rRect) const
bool IsLayerLocked(const OUString &rName) const
Definition: svdpagv.hxx:193
void ImpCopyAttributes(const SdrObject *pSource, SdrObject *pDest) const
Definition: svdedtv2.cxx:548
constexpr sal_uInt16 SDRATTR_NOTPERSIST_FIRST(SDRATTR_CIRC_LAST+1)
SdrPageView * GetPageView() const
Definition: svdmark.hxx:70
size_t DoImport(const GDIMetaFile &rMtf, SdrObjList &rDestList, size_t nInsPos, SvdProgressInfo *pProgrInfo=nullptr)
Definition: svdfmtf.cxx:208
constexpr sal_uInt16 EE_ITEMS_START(OWN_ATTR_VALUE_END+1)
Helper class for the communication between the dialog In order to break open Metafiles (sd/source/ui/...
Definition: svdetc.hxx:112
void CombineMarkedObjects(bool bNoPolyPoly=true)
Definition: svdedtv2.cxx:1286
SvxDistributeVertical
SdrModel & getSdrModelFromSdrObject() const
Definition: svdobj.cxx:279
sal_uInt32 GetOrdNum() const
The order number (aka ZOrder, aka z-index) determines whether a SdrObject is located above or below a...
Definition: svdobj.cxx:892
bool IsGroupObject() const
Definition: svdobj.cxx:733
virtual void SetLogicRect(const tools::Rectangle &rRect)
Definition: svdobj.cxx:1694
void SetMergedItem(const SfxPoolItem &rItem)
Definition: svdobj.cxx:1982
OUString GetText(Paragraph const *pPara, sal_Int32 nParaCount=1) const
polygon, PolyPolygon
const SfxPoolItem & GetMergedItem(const sal_uInt16 nWhich) const
Definition: svdobj.cxx:2007
std::optional< OutlinerParaObject > CreateParaObject(sal_Int32 nStartPara=0, sal_Int32 nParaCount=EE_PARA_ALL) const
This class represents an embedded or linked bitmap graphic object.
Definition: svdograf.hxx:67
Abstract DrawObject.
Definition: svdobj.hxx:259
bool ReportActions(size_t nActionCount)
Definition: svdetc.cxx:433
virtual SdrObjKind GetObjIdentifier() const override
Definition: svdopath.cxx:1822
virtual SdrObject * RemoveObject(size_t nObjNum)
Definition: svdpage.cxx:407
virtual void ObjOrderChanged(SdrObject *pObj, size_t nOldPos, size_t nNewPos)
Definition: svdedtv2.cxx:68
void UnGroupMarked()
Definition: svdedtv2.cxx:1879
SdrInsertFlags
Definition: svdedtv.hxx:58
virtual SdrInventor GetObjInventor() const
Definition: svdobj.cxx:644
constexpr Point Center() const
void CombineMarkedTextObjects()
Definition: svdedtv2.cxx:1222
constexpr Point TopLeft() const
Paragraph * GetParagraph(sal_Int32 nAbsPos) const
virtual SdrLayerID GetLayer() const
Definition: svdobj.cxx:668
const SdrObject * GetSdrObjectFromCustomShape() const
Definition: svdoashp.cxx:408
void append(const B2DPolygon &rPolygon, sal_uInt32 nCount=1)
bool IsLine() const
Definition: svdopath.hxx:147
virtual void NbcSetOutlinerParaObject(std::optional< OutlinerParaObject > pTextObject)
Definition: svdobj.cxx:1827
SdrObject * Next()
Definition: svditer.hxx:63
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
SdrObjectUniquePtr ConvertToPolyObj(bool bBezier, bool bLineToArea) const
Definition: svdobj.cxx:2618
constexpr Size GetSize() const
void ForceSort() const
Definition: svdmark.cxx:142
sal_uInt32 count() const
virtual SdrObject * ReplaceObject(SdrObject *pNewObj, size_t nObjNum)
Replace existing object by different one.
Definition: svdpage.cxx:463
#define SAL_WARN_IF(condition, area, stream)
void GroupMarked()
Definition: svdedtv2.cxx:1779
void DismantleMarkedObjects(bool bMakeLines=false)
Definition: svdedtv2.cxx:1720
virtual OutlinerParaObject * GetOutlinerParaObject() const override
Definition: svdotext.cxx:1330
void AddUndo(std::unique_ptr< SdrUndoAction > pUndo)
Definition: svddrgmt.hxx:167
void DistributeMarkedObjects(sal_uInt16 SlotID)
Definition: svdedtv2.cxx:772
eFillStyle
Definition: fillctrl.cxx:53
Degree100 nRotationAngle
Definition: svdtrans.hxx:203
OUString aName
static basegfx::B2DPolygon ImpCombineToSinglePolygon(const basegfx::B2DPolyPolygon &rPolyPolygon)
Definition: svdedtv2.cxx:692
const SfxItemSet & GetMergedItemSet() const
Definition: svdobj.cxx:1972
bool HasGDIMetaFile() const
Definition: svdograf.cxx:856
bool IsTextPath() const
Definition: svdoashp.cxx:446
double mfCosRotationAngle
Definition: svdtrans.hxx:207
void insert(sal_uInt32 nIndex, const B2DPolygon &rPolygon, sal_uInt32 nCount=1)
void AddText(const OutlinerParaObject &, bool bAppend=false)
virtual SdrObject * CloneSdrObject(SdrModel &rTargetModel) const
Definition: svdobj.cxx:1070
std::vector< ImpDistributeEntry > ImpDistributeEntryList
Definition: svdedtv2.cxx:770
size_t GetActionSize() const
bool GetTextBounds(tools::Rectangle &rTextBound) const
Definition: svdoashp.cxx:519
std::unique_ptr< SdrObject, SdrObjectFreeOp > SdrObjectUniquePtr
Definition: svdobj.hxx:97
SdrOnOffItem makeSdrShadowItem(bool bShadow)
Definition: sdshitm.hxx:25
double getLength(const B2DPolygon &rCandidate)
const basegfx::B2DPolyPolygon & GetPathPoly() const
Definition: svdopath.hxx:141
virtual OUString TakeObjNamePlural() const
Definition: svdobj.cxx:1085
bool IsOutlText() const
Definition: svdotext.hxx:335
virtual void SetSnapRect(const tools::Rectangle &rRect)
Definition: svdobj.cxx:1685
void ImpConvertTo(bool bPath, bool bLineToArea)
Definition: svdedtv2.cxx:2039
virtual SdrObject * GetMaxToTopObj(SdrObject *pObj) const
Definition: svdedtv2.cxx:58
void ImpDismantleOneObject(const SdrObject *pObj, SdrObjList &rOL, size_t &rPos, SdrPageView *pPV, bool bMakeLines)
Definition: svdedtv2.cxx:1565
virtual SdrObject * SetObjectOrdNum(size_t nOldObjNum, size_t nNewObjNum)
Modify ZOrder of an SdrObject.
Definition: svdpage.cxx:527
void ReverseOrderOfMarked()
Definition: svdedtv2.cxx:435
virtual const tools::Rectangle & GetLogicRect() const
Definition: svdobj.cxx:1670
void PutMarkedToBtm()
Definition: svdedtv2.cxx:350
B2DPolygon simplifyCurveSegments(const B2DPolygon &rCandidate)
SdrObjList * getParentSdrObjListFromSdrObject() const
Definition: svdobj.cxx:305
void NbcSetStyleSheet(SfxStyleSheet *pNewStyleSheet, bool bDontRemoveHardAttr)
Definition: svdobj.cxx:2260
SvxDistributeHorizontal
const std::shared_ptr< VectorGraphicData > & getVectorGraphicData() const
const OUString & GetMarkDescription() const
Definition: svdmark.cxx:416
SdrMergeMode
Definition: svdedtv.hxx:51
B2DPolyPolygon prepareForPolygonOperation(const B2DPolygon &rCandidate)
void DoImportMarkedMtf(SvdProgressInfo *pProgrInfo=nullptr)
Definition: svdedtv2.cxx:2117
void MergeMarkedObjects(SdrMergeMode eMode)
Definition: svdedtv2.cxx:991
void InsertEntry(const SdrMark &rMark, bool bChkSort=true)
Definition: svdmark.cxx:260
bool isEmbeddedVectorGraphicData() const
Definition: svdograf.cxx:861
virtual OutlinerParaObject * GetOutlinerParaObject() const
Definition: svdobj.cxx:1831
bool Is3DObj() const
Definition: svdobj.hxx:742
aStr
SdrObject * ImpConvertOneObj(SdrObject *pObj, bool bPath, bool bLineToArea)
Definition: svdedtv2.cxx:2020
sal_uInt16 nPos
const Graphic * GetGraphic() const
Definition: svdoole2.cxx:1631
virtual const tools::Rectangle & GetLogicRect() const override
Definition: svdotxtr.cxx:69
virtual void NbcSetLayer(SdrLayerID nLayer)
Definition: svdobj.cxx:685