bump product version to 4.1.6.2
[LibreOffice.git] / svx / source / svdraw / svdedtv2.cxx
blob6f626da3bacaf619692ca1f4fa0580d548551949
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/svdedtv.hxx>
21 #include <editeng/outliner.hxx>
22 #include <svx/svdundo.hxx>
23 #include <svx/svdogrp.hxx> // for grouping objects
24 #include <svx/svdovirt.hxx> // for VirtualObject bundling (Writer)
25 #include <svx/svdopath.hxx> // for CombineObjects
26 #include <svx/svdpage.hxx>
27 #include <svx/svdpagv.hxx>
28 #include "svx/svditer.hxx"
29 #include <svx/svdograf.hxx> // for Possibilities
30 #include <svx/svdoole2.hxx> // and Mtf-Import
31 #include "svx/svdstr.hrc" // names taken from the resource
32 #include "svx/svdglob.hxx" // StringCache
33 #include "svdfmtf.hxx"
34 #include <svx/svdetc.hxx>
35 #include <sfx2/basedlgs.hxx>
36 #include <vcl/msgbox.hxx>
37 #include <editeng/outlobj.hxx>
38 #include <editeng/eeitem.hxx>
39 #include <basegfx/polygon/b2dpolypolygon.hxx>
40 #include <basegfx/polygon/b2dpolypolygontools.hxx>
42 #include <svx/svxdlg.hxx>
43 #include <svx/dialogs.hrc>
45 // #i37011#
46 #include <svx/svdoashp.hxx>
47 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
49 #include <vector>
50 using ::std::vector;
52 SdrObject* SdrEditView::GetMaxToTopObj(SdrObject* /*pObj*/) const
54 return NULL;
57 SdrObject* SdrEditView::GetMaxToBtmObj(SdrObject* /*pObj*/) const
59 return NULL;
62 void SdrEditView::ObjOrderChanged(SdrObject* /*pObj*/, sal_uIntPtr /*nOldPos*/, sal_uIntPtr /*nNewPos*/)
66 void SdrEditView::MovMarkedToTop()
68 sal_uIntPtr nAnz=GetMarkedObjectCount();
69 if (nAnz!=0)
71 const bool bUndo = IsUndoEnabled();
73 if( bUndo )
74 BegUndo(ImpGetResStr(STR_EditMovToTop),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVTOTOP);
76 SortMarkedObjects();
77 sal_uIntPtr nm;
78 for (nm=0; nm<nAnz; nm++)
79 { // All Ordnums have to be correct!
80 GetMarkedObjectByIndex(nm)->GetOrdNum();
82 bool bChg=false;
83 SdrObjList* pOL0=NULL;
84 sal_uIntPtr nNewPos=0;
85 for (nm=nAnz; nm>0;)
87 nm--;
88 SdrMark* pM=GetSdrMarkByIndex(nm);
89 SdrObject* pObj=pM->GetMarkedSdrObj();
90 SdrObjList* pOL=pObj->GetObjList();
91 if (pOL!=pOL0)
93 nNewPos=sal_uIntPtr(pOL->GetObjCount()-1);
94 pOL0=pOL;
96 sal_uIntPtr nNowPos=pObj->GetOrdNumDirect();
97 const Rectangle& rBR=pObj->GetCurrentBoundRect();
98 sal_uIntPtr nCmpPos=nNowPos+1;
99 SdrObject* pMaxObj=GetMaxToTopObj(pObj);
100 if (pMaxObj!=NULL)
102 sal_uIntPtr nMaxPos=pMaxObj->GetOrdNum();
103 if (nMaxPos!=0)
104 nMaxPos--;
105 if (nNewPos>nMaxPos)
106 nNewPos=nMaxPos; // neither go faster...
107 if (nNewPos<nNowPos)
108 nNewPos=nNowPos; // nor go in the other direction
110 bool bEnd=false;
111 while (nCmpPos<nNewPos && !bEnd)
113 SdrObject* pCmpObj=pOL->GetObj(nCmpPos);
114 if (pCmpObj==NULL)
116 OSL_FAIL("MovMarkedToTop(): Reference object not found.");
117 bEnd=true;
119 else if (pCmpObj==pMaxObj)
121 nNewPos=nCmpPos;
122 nNewPos--;
123 bEnd=true;
125 else if (rBR.IsOver(pCmpObj->GetCurrentBoundRect()))
127 nNewPos=nCmpPos;
128 bEnd=true;
130 else
132 nCmpPos++;
135 if (nNowPos!=nNewPos)
137 bChg=true;
138 pOL->SetObjectOrdNum(nNowPos,nNewPos);
139 if( bUndo )
140 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
141 ObjOrderChanged(pObj,nNowPos,nNewPos);
143 nNewPos--;
146 if( bUndo )
147 EndUndo();
149 if (bChg)
150 MarkListHasChanged();
154 void SdrEditView::MovMarkedToBtm()
156 sal_uIntPtr nAnz=GetMarkedObjectCount();
157 if (nAnz!=0)
159 const bool bUndo = IsUndoEnabled();
161 if( bUndo )
162 BegUndo(ImpGetResStr(STR_EditMovToBtm),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVTOBTM);
164 SortMarkedObjects();
165 sal_uIntPtr nm;
166 for (nm=0; nm<nAnz; nm++)
167 { // All Ordnums have to be correct!
168 GetMarkedObjectByIndex(nm)->GetOrdNum();
171 bool bChg=false;
172 SdrObjList* pOL0=NULL;
173 sal_uIntPtr nNewPos=0;
174 for (nm=0; nm<nAnz; nm++)
176 SdrMark* pM=GetSdrMarkByIndex(nm);
177 SdrObject* pObj=pM->GetMarkedSdrObj();
178 SdrObjList* pOL=pObj->GetObjList();
179 if (pOL!=pOL0)
181 nNewPos=0;
182 pOL0=pOL;
184 sal_uIntPtr nNowPos=pObj->GetOrdNumDirect();
185 const Rectangle& rBR=pObj->GetCurrentBoundRect();
186 sal_uIntPtr nCmpPos=nNowPos; if (nCmpPos>0) nCmpPos--;
187 SdrObject* pMaxObj=GetMaxToBtmObj(pObj);
188 if (pMaxObj!=NULL)
190 sal_uIntPtr nMinPos=pMaxObj->GetOrdNum()+1;
191 if (nNewPos<nMinPos)
192 nNewPos=nMinPos; // neither go faster...
193 if (nNewPos>nNowPos)
194 nNewPos=nNowPos; // nor go in the other direction
196 bool bEnd=false;
197 // nNewPos in this case is the "maximum" position
198 // the object may reach without going faster than the object before
199 // it (multiple selection).
200 while (nCmpPos>nNewPos && !bEnd)
202 SdrObject* pCmpObj=pOL->GetObj(nCmpPos);
203 if (pCmpObj==NULL)
205 OSL_FAIL("MovMarkedToBtm(): Reference object not found.");
206 bEnd=true;
208 else if (pCmpObj==pMaxObj)
210 nNewPos=nCmpPos;
211 nNewPos++;
212 bEnd=true;
214 else if (rBR.IsOver(pCmpObj->GetCurrentBoundRect()))
216 nNewPos=nCmpPos;
217 bEnd=true;
219 else
221 nCmpPos--;
224 if (nNowPos!=nNewPos)
226 bChg=true;
227 pOL->SetObjectOrdNum(nNowPos,nNewPos);
228 if( bUndo )
229 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
230 ObjOrderChanged(pObj,nNowPos,nNewPos);
232 nNewPos++;
235 if(bUndo)
236 EndUndo();
238 if(bChg)
239 MarkListHasChanged();
243 void SdrEditView::PutMarkedToTop()
245 PutMarkedInFrontOfObj(NULL);
248 void SdrEditView::PutMarkedInFrontOfObj(const SdrObject* pRefObj)
250 sal_uIntPtr nAnz=GetMarkedObjectCount();
251 if (nAnz!=0)
253 const bool bUndo = IsUndoEnabled();
254 if( bUndo )
255 BegUndo(ImpGetResStr(STR_EditPutToTop),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_PUTTOTOP);
257 SortMarkedObjects();
259 if (pRefObj!=NULL)
261 // Make "in front of the object" work, even if the
262 // selected objects are already in front of the other object
263 sal_uIntPtr nRefMark=TryToFindMarkedObject(pRefObj);
264 SdrMark aRefMark;
265 if (nRefMark!=CONTAINER_ENTRY_NOTFOUND)
267 aRefMark=*GetSdrMarkByIndex(nRefMark);
268 GetMarkedObjectListWriteAccess().DeleteMark(nRefMark);
270 PutMarkedToBtm();
271 if (nRefMark!=CONTAINER_ENTRY_NOTFOUND)
273 GetMarkedObjectListWriteAccess().InsertEntry(aRefMark);
274 SortMarkedObjects();
277 sal_uIntPtr nm;
278 for (nm=0; nm<nAnz; nm++)
279 { // All Ordnums have to be correct!
280 GetMarkedObjectByIndex(nm)->GetOrdNum();
282 bool bChg=false;
283 SdrObjList* pOL0=NULL;
284 sal_uIntPtr nNewPos=0;
285 for (nm=nAnz; nm>0;)
287 nm--;
288 SdrMark* pM=GetSdrMarkByIndex(nm);
289 SdrObject* pObj=pM->GetMarkedSdrObj();
290 if (pObj!=pRefObj)
292 SdrObjList* pOL=pObj->GetObjList();
293 if (pOL!=pOL0)
295 nNewPos=sal_uIntPtr(pOL->GetObjCount()-1);
296 pOL0=pOL;
298 sal_uIntPtr nNowPos=pObj->GetOrdNumDirect();
299 SdrObject* pMaxObj=GetMaxToTopObj(pObj);
300 if (pMaxObj!=NULL)
302 sal_uIntPtr nMaxOrd=pMaxObj->GetOrdNum(); // sadly doesn't work any other way
303 if (nMaxOrd>0)
304 nMaxOrd--;
305 if (nNewPos>nMaxOrd)
306 nNewPos=nMaxOrd; // neither go faster...
307 if (nNewPos<nNowPos)
308 nNewPos=nNowPos; // nor go into the other direction
310 if (pRefObj!=NULL)
312 if (pRefObj->GetObjList()==pObj->GetObjList())
314 sal_uIntPtr nMaxOrd=pRefObj->GetOrdNum(); // sadly doesn't work any other way
315 if (nNewPos>nMaxOrd)
316 nNewPos=nMaxOrd; // neither go faster...
317 if (nNewPos<nNowPos)
318 nNewPos=nNowPos; // nor go into the other direction
320 else
322 nNewPos=nNowPos; // different PageView, so don't change
325 if (nNowPos!=nNewPos)
327 bChg=true;
328 pOL->SetObjectOrdNum(nNowPos,nNewPos);
329 if( bUndo )
330 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
331 ObjOrderChanged(pObj,nNowPos,nNewPos);
333 nNewPos--;
334 } // if (pObj!=pRefObj)
335 } // for loop over all selected objects
337 if( bUndo )
338 EndUndo();
340 if(bChg)
341 MarkListHasChanged();
345 void SdrEditView::PutMarkedToBtm()
347 PutMarkedBehindObj(NULL);
350 void SdrEditView::PutMarkedBehindObj(const SdrObject* pRefObj)
352 sal_uIntPtr nAnz=GetMarkedObjectCount();
353 if (nAnz!=0)
355 const bool bUndo = IsUndoEnabled();
357 if( bUndo )
358 BegUndo(ImpGetResStr(STR_EditPutToBtm),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_PUTTOBTM);
360 SortMarkedObjects();
361 if (pRefObj!=NULL)
363 // Make "behind the object" work, even if the
364 // selected objects are already behind the other object
365 sal_uIntPtr nRefMark=TryToFindMarkedObject(pRefObj);
366 SdrMark aRefMark;
367 if (nRefMark!=CONTAINER_ENTRY_NOTFOUND)
369 aRefMark=*GetSdrMarkByIndex(nRefMark);
370 GetMarkedObjectListWriteAccess().DeleteMark(nRefMark);
372 PutMarkedToTop();
373 if (nRefMark!=CONTAINER_ENTRY_NOTFOUND)
375 GetMarkedObjectListWriteAccess().InsertEntry(aRefMark);
376 SortMarkedObjects();
379 sal_uIntPtr nm;
380 for (nm=0; nm<nAnz; nm++) { // All Ordnums have to be correct!
381 GetMarkedObjectByIndex(nm)->GetOrdNum();
383 bool bChg=false;
384 SdrObjList* pOL0=NULL;
385 sal_uIntPtr nNewPos=0;
386 for (nm=0; nm<nAnz; nm++) {
387 SdrMark* pM=GetSdrMarkByIndex(nm);
388 SdrObject* pObj=pM->GetMarkedSdrObj();
389 if (pObj!=pRefObj) {
390 SdrObjList* pOL=pObj->GetObjList();
391 if (pOL!=pOL0) {
392 nNewPos=0;
393 pOL0=pOL;
395 sal_uIntPtr nNowPos=pObj->GetOrdNumDirect();
396 SdrObject* pMinObj=GetMaxToBtmObj(pObj);
397 if (pMinObj!=NULL) {
398 sal_uIntPtr nMinOrd=pMinObj->GetOrdNum()+1; // sadly doesn't work any differently
399 if (nNewPos<nMinOrd) nNewPos=nMinOrd; // neither go faster...
400 if (nNewPos>nNowPos) nNewPos=nNowPos; // nor go into the other direction
402 if (pRefObj!=NULL) {
403 if (pRefObj->GetObjList()==pObj->GetObjList()) {
404 sal_uIntPtr nMinOrd=pRefObj->GetOrdNum(); // sadly doesn't work any differently
405 if (nNewPos<nMinOrd) nNewPos=nMinOrd; // neither go faster...
406 if (nNewPos>nNowPos) nNewPos=nNowPos; // nor go into the other direction
407 } else {
408 nNewPos=nNowPos; // different PageView, so don't change
411 if (nNowPos!=nNewPos) {
412 bChg=true;
413 pOL->SetObjectOrdNum(nNowPos,nNewPos);
414 if( bUndo )
415 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
416 ObjOrderChanged(pObj,nNowPos,nNewPos);
418 nNewPos++;
419 } // if (pObj!=pRefObj)
420 } // for loop over all selected objects
422 if(bUndo)
423 EndUndo();
425 if(bChg)
426 MarkListHasChanged();
430 void SdrEditView::ReverseOrderOfMarked()
432 SortMarkedObjects();
433 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
434 if (nMarkAnz>0)
436 bool bChg=false;
438 bool bUndo = IsUndoEnabled();
439 if( bUndo )
440 BegUndo(ImpGetResStr(STR_EditRevOrder),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_REVORDER);
442 sal_uIntPtr a=0;
443 do {
444 // take into account selection across multiple PageViews
445 sal_uIntPtr b=a+1;
446 while (b<nMarkAnz && GetSdrPageViewOfMarkedByIndex(b) == GetSdrPageViewOfMarkedByIndex(a)) b++;
447 b--;
448 SdrObjList* pOL=GetSdrPageViewOfMarkedByIndex(a)->GetObjList();
449 sal_uIntPtr c=b;
450 if (a<c) { // make sure OrdNums aren't dirty
451 GetMarkedObjectByIndex(a)->GetOrdNum();
453 while (a<c) {
454 SdrObject* pObj1=GetMarkedObjectByIndex(a);
455 SdrObject* pObj2=GetMarkedObjectByIndex(c);
456 sal_uIntPtr nOrd1=pObj1->GetOrdNumDirect();
457 sal_uIntPtr nOrd2=pObj2->GetOrdNumDirect();
458 if( bUndo )
460 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj1,nOrd1,nOrd2));
461 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj2,nOrd2-1,nOrd1));
463 pOL->SetObjectOrdNum(nOrd1,nOrd2);
464 // Obj 2 has moved forward by one position, so now nOrd2-1
465 pOL->SetObjectOrdNum(nOrd2-1,nOrd1);
466 // use Replace instead of SetOrdNum for performance reasons (recalculation of Ordnums)
467 a++; c--;
468 bChg=true;
470 a=b+1;
471 } while (a<nMarkAnz);
473 if(bUndo)
474 EndUndo();
476 if(bChg)
477 MarkListHasChanged();
481 void SdrEditView::ImpCheckToTopBtmPossible()
483 sal_uIntPtr nAnz=GetMarkedObjectCount();
484 if (nAnz==0)
485 return;
486 if (nAnz==1)
487 { // special-casing for single selection
488 SdrObject* pObj=GetMarkedObjectByIndex(0);
489 SdrObjList* pOL=pObj->GetObjList();
490 sal_uIntPtr nMax=pOL->GetObjCount();
491 sal_uIntPtr nMin=0;
492 sal_uIntPtr nObjNum=pObj->GetOrdNum();
493 SdrObject* pRestrict=GetMaxToTopObj(pObj);
494 if (pRestrict!=NULL) {
495 sal_uIntPtr nRestrict=pRestrict->GetOrdNum();
496 if (nRestrict<nMax) nMax=nRestrict;
498 pRestrict=GetMaxToBtmObj(pObj);
499 if (pRestrict!=NULL) {
500 sal_uIntPtr nRestrict=pRestrict->GetOrdNum();
501 if (nRestrict>nMin) nMin=nRestrict;
503 bToTopPossible=nObjNum<sal_uIntPtr(nMax-1);
504 bToBtmPossible=nObjNum>nMin;
505 } else { // multiple selection
506 sal_uIntPtr nm=0;
507 SdrObjList* pOL0=NULL;
508 long nPos0=-1;
509 while (!bToBtmPossible && nm<nAnz) { // check 'send to background'
510 SdrObject* pObj=GetMarkedObjectByIndex(nm);
511 SdrObjList* pOL=pObj->GetObjList();
512 if (pOL!=pOL0) {
513 nPos0=-1;
514 pOL0=pOL;
516 sal_uIntPtr nPos=pObj->GetOrdNum();
517 bToBtmPossible=nPos>sal_uIntPtr(nPos0+1);
518 nPos0=long(nPos);
519 nm++;
521 nm=nAnz;
522 pOL0=NULL;
523 nPos0=0x7FFFFFFF;
524 while (!bToTopPossible && nm>0) { // check 'bring to front'
525 nm--;
526 SdrObject* pObj=GetMarkedObjectByIndex(nm);
527 SdrObjList* pOL=pObj->GetObjList();
528 if (pOL!=pOL0) {
529 nPos0=pOL->GetObjCount();
530 pOL0=pOL;
532 sal_uIntPtr nPos=pObj->GetOrdNum();
533 bToTopPossible=nPos+1<sal_uIntPtr(nPos0);
534 nPos0=nPos;
539 ////////////////////////////////////////////////////////////////////////////////////////////////////
540 // Combine
541 ////////////////////////////////////////////////////////////////////////////////////////////////////
543 void SdrEditView::ImpCopyAttributes(const SdrObject* pSource, SdrObject* pDest) const
545 if (pSource!=NULL) {
546 SdrObjList* pOL=pSource->GetSubList();
547 if (pOL!=NULL && !pSource->Is3DObj()) { // get first non-group object from group
548 SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS);
549 pSource=aIter.Next();
553 if(pSource && pDest)
555 SfxItemSet aSet(pMod->GetItemPool(),
556 SDRATTR_START, SDRATTR_NOTPERSIST_FIRST-1,
557 SDRATTR_NOTPERSIST_LAST+1, SDRATTR_END,
558 EE_ITEMS_START, EE_ITEMS_END,
559 0, 0);
561 aSet.Put(pSource->GetMergedItemSet());
563 pDest->ClearMergedItem();
564 pDest->SetMergedItemSet(aSet);
566 pDest->NbcSetLayer(pSource->GetLayer());
567 pDest->NbcSetStyleSheet(pSource->GetStyleSheet(), sal_True);
571 sal_Bool SdrEditView::ImpCanConvertForCombine1(const SdrObject* pObj) const
573 // new condition IsLine() to be able to combine simple Lines
574 sal_Bool bIsLine(sal_False);
576 const SdrPathObj* pPath = PTR_CAST(SdrPathObj,pObj);
578 if(pPath)
580 bIsLine = pPath->IsLine();
583 SdrObjTransformInfoRec aInfo;
584 pObj->TakeObjInfo(aInfo);
586 return (aInfo.bCanConvToPath || aInfo.bCanConvToPoly || bIsLine);
589 sal_Bool SdrEditView::ImpCanConvertForCombine(const SdrObject* pObj) const
591 SdrObjList* pOL = pObj->GetSubList();
593 if(pOL && !pObj->Is3DObj())
595 SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS);
597 while(aIter.IsMore())
599 SdrObject* pObj1 = aIter.Next();
601 // all members of a group have to be convertible
602 if(!ImpCanConvertForCombine1(pObj1))
604 return sal_False;
608 else
610 if(!ImpCanConvertForCombine1(pObj))
612 return sal_False;
616 return sal_True;
619 basegfx::B2DPolyPolygon SdrEditView::ImpGetPolyPolygon1(const SdrObject* pObj, sal_Bool bCombine) const
621 basegfx::B2DPolyPolygon aRetval;
622 SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj);
624 if(bCombine && pPath && !pObj->GetOutlinerParaObject())
626 aRetval = pPath->GetPathPoly();
628 else
630 SdrObject* pConvObj = pObj->ConvertToPolyObj(bCombine, sal_False);
632 if(pConvObj)
634 SdrObjList* pOL = pConvObj->GetSubList();
636 if(pOL)
638 SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS);
640 while(aIter.IsMore())
642 SdrObject* pObj1 = aIter.Next();
643 pPath = PTR_CAST(SdrPathObj, pObj1);
645 if(pPath)
647 aRetval.append(pPath->GetPathPoly());
651 else
653 pPath = PTR_CAST(SdrPathObj, pConvObj);
655 if(pPath)
657 aRetval = pPath->GetPathPoly();
661 SdrObject::Free( pConvObj );
665 return aRetval;
668 basegfx::B2DPolyPolygon SdrEditView::ImpGetPolyPolygon(const SdrObject* pObj, sal_Bool bCombine) const
670 SdrObjList* pOL = pObj->GetSubList();
672 if(pOL && !pObj->Is3DObj())
674 basegfx::B2DPolyPolygon aRetval;
675 SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS);
677 while(aIter.IsMore())
679 SdrObject* pObj1 = aIter.Next();
680 aRetval.append(ImpGetPolyPolygon1(pObj1, bCombine));
683 return aRetval;
685 else
687 return ImpGetPolyPolygon1(pObj, bCombine);
691 basegfx::B2DPolygon SdrEditView::ImpCombineToSinglePolygon(const basegfx::B2DPolyPolygon& rPolyPolygon) const
693 const sal_uInt32 nPolyCount(rPolyPolygon.count());
695 if(0L == nPolyCount)
697 return basegfx::B2DPolygon();
699 else if(1L == nPolyCount)
701 return rPolyPolygon.getB2DPolygon(0L);
703 else
705 basegfx::B2DPolygon aRetval(rPolyPolygon.getB2DPolygon(0L));
707 for(sal_uInt32 a(1L); a < nPolyCount; a++)
709 basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a));
711 if(aRetval.count())
713 if(aCandidate.count())
715 const basegfx::B2DPoint aCA(aCandidate.getB2DPoint(0L));
716 const basegfx::B2DPoint aCB(aCandidate.getB2DPoint(aCandidate.count() - 1L));
717 const basegfx::B2DPoint aRA(aRetval.getB2DPoint(0L));
718 const basegfx::B2DPoint aRB(aRetval.getB2DPoint(aRetval.count() - 1L));
720 const double fRACA(basegfx::B2DVector(aCA - aRA).getLength());
721 const double fRACB(basegfx::B2DVector(aCB - aRA).getLength());
722 const double fRBCA(basegfx::B2DVector(aCA - aRB).getLength());
723 const double fRBCB(basegfx::B2DVector(aCB - aRB).getLength());
725 const double fSmallestRA(fRACA < fRACB ? fRACA : fRACB);
726 const double fSmallestRB(fRBCA < fRBCB ? fRBCA : fRBCB);
728 if(fSmallestRA < fSmallestRB)
730 // flip result
731 aRetval.flip();
734 const double fSmallestCA(fRACA < fRBCA ? fRACA : fRBCA);
735 const double fSmallestCB(fRACB < fRBCB ? fRACB : fRBCB);
737 if(fSmallestCB < fSmallestCA)
739 // flip candidate
740 aCandidate.flip();
743 // append candidate to retval
744 aRetval.append(aCandidate);
747 else
749 aRetval = aCandidate;
753 return aRetval;
757 // for distribution dialog function
758 struct ImpDistributeEntry
760 SdrObject* mpObj;
761 sal_Int32 mnPos;
762 sal_Int32 mnLength;
765 typedef vector< ImpDistributeEntry*> ImpDistributeEntryList;
767 void SdrEditView::DistributeMarkedObjects()
769 sal_uInt32 nMark(GetMarkedObjectCount());
771 if(nMark > 2)
773 SfxItemSet aNewAttr(pMod->GetItemPool());
775 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
776 if(pFact)
778 AbstractSvxDistributeDialog *pDlg = pFact->CreateSvxDistributeDialog(NULL, aNewAttr);
779 DBG_ASSERT(pDlg, "Dialogdiet fail!");
781 sal_uInt16 nResult = pDlg->Execute();
783 if(nResult == RET_OK)
785 SvxDistributeHorizontal eHor = pDlg->GetDistributeHor();
786 SvxDistributeVertical eVer = pDlg->GetDistributeVer();
787 ImpDistributeEntryList aEntryList;
788 ImpDistributeEntryList::iterator itEntryList;
789 sal_uInt32 nFullLength;
791 const bool bUndo = IsUndoEnabled();
792 if( bUndo )
793 BegUndo();
795 if(eHor != SvxDistributeHorizontalNone)
797 // build sorted entry list
798 nFullLength = 0L;
800 for( sal_uInt32 a = 0; a < nMark; a++ )
802 SdrMark* pMark = GetSdrMarkByIndex(a);
803 ImpDistributeEntry* pNew = new ImpDistributeEntry;
805 pNew->mpObj = pMark->GetMarkedSdrObj();
807 switch(eHor)
809 case SvxDistributeHorizontalLeft:
811 pNew->mnPos = pNew->mpObj->GetSnapRect().Left();
812 break;
814 case SvxDistributeHorizontalCenter:
816 pNew->mnPos = (pNew->mpObj->GetSnapRect().Right() + pNew->mpObj->GetSnapRect().Left()) / 2;
817 break;
819 case SvxDistributeHorizontalDistance:
821 pNew->mnLength = pNew->mpObj->GetSnapRect().GetWidth() + 1;
822 nFullLength += pNew->mnLength;
823 pNew->mnPos = (pNew->mpObj->GetSnapRect().Right() + pNew->mpObj->GetSnapRect().Left()) / 2;
824 break;
826 case SvxDistributeHorizontalRight:
828 pNew->mnPos = pNew->mpObj->GetSnapRect().Right();
829 break;
831 default: break;
834 for ( itEntryList = aEntryList.begin();
835 itEntryList < aEntryList.end() && (*itEntryList)->mnPos < pNew->mnPos;
836 ++itEntryList )
838 if ( itEntryList < aEntryList.end() )
839 aEntryList.insert( itEntryList, pNew );
840 else
841 aEntryList.push_back( pNew );
844 if(eHor == SvxDistributeHorizontalDistance)
846 // calculate room in-between
847 sal_Int32 nWidth = GetAllMarkedBoundRect().GetWidth() + 1;
848 double fStepWidth = ((double)nWidth - (double)nFullLength) / (double)(aEntryList.size() - 1);
849 double fStepStart = (double)aEntryList[ 0 ]->mnPos;
850 fStepStart += fStepWidth + (double)((aEntryList[ 0 ]->mnLength + aEntryList[ 1 ]->mnLength) / 2);
852 // move entries 1..n-1
853 for( size_t i = 1, n = aEntryList.size()-1; i < n; ++i )
855 ImpDistributeEntry* pCurr = aEntryList[ i ];
856 ImpDistributeEntry* pNext = aEntryList[ i + 1];
857 sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos;
858 if( bUndo )
859 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj));
860 pCurr->mpObj->Move(Size(nDelta, 0));
861 fStepStart += fStepWidth + (double)((pCurr->mnLength + pNext->mnLength) / 2);
864 else
866 // calculate distances
867 sal_Int32 nWidth = aEntryList[ aEntryList.size() - 1 ]->mnPos - aEntryList[ 0 ]->mnPos;
868 double fStepWidth = (double)nWidth / (double)(aEntryList.size() - 1);
869 double fStepStart = (double)aEntryList[ 0 ]->mnPos;
870 fStepStart += fStepWidth;
872 // move entries 1..n-1
873 for( size_t i = 1 ; i < aEntryList.size()-1 ; ++i )
875 ImpDistributeEntry* pCurr = aEntryList[ i ];
876 sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos;
877 if( bUndo )
878 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj));
879 pCurr->mpObj->Move(Size(nDelta, 0));
880 fStepStart += fStepWidth;
884 // clear list
885 for ( size_t i = 0, n = aEntryList.size(); i < n; ++i )
886 delete aEntryList[ i ];
887 aEntryList.clear();
890 if(eVer != SvxDistributeVerticalNone)
892 // build sorted entry list
893 nFullLength = 0L;
895 for( sal_uInt32 a = 0; a < nMark; a++ )
897 SdrMark* pMark = GetSdrMarkByIndex(a);
898 ImpDistributeEntry* pNew = new ImpDistributeEntry;
900 pNew->mpObj = pMark->GetMarkedSdrObj();
902 switch(eVer)
904 case SvxDistributeVerticalTop:
906 pNew->mnPos = pNew->mpObj->GetSnapRect().Top();
907 break;
909 case SvxDistributeVerticalCenter:
911 pNew->mnPos = (pNew->mpObj->GetSnapRect().Bottom() + pNew->mpObj->GetSnapRect().Top()) / 2;
912 break;
914 case SvxDistributeVerticalDistance:
916 pNew->mnLength = pNew->mpObj->GetSnapRect().GetHeight() + 1;
917 nFullLength += pNew->mnLength;
918 pNew->mnPos = (pNew->mpObj->GetSnapRect().Bottom() + pNew->mpObj->GetSnapRect().Top()) / 2;
919 break;
921 case SvxDistributeVerticalBottom:
923 pNew->mnPos = pNew->mpObj->GetSnapRect().Bottom();
924 break;
926 default: break;
929 for ( itEntryList = aEntryList.begin();
930 itEntryList < aEntryList.end() && (*itEntryList)->mnPos < pNew->mnPos;
931 ++itEntryList )
933 if ( itEntryList < aEntryList.end() )
934 aEntryList.insert( itEntryList, pNew );
935 else
936 aEntryList.push_back( pNew );
939 if(eVer == SvxDistributeVerticalDistance)
941 // calculate room in-between
942 sal_Int32 nHeight = GetAllMarkedBoundRect().GetHeight() + 1;
943 double fStepWidth = ((double)nHeight - (double)nFullLength) / (double)(aEntryList.size() - 1);
944 double fStepStart = (double)aEntryList[ 0 ]->mnPos;
945 fStepStart += fStepWidth + (double)((aEntryList[ 0 ]->mnLength + aEntryList[ 1 ]->mnLength) / 2);
947 // move entries 1..n-1
948 for( size_t i = 1, n = aEntryList.size()-1; i < n; ++i)
950 ImpDistributeEntry* pCurr = aEntryList[ i ];
951 ImpDistributeEntry* pNext = aEntryList[ i + 1 ];
952 sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos;
953 if( bUndo )
954 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj));
955 pCurr->mpObj->Move(Size(0, nDelta));
956 fStepStart += fStepWidth + (double)((pCurr->mnLength + pNext->mnLength) / 2);
959 else
961 // calculate distances
962 sal_Int32 nHeight = aEntryList[ aEntryList.size() - 1 ]->mnPos - aEntryList[ 0 ]->mnPos;
963 double fStepWidth = (double)nHeight / (double)(aEntryList.size() - 1);
964 double fStepStart = (double)aEntryList[ 0 ]->mnPos;
965 fStepStart += fStepWidth;
967 // move entries 1..n-1
968 for(size_t i = 1, n = aEntryList.size()-1; i < n; ++i)
970 ImpDistributeEntry* pCurr = aEntryList[ i ];
971 sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos;
972 if( bUndo )
973 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj));
974 pCurr->mpObj->Move(Size(0, nDelta));
975 fStepStart += fStepWidth;
979 // clear list
980 for ( size_t i = 0, n = aEntryList.size(); i < n; ++i )
981 delete aEntryList[ i ];
982 aEntryList.clear();
985 // UNDO-Comment and end of UNDO
986 SetUndoComment(ImpGetResStr(STR_DistributeMarkedObjects));
988 if( bUndo )
989 EndUndo();
992 delete(pDlg);
997 void SdrEditView::MergeMarkedObjects(SdrMergeMode eMode)
999 // #i73441# check content
1000 if(AreObjectsMarked())
1002 SdrMarkList aRemove;
1003 SortMarkedObjects();
1005 const bool bUndo = IsUndoEnabled();
1007 if( bUndo )
1008 BegUndo();
1010 sal_uInt32 nInsPos=0xFFFFFFFF;
1011 const SdrObject* pAttrObj = NULL;
1012 basegfx::B2DPolyPolygon aMergePolyPolygonA;
1013 basegfx::B2DPolyPolygon aMergePolyPolygonB;
1015 SdrObjList* pInsOL = NULL;
1016 SdrPageView* pInsPV = NULL;
1017 bool bFirstObjectComplete(false);
1019 // make sure selected objects are contour objects
1020 // since now basegfx::tools::adaptiveSubdivide() is used, it is no longer
1021 // necessary to use ConvertMarkedToPolyObj which will subdivide curves using the old
1022 // mechanisms. In a next step the polygon clipper will even be able to clip curves...
1023 // ConvertMarkedToPolyObj(sal_True);
1024 ConvertMarkedToPathObj(sal_True);
1025 OSL_ENSURE(AreObjectsMarked(), "no more objects selected after preparations (!)");
1027 for(sal_uInt32 a=0;a<GetMarkedObjectCount();a++)
1029 SdrMark* pM = GetSdrMarkByIndex(a);
1030 SdrObject* pObj = pM->GetMarkedSdrObj();
1032 if(ImpCanConvertForCombine(pObj))
1034 if(!pAttrObj)
1035 pAttrObj = pObj;
1037 nInsPos = pObj->GetOrdNum() + 1;
1038 pInsPV = pM->GetPageView();
1039 pInsOL = pObj->GetObjList();
1041 // #i76891# use single iteration from SJ here which works on SdrObjects and takes
1042 // groups into account by itself
1043 SdrObjListIter aIter(*pObj, IM_DEEPWITHGROUPS);
1045 while(aIter.IsMore())
1047 SdrObject* pCandidate = aIter.Next();
1048 SdrPathObj* pPathObj = PTR_CAST(SdrPathObj, pCandidate);
1049 if(pPathObj)
1051 basegfx::B2DPolyPolygon aTmpPoly(pPathObj->GetPathPoly());
1053 // #i76891# unfortunately ConvertMarkedToPathObj has converted all
1054 // involved polygon data to curve segments, even if not necessary.
1055 // It is better to try to reduce to more simple polygons.
1056 aTmpPoly = basegfx::tools::simplifyCurveSegments(aTmpPoly);
1058 // for each part polygon as preparation, remove self-intersections
1059 // correct orientations and get rid of possible neutral polygons.
1060 aTmpPoly = basegfx::tools::prepareForPolygonOperation(aTmpPoly);
1062 if(!bFirstObjectComplete)
1064 // #i111987# Also need to collect ORed source shape when more than
1065 // a single polygon is involved
1066 if(aMergePolyPolygonA.count())
1068 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA, aTmpPoly);
1070 else
1072 aMergePolyPolygonA = aTmpPoly;
1075 else
1077 if(aMergePolyPolygonB.count())
1079 // to topologically correctly collect the 2nd polygon
1080 // group it is necessary to OR the parts (each is seen as
1081 // XOR-FillRule polygon and they are drawn over each-other)
1082 aMergePolyPolygonB = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonB, aTmpPoly);
1084 else
1086 aMergePolyPolygonB = aTmpPoly;
1092 // was there something added to the first polygon?
1093 if(!bFirstObjectComplete && aMergePolyPolygonA.count())
1095 bFirstObjectComplete = true;
1098 // move object to temporary delete list
1099 aRemove.InsertEntry(SdrMark(pObj, pM->GetPageView()));
1103 switch(eMode)
1105 case SDR_MERGE_MERGE:
1107 // merge all contained parts (OR)
1108 static bool bTestXOR(false);
1109 if(bTestXOR)
1111 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationXor(aMergePolyPolygonA, aMergePolyPolygonB);
1113 else
1115 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA, aMergePolyPolygonB);
1117 break;
1119 case SDR_MERGE_SUBSTRACT:
1121 // Substract B from A
1122 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationDiff(aMergePolyPolygonA, aMergePolyPolygonB);
1123 break;
1125 case SDR_MERGE_INTERSECT:
1127 // AND B and A
1128 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationAnd(aMergePolyPolygonA, aMergePolyPolygonB);
1129 break;
1133 // #i73441# check insert list before taking actions
1134 if(pInsOL)
1136 SdrPathObj* pPath = new SdrPathObj(OBJ_PATHFILL, aMergePolyPolygonA);
1137 ImpCopyAttributes(pAttrObj, pPath);
1138 SdrInsertReason aReason(SDRREASON_VIEWCALL, pAttrObj);
1139 pInsOL->InsertObject(pPath, nInsPos, &aReason);
1140 if( bUndo )
1141 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath));
1142 MarkObj(pPath, pInsPV, sal_False, sal_True);
1145 aRemove.ForceSort();
1146 switch(eMode)
1148 case SDR_MERGE_MERGE:
1150 SetUndoComment(
1151 ImpGetResStr(STR_EditMergeMergePoly),
1152 aRemove.GetMarkDescription());
1153 break;
1155 case SDR_MERGE_SUBSTRACT:
1157 SetUndoComment(
1158 ImpGetResStr(STR_EditMergeSubstractPoly),
1159 aRemove.GetMarkDescription());
1160 break;
1162 case SDR_MERGE_INTERSECT:
1164 SetUndoComment(
1165 ImpGetResStr(STR_EditMergeIntersectPoly),
1166 aRemove.GetMarkDescription());
1167 break;
1170 DeleteMarkedList(aRemove);
1172 if( bUndo )
1173 EndUndo();
1177 void SdrEditView::CombineMarkedObjects(sal_Bool bNoPolyPoly)
1179 // #105899# Start of Combine-Undo put to front, else ConvertMarkedToPolyObj would
1180 // create a 2nd Undo-action and Undo-Comment.
1182 bool bUndo = IsUndoEnabled();
1184 // Undo-String will be set later
1185 if( bUndo )
1186 BegUndo(String(), String(), bNoPolyPoly ? SDRREPFUNC_OBJ_COMBINE_ONEPOLY : SDRREPFUNC_OBJ_COMBINE_POLYPOLY);
1188 // #105899# First, guarantee that all objects are converted to polyobjects,
1189 // especially for SdrGrafObj with bitmap filling this is necessary to not
1190 // loose the bitmap filling.
1192 // #i12392#
1193 // ConvertMarkedToPolyObj was too strong here, it will loose quality and
1194 // information when curve objects are combined. This can be replaced by
1195 // using ConvertMarkedToPathObj without changing the previous fix.
1197 // #i21250#
1198 // Instead of simply passing sal_True as LineToArea, use bNoPolyPoly as info
1199 // if this command is a 'Combine' or a 'Connect' command. On Connect it's sal_True.
1200 // To not concert line segments with a set line width to polygons in that case,
1201 // use this info. Do not convert LineToArea on Connect commands.
1202 // ConvertMarkedToPathObj(!bNoPolyPoly);
1204 // This is used for Combine and Connect. In no case it is necessary to force
1205 // the content to curve, but it is also not good to force to polygons. Thus,
1206 // curve is the less information loosing one. Remember: This place is not
1207 // used for merge.
1208 // LineToArea is never necessary, both commands are able to take over the
1209 // set line style and to display it correctly. Thus, i will use a
1210 // ConvertMarkedToPathObj with a sal_False in any case. Only drawback is that
1211 // simple polygons will be changed to curves, but with no information loss.
1212 ConvertMarkedToPathObj(sal_False /* bLineToArea */);
1214 // continue as before
1215 basegfx::B2DPolyPolygon aPolyPolygon;
1216 SdrObjList* pAktOL = 0L;
1217 SdrMarkList aRemoveMerker;
1219 SortMarkedObjects();
1220 sal_uInt32 nInsPos(0xFFFFFFFF);
1221 SdrObjList* pInsOL = 0L;
1222 SdrPageView* pInsPV = 0L;
1223 const sal_uInt32 nAnz(GetMarkedObjectCount());
1224 const SdrObject* pAttrObj = 0L;
1226 for(sal_uInt32 a(nAnz); a > 0L; )
1228 a--;
1229 SdrMark* pM = GetSdrMarkByIndex(a);
1230 SdrObject* pObj = pM->GetMarkedSdrObj();
1231 SdrObjList* pThisOL = pObj->GetObjList();
1233 if(pAktOL != pThisOL)
1235 pAktOL = pThisOL;
1238 if(ImpCanConvertForCombine(pObj))
1240 // remember objects to be able to copy attributes
1241 pAttrObj = pObj;
1243 // unfortunately ConvertMarkedToPathObj has converted all
1244 // involved polygon data to curve segments, even if not necessary.
1245 // It is better to try to reduce to more simple polygons.
1246 basegfx::B2DPolyPolygon aTmpPoly(basegfx::tools::simplifyCurveSegments(ImpGetPolyPolygon(pObj, sal_True)));
1247 aPolyPolygon.insert(0L, aTmpPoly);
1249 if(!pInsOL)
1251 nInsPos = pObj->GetOrdNum() + 1L;
1252 pInsPV = pM->GetPageView();
1253 pInsOL = pObj->GetObjList();
1256 aRemoveMerker.InsertEntry(SdrMark(pObj, pM->GetPageView()));
1260 if(bNoPolyPoly)
1262 basegfx::B2DPolygon aCombinedPolygon(ImpCombineToSinglePolygon(aPolyPolygon));
1263 aPolyPolygon.clear();
1264 aPolyPolygon.append(aCombinedPolygon);
1267 const sal_uInt32 nPolyCount(aPolyPolygon.count());
1269 if(nPolyCount)
1271 SdrObjKind eKind = OBJ_PATHFILL;
1273 if(nPolyCount > 1L)
1275 aPolyPolygon.setClosed(true);
1277 else
1279 // check for Polyline
1280 const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(0L));
1281 const sal_uInt32 nPointCount(aPolygon.count());
1283 if(nPointCount <= 2L)
1285 eKind = OBJ_PATHLINE;
1287 else
1289 if(!aPolygon.isClosed())
1291 const basegfx::B2DPoint aPointA(aPolygon.getB2DPoint(0L));
1292 const basegfx::B2DPoint aPointB(aPolygon.getB2DPoint(nPointCount - 1L));
1293 const double fDistance(basegfx::B2DVector(aPointB - aPointA).getLength());
1294 const double fJoinTolerance(10.0);
1296 if(fDistance < fJoinTolerance)
1298 aPolyPolygon.setClosed(true);
1300 else
1302 eKind = OBJ_PATHLINE;
1308 SdrPathObj* pPath = new SdrPathObj(eKind,aPolyPolygon);
1310 // attributes of the lowest object
1311 ImpCopyAttributes(pAttrObj, pPath);
1313 // If LineStyle of pAttrObj is XLINE_NONE force to XLINE_SOLID to make visible.
1314 const XLineStyle eLineStyle = ((const XLineStyleItem&)pAttrObj->GetMergedItem(XATTR_LINESTYLE)).GetValue();
1315 const XFillStyle eFillStyle = ((const XFillStyleItem&)pAttrObj->GetMergedItem(XATTR_FILLSTYLE)).GetValue();
1317 // Take fill style/closed state of pAttrObj in account when deciding to change the line style
1318 bool bIsClosedPathObj(pAttrObj->ISA(SdrPathObj) && ((SdrPathObj*)pAttrObj)->IsClosed());
1320 if(XLINE_NONE == eLineStyle && (XFILL_NONE == eFillStyle || !bIsClosedPathObj))
1322 pPath->SetMergedItem(XLineStyleItem(XLINE_SOLID));
1325 SdrInsertReason aReason(SDRREASON_VIEWCALL,pAttrObj);
1326 pInsOL->InsertObject(pPath,nInsPos,&aReason);
1327 if( bUndo )
1328 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath));
1330 // Here was a severe error: Without UnmarkAllObj, the new object was marked
1331 // additionally to the two ones which are deleted below. As long as those are
1332 // in the UNDO there is no problem, but as soon as they get deleted, the
1333 // MarkList will contain deleted objects -> GPF.
1334 UnmarkAllObj(pInsPV);
1335 MarkObj(pPath, pInsPV, sal_False, sal_True);
1338 // build an UndoComment from the objects actually used
1339 aRemoveMerker.ForceSort(); // important for remove (see below)
1340 if( bUndo )
1341 SetUndoComment(ImpGetResStr(bNoPolyPoly?STR_EditCombine_OnePoly:STR_EditCombine_PolyPoly),aRemoveMerker.GetMarkDescription());
1343 // remove objects actually used from the list
1344 DeleteMarkedList(aRemoveMerker);
1345 if( bUndo )
1346 EndUndo();
1349 ////////////////////////////////////////////////////////////////////////////////////////////////////
1350 // Dismantle
1351 ////////////////////////////////////////////////////////////////////////////////////////////////////
1353 sal_Bool SdrEditView::ImpCanDismantle(const basegfx::B2DPolyPolygon& rPpolyPolygon, sal_Bool bMakeLines) const
1355 sal_Bool bCan(sal_False);
1356 const sal_uInt32 nPolygonCount(rPpolyPolygon.count());
1358 if(nPolygonCount >= 2L)
1360 // #i69172# dismantle makes sense with 2 or more polygons in a polyPolygon
1361 bCan = sal_True;
1363 else if(bMakeLines && 1L == nPolygonCount)
1365 // #i69172# ..or with at least 2 edges (curves or lines)
1366 const basegfx::B2DPolygon aPolygon(rPpolyPolygon.getB2DPolygon(0L));
1367 const sal_uInt32 nPointCount(aPolygon.count());
1369 if(nPointCount > 2L)
1371 bCan = sal_True;
1375 return bCan;
1378 sal_Bool SdrEditView::ImpCanDismantle(const SdrObject* pObj, sal_Bool bMakeLines) const
1380 bool bOtherObjs(false); // true=objects other than PathObj's existent
1381 bool bMin1PolyPoly(false); // sal_True=at least 1 PolyPolygon with more than one Polygon existent
1382 SdrObjList* pOL = pObj->GetSubList();
1384 if(pOL)
1386 // group object -- check all members if they're PathObjs
1387 SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS);
1389 while(aIter.IsMore() && !bOtherObjs)
1391 const SdrObject* pObj1 = aIter.Next();
1392 const SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj1);
1394 if(pPath)
1396 if(ImpCanDismantle(pPath->GetPathPoly(), bMakeLines))
1398 bMin1PolyPoly = true;
1401 SdrObjTransformInfoRec aInfo;
1402 pObj1->TakeObjInfo(aInfo);
1404 if(!aInfo.bCanConvToPath)
1406 // happens e. g. in the case of FontWork
1407 bOtherObjs = true;
1410 else
1412 bOtherObjs = true;
1416 else
1418 const SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj);
1419 const SdrObjCustomShape* pCustomShape = PTR_CAST(SdrObjCustomShape, pObj);
1421 // #i37011#
1422 if(pPath)
1424 if(ImpCanDismantle(pPath->GetPathPoly(),bMakeLines))
1426 bMin1PolyPoly = true;
1429 SdrObjTransformInfoRec aInfo;
1430 pObj->TakeObjInfo(aInfo);
1432 // new condition IsLine() to be able to break simple Lines
1433 if(!(aInfo.bCanConvToPath || aInfo.bCanConvToPoly) && !pPath->IsLine())
1435 // happens e. g. in the case of FontWork
1436 bOtherObjs = true;
1439 else if(pCustomShape)
1441 if(bMakeLines)
1443 // allow break command
1444 bMin1PolyPoly = true;
1447 else
1449 bOtherObjs = true;
1452 return bMin1PolyPoly && !bOtherObjs;
1455 void SdrEditView::ImpDismantleOneObject(const SdrObject* pObj, SdrObjList& rOL, sal_uIntPtr& rPos, SdrPageView* pPV, sal_Bool bMakeLines)
1457 const SdrPathObj* pSrcPath = PTR_CAST(SdrPathObj, pObj);
1458 const SdrObjCustomShape* pCustomShape = PTR_CAST(SdrObjCustomShape, pObj);
1460 const bool bUndo = IsUndoEnabled();
1462 if(pSrcPath)
1464 // #i74631# redesigned due to XpolyPolygon removal and explicit constructors
1465 SdrObject* pLast = 0; // to be able to apply OutlinerParaObject
1466 const basegfx::B2DPolyPolygon& rPolyPolygon(pSrcPath->GetPathPoly());
1467 const sal_uInt32 nPolyCount(rPolyPolygon.count());
1469 for(sal_uInt32 a(0); a < nPolyCount; a++)
1471 const basegfx::B2DPolygon& rCandidate(rPolyPolygon.getB2DPolygon(a));
1472 const sal_uInt32 nPointCount(rCandidate.count());
1474 if(!bMakeLines || nPointCount < 2)
1476 SdrPathObj* pPath = new SdrPathObj((SdrObjKind)pSrcPath->GetObjIdentifier(), basegfx::B2DPolyPolygon(rCandidate));
1477 ImpCopyAttributes(pSrcPath, pPath);
1478 pLast = pPath;
1479 SdrInsertReason aReason(SDRREASON_VIEWCALL, pSrcPath);
1480 rOL.InsertObject(pPath, rPos, &aReason);
1481 if( bUndo )
1482 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, sal_True));
1483 MarkObj(pPath, pPV, sal_False, sal_True);
1484 rPos++;
1486 else
1488 const sal_uInt32 nLoopCount(rCandidate.isClosed() ? nPointCount : nPointCount - 1);
1490 for(sal_uInt32 b(0); b < nLoopCount; b++)
1492 SdrObjKind eKind(OBJ_PLIN);
1493 basegfx::B2DPolygon aNewPolygon;
1494 const sal_uInt32 nNextIndex((b + 1) % nPointCount);
1496 aNewPolygon.append(rCandidate.getB2DPoint(b));
1498 if(rCandidate.areControlPointsUsed())
1500 aNewPolygon.appendBezierSegment(
1501 rCandidate.getNextControlPoint(b),
1502 rCandidate.getPrevControlPoint(nNextIndex),
1503 rCandidate.getB2DPoint(nNextIndex));
1504 eKind = OBJ_PATHLINE;
1506 else
1508 aNewPolygon.append(rCandidate.getB2DPoint(nNextIndex));
1511 SdrPathObj* pPath = new SdrPathObj(eKind, basegfx::B2DPolyPolygon(aNewPolygon));
1512 ImpCopyAttributes(pSrcPath, pPath);
1513 pLast = pPath;
1514 SdrInsertReason aReason(SDRREASON_VIEWCALL, pSrcPath);
1515 rOL.InsertObject(pPath, rPos, &aReason);
1516 if( bUndo )
1517 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, sal_True));
1518 MarkObj(pPath, pPV, sal_False, sal_True);
1519 rPos++;
1524 if(pLast && pSrcPath->GetOutlinerParaObject())
1526 pLast->SetOutlinerParaObject(new OutlinerParaObject(*pSrcPath->GetOutlinerParaObject()));
1529 else if(pCustomShape)
1531 if(bMakeLines)
1533 // break up custom shape
1534 const SdrObject* pReplacement = pCustomShape->GetSdrObjectFromCustomShape();
1536 if(pReplacement)
1538 SdrObject* pCandidate = pReplacement->Clone();
1539 DBG_ASSERT(pCandidate, "SdrEditView::ImpDismantleOneObject: Could not clone SdrObject (!)");
1540 pCandidate->SetModel(pCustomShape->GetModel());
1542 if(((SdrShadowItem&)pCustomShape->GetMergedItem(SDRATTR_SHADOW)).GetValue())
1544 if(pReplacement->ISA(SdrObjGroup))
1546 pCandidate->SetMergedItem(SdrShadowItem(sal_True));
1550 SdrInsertReason aReason(SDRREASON_VIEWCALL, pCustomShape);
1551 rOL.InsertObject(pCandidate, rPos, &aReason);
1552 if( bUndo )
1553 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pCandidate, true));
1554 MarkObj(pCandidate, pPV, sal_False, sal_True);
1556 if(pCustomShape->HasText() && !pCustomShape->IsTextPath())
1558 // #i37011# also create a text object and add at rPos + 1
1559 SdrTextObj* pTextObj = (SdrTextObj*)SdrObjFactory::MakeNewObject(
1560 pCustomShape->GetObjInventor(), OBJ_TEXT, 0L, pCustomShape->GetModel());
1562 // Copy text content
1563 OutlinerParaObject* pParaObj = pCustomShape->GetOutlinerParaObject();
1564 if(pParaObj)
1566 pTextObj->NbcSetOutlinerParaObject(new OutlinerParaObject(*pParaObj));
1569 // copy all attributes
1570 SfxItemSet aTargetItemSet(pCustomShape->GetMergedItemSet());
1572 // clear fill and line style
1573 aTargetItemSet.Put(XLineStyleItem(XLINE_NONE));
1574 aTargetItemSet.Put(XFillStyleItem(XFILL_NONE));
1576 // get the text bounds and set at text object
1577 Rectangle aTextBounds = pCustomShape->GetSnapRect();
1578 if(pCustomShape->GetTextBounds(aTextBounds))
1580 pTextObj->SetSnapRect(aTextBounds);
1583 // if rotated, copy GeoStat, too.
1584 const GeoStat& rSourceGeo = pCustomShape->GetGeoStat();
1585 if(rSourceGeo.nDrehWink)
1587 pTextObj->NbcRotate(
1588 pCustomShape->GetSnapRect().Center(), rSourceGeo.nDrehWink,
1589 rSourceGeo.nSin, rSourceGeo.nCos);
1592 // set modified ItemSet at text object
1593 pTextObj->SetMergedItemSet(aTargetItemSet);
1595 // insert object
1596 rOL.InsertObject(pTextObj, rPos + 1, &aReason);
1597 if( bUndo )
1598 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pTextObj, true));
1599 MarkObj(pTextObj, pPV, sal_False, sal_True);
1606 void SdrEditView::DismantleMarkedObjects(sal_Bool bMakeLines)
1608 // temporary MarkList
1609 SdrMarkList aRemoveMerker;
1611 SortMarkedObjects();
1613 const bool bUndo = IsUndoEnabled();
1615 if( bUndo )
1617 // comment is constructed later
1618 BegUndo(String(), String(),
1619 bMakeLines ? SDRREPFUNC_OBJ_DISMANTLE_LINES : SDRREPFUNC_OBJ_DISMANTLE_POLYS);
1622 sal_uIntPtr nm;
1623 sal_uIntPtr nAnz=GetMarkedObjectCount();
1624 SdrObjList* pOL0=NULL;
1625 for (nm=nAnz; nm>0;) {
1626 nm--;
1627 SdrMark* pM=GetSdrMarkByIndex(nm);
1628 SdrObject* pObj=pM->GetMarkedSdrObj();
1629 SdrPageView* pPV=pM->GetPageView();
1630 SdrObjList* pOL=pObj->GetObjList();
1631 if (pOL!=pOL0) { pOL0=pOL; pObj->GetOrdNum(); } // make sure OrdNums are correct!
1632 if (ImpCanDismantle(pObj,bMakeLines)) {
1633 aRemoveMerker.InsertEntry(SdrMark(pObj,pM->GetPageView()));
1634 sal_uIntPtr nPos0=pObj->GetOrdNumDirect();
1635 sal_uIntPtr nPos=nPos0+1;
1636 SdrObjList* pSubList=pObj->GetSubList();
1637 if (pSubList!=NULL && !pObj->Is3DObj()) {
1638 SdrObjListIter aIter(*pSubList,IM_DEEPNOGROUPS);
1639 while (aIter.IsMore()) {
1640 const SdrObject* pObj1=aIter.Next();
1641 ImpDismantleOneObject(pObj1,*pOL,nPos,pPV,bMakeLines);
1643 } else {
1644 ImpDismantleOneObject(pObj,*pOL,nPos,pPV,bMakeLines);
1646 if( bUndo )
1647 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj,sal_True));
1648 pOL->RemoveObject(nPos0);
1650 if( !bUndo )
1651 SdrObject::Free(pObj);
1655 if( bUndo )
1657 // construct UndoComment from objects actually used
1658 SetUndoComment(ImpGetResStr(bMakeLines?STR_EditDismantle_Lines:STR_EditDismantle_Polys),aRemoveMerker.GetMarkDescription());
1659 // remove objects actually used from the list
1660 EndUndo();
1664 ////////////////////////////////////////////////////////////////////////////////////////////////////
1665 // Group
1666 ////////////////////////////////////////////////////////////////////////////////////////////////////
1668 void SdrEditView::GroupMarked(const SdrObject* pUserGrp)
1670 if (AreObjectsMarked())
1672 SortMarkedObjects();
1674 const bool bUndo = IsUndoEnabled();
1675 if( bUndo )
1677 BegUndo(ImpGetResStr(STR_EditGroup),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_GROUP);
1679 const sal_uIntPtr nAnz = GetMarkedObjectCount();
1680 for(sal_uIntPtr nm = nAnz; nm>0; )
1682 // add UndoActions for all affected objects
1683 nm--;
1684 SdrMark* pM=GetSdrMarkByIndex(nm);
1685 SdrObject* pObj = pM->GetMarkedSdrObj();
1686 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pObj ) );
1687 AddUndoActions( vConnectorUndoActions );
1688 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject( *pObj ));
1692 SdrMarkList aNewMark;
1693 SdrPageView* pPV = GetSdrPageView();
1695 if(pPV)
1697 SdrObjList* pAktLst=pPV->GetObjList();
1698 SdrObjList* pSrcLst=pAktLst;
1699 SdrObjList* pSrcLst0=pSrcLst;
1700 SdrPage* pPage=pPV->GetPage();
1701 // make sure OrdNums are correct
1702 if (pSrcLst->IsObjOrdNumsDirty())
1703 pSrcLst->RecalcObjOrdNums();
1704 SdrObject* pGrp=NULL;
1705 SdrObject* pRefObj=NULL; // reference for InsertReason (-> anchors in Writer)
1706 SdrObject* pRefObj1=NULL; // reference for InsertReason (-> anchors in Writer)
1707 SdrObjList* pDstLst=NULL;
1708 // if all selected objects come from foreign object lists.
1709 // the group object is the last one in the list.
1710 sal_uIntPtr nInsPos=pSrcLst->GetObjCount();
1711 bool bNeedInsPos=true;
1712 for (sal_uIntPtr nm=GetMarkedObjectCount(); nm>0;)
1714 nm--;
1715 SdrMark* pM=GetSdrMarkByIndex(nm);
1716 if (pM->GetPageView()==pPV)
1718 if (pGrp==NULL)
1720 if (pUserGrp!=NULL)
1721 pGrp=pUserGrp->Clone();
1722 if (pGrp==NULL)
1723 pGrp=new SdrObjGroup;
1724 pDstLst=pGrp->GetSubList();
1725 DBG_ASSERT(pDstLst!=NULL,"Alleged group object doesn't return object list.");
1727 SdrObject* pObj=pM->GetMarkedSdrObj();
1728 pSrcLst=pObj->GetObjList();
1729 if (pSrcLst!=pSrcLst0)
1731 if (pSrcLst->IsObjOrdNumsDirty())
1732 pSrcLst->RecalcObjOrdNums();
1734 bool bForeignList=pSrcLst!=pAktLst;
1735 bool bGrouped=pSrcLst!=pPage;
1736 if (!bForeignList && bNeedInsPos)
1738 nInsPos=pObj->GetOrdNum(); // this way, all ObjOrdNum of the page are set
1739 nInsPos++;
1740 bNeedInsPos=false;
1742 pSrcLst->RemoveObject(pObj->GetOrdNumDirect());
1743 if (!bForeignList)
1744 nInsPos--; // correct InsertPos
1745 SdrInsertReason aReason(SDRREASON_VIEWCALL);
1746 pDstLst->InsertObject(pObj,0,&aReason);
1747 GetMarkedObjectListWriteAccess().DeleteMark(nm);
1748 if (pRefObj1==NULL)
1749 pRefObj1=pObj; // the topmost visible object
1750 if (!bGrouped)
1752 if (pRefObj==NULL)
1753 pRefObj=pObj; // the topmost visible non-group object
1755 pSrcLst0=pSrcLst;
1758 if (pRefObj==NULL)
1759 pRefObj=pRefObj1;
1760 if (pGrp!=NULL)
1762 aNewMark.InsertEntry(SdrMark(pGrp,pPV));
1763 sal_uIntPtr nAnz=pDstLst->GetObjCount();
1764 SdrInsertReason aReason(SDRREASON_VIEWCALL,pRefObj);
1765 pAktLst->InsertObject(pGrp,nInsPos,&aReason);
1766 if( bUndo )
1768 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pGrp,true)); // no recalculation!
1769 for (sal_uIntPtr no=0; no<nAnz; no++)
1771 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pDstLst->GetObj(no)));
1776 GetMarkedObjectListWriteAccess().Merge(aNewMark);
1777 MarkListHasChanged();
1779 if( bUndo )
1780 EndUndo();
1784 ////////////////////////////////////////////////////////////////////////////////////////////////////
1785 // Ungroup
1786 ////////////////////////////////////////////////////////////////////////////////////////////////////
1788 void SdrEditView::UnGroupMarked()
1790 SdrMarkList aNewMark;
1792 const bool bUndo = IsUndoEnabled();
1793 if( bUndo )
1794 BegUndo(String(), String(), SDRREPFUNC_OBJ_UNGROUP);
1796 sal_uIntPtr nCount=0;
1797 XubString aName1;
1798 XubString aName;
1799 bool bNameOk=false;
1800 for (sal_uIntPtr nm=GetMarkedObjectCount(); nm>0;) {
1801 nm--;
1802 SdrMark* pM=GetSdrMarkByIndex(nm);
1803 SdrObject* pGrp=pM->GetMarkedSdrObj();
1804 SdrObjList* pSrcLst=pGrp->GetSubList();
1805 if (pSrcLst!=NULL) {
1806 nCount++;
1807 if (nCount==1) {
1808 pGrp->TakeObjNameSingul(aName); // retrieve name of group
1809 pGrp->TakeObjNamePlural(aName1); // retrieve name of group
1810 bNameOk=true;
1811 } else {
1812 if (nCount==2) aName=aName1; // set plural name
1813 if (bNameOk) {
1814 XubString aStr;
1815 pGrp->TakeObjNamePlural(aStr); // retrieve name of group
1817 if(!aStr.Equals(aName))
1818 bNameOk = false;
1821 sal_uIntPtr nDstCnt=pGrp->GetOrdNum();
1822 SdrObjList* pDstLst=pM->GetPageView()->GetObjList();
1824 // FIRST move contained objects to parent of group, so that
1825 // the contained objects are NOT migrated to the UNDO-ItemPool
1826 // when AddUndo(new SdrUndoDelObj(*pGrp)) is called.
1827 sal_uIntPtr nAnz=pSrcLst->GetObjCount();
1828 sal_uIntPtr no;
1830 if( bUndo )
1832 for (no=nAnz; no>0;)
1834 no--;
1835 SdrObject* pObj=pSrcLst->GetObj(no);
1836 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject(*pObj));
1839 for (no=0; no<nAnz; no++)
1841 SdrObject* pObj=pSrcLst->RemoveObject(0);
1842 SdrInsertReason aReason(SDRREASON_VIEWCALL,pGrp);
1843 pDstLst->InsertObject(pObj,nDstCnt,&aReason);
1844 if( bUndo )
1845 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pObj,true));
1846 nDstCnt++;
1847 // No SortCheck when inserting into MarkList, because that would
1848 // provoke a RecalcOrdNums() each time because of pObj->GetOrdNum():
1849 aNewMark.InsertEntry(SdrMark(pObj,pM->GetPageView()),sal_False);
1852 if( bUndo )
1854 // Now it is safe to add the delete-UNDO which triggers the
1855 // MigrateItemPool now only for itself, not for the sub-objects.
1856 // nDstCnt is right, because previous inserts move group
1857 // object deeper and increase nDstCnt.
1858 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pGrp));
1860 pDstLst->RemoveObject(nDstCnt);
1862 if( !bUndo )
1863 SdrObject::Free(pGrp);
1865 GetMarkedObjectListWriteAccess().DeleteMark(nm);
1868 if (nCount!=0)
1870 if (!bNameOk)
1871 aName=ImpGetResStr(STR_ObjNamePluralGRUP); // Use the term "Group Objects," if different objects are grouped.
1872 SetUndoComment(ImpGetResStr(STR_EditUngroup),aName);
1875 if( bUndo )
1876 EndUndo();
1878 if (nCount!=0)
1880 GetMarkedObjectListWriteAccess().Merge(aNewMark,sal_True); // Because of the sorting above, aNewMark is reversed
1881 MarkListHasChanged();
1885 ////////////////////////////////////////////////////////////////////////////////////////////////////
1886 // ConvertToPoly
1887 ////////////////////////////////////////////////////////////////////////////////////////////////////
1889 SdrObject* SdrEditView::ImpConvertOneObj(SdrObject* pObj, sal_Bool bPath, sal_Bool bLineToArea)
1891 SdrObject* pNewObj = pObj->ConvertToPolyObj(bPath, bLineToArea);
1892 if (pNewObj!=NULL)
1894 SdrObjList* pOL=pObj->GetObjList();
1895 DBG_ASSERT(pOL!=NULL,"ConvertTo: Object doesn't return object list");
1896 if (pOL!=NULL)
1898 const bool bUndo = IsUndoEnabled();
1899 if( bUndo )
1900 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoReplaceObject(*pObj,*pNewObj));
1902 pOL->ReplaceObject(pNewObj,pObj->GetOrdNum());
1904 if( !bUndo )
1905 SdrObject::Free(pObj);
1908 return pNewObj;
1911 void SdrEditView::ImpConvertTo(sal_Bool bPath, sal_Bool bLineToArea)
1913 bool bMrkChg=false;
1914 if (AreObjectsMarked()) {
1915 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
1916 sal_uInt16 nDscrID=0;
1917 if(bLineToArea)
1919 if(nMarkAnz == 1)
1920 nDscrID = STR_EditConvToContour;
1921 else
1922 nDscrID = STR_EditConvToContours;
1924 BegUndo(ImpGetResStr(nDscrID), GetDescriptionOfMarkedObjects());
1926 else
1928 if (bPath) {
1929 if (nMarkAnz==1) nDscrID=STR_EditConvToCurve;
1930 else nDscrID=STR_EditConvToCurves;
1931 BegUndo(ImpGetResStr(nDscrID),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_CONVERTTOPATH);
1932 } else {
1933 if (nMarkAnz==1) nDscrID=STR_EditConvToPoly;
1934 else nDscrID=STR_EditConvToPolys;
1935 BegUndo(ImpGetResStr(nDscrID),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_CONVERTTOPOLY);
1938 for (sal_uIntPtr nm=nMarkAnz; nm>0;) {
1939 nm--;
1940 SdrMark* pM=GetSdrMarkByIndex(nm);
1941 SdrObject* pObj=pM->GetMarkedSdrObj();
1942 SdrPageView* pPV=pM->GetPageView();
1943 if (pObj->IsGroupObject() && !pObj->Is3DObj()) {
1944 SdrObject* pGrp=pObj;
1945 SdrObjListIter aIter(*pGrp,IM_DEEPNOGROUPS);
1946 while (aIter.IsMore()) {
1947 pObj=aIter.Next();
1948 ImpConvertOneObj(pObj,bPath,bLineToArea);
1950 } else {
1951 SdrObject* pNewObj=ImpConvertOneObj(pObj,bPath,bLineToArea);
1952 if (pNewObj!=NULL) {
1953 bMrkChg=true;
1954 GetMarkedObjectListWriteAccess().ReplaceMark(SdrMark(pNewObj,pPV),nm);
1958 EndUndo();
1959 if (bMrkChg) AdjustMarkHdl();
1960 if (bMrkChg) MarkListHasChanged();
1964 void SdrEditView::ConvertMarkedToPathObj(sal_Bool bLineToArea)
1966 ImpConvertTo(sal_True, bLineToArea);
1969 void SdrEditView::ConvertMarkedToPolyObj(sal_Bool bLineToArea)
1971 ImpConvertTo(sal_False, bLineToArea);
1974 ////////////////////////////////////////////////////////////////////////////////////////////////////
1975 // Metafile Import
1976 ////////////////////////////////////////////////////////////////////////////////////////////////////
1978 void SdrEditView::DoImportMarkedMtf(SvdProgressInfo *pProgrInfo)
1980 const bool bUndo = IsUndoEnabled();
1982 if( bUndo )
1983 BegUndo(String(), String(), SDRREPFUNC_OBJ_IMPORTMTF);
1985 SortMarkedObjects();
1986 SdrMarkList aForTheDescription;
1987 SdrMarkList aNewMarked;
1988 sal_uIntPtr nAnz=GetMarkedObjectCount();
1990 for (sal_uIntPtr nm=nAnz; nm>0;)
1991 { // create Undo objects for all new objects
1992 // check for cancellation between the metafiles
1993 if( pProgrInfo != NULL )
1995 pProgrInfo->SetNextObject();
1996 if(!pProgrInfo->ReportActions(0))
1997 break;
2000 nm--;
2001 SdrMark* pM=GetSdrMarkByIndex(nm);
2002 SdrObject* pObj=pM->GetMarkedSdrObj();
2003 SdrPageView* pPV=pM->GetPageView();
2004 SdrObjList* pOL=pObj->GetObjList();
2005 sal_uIntPtr nInsPos=pObj->GetOrdNum()+1;
2006 SdrGrafObj* pGraf=PTR_CAST(SdrGrafObj,pObj);
2007 SdrOle2Obj* pOle2=PTR_CAST(SdrOle2Obj,pObj);
2008 sal_uIntPtr nInsAnz=0;
2009 Rectangle aLogicRect;
2011 if(pGraf && (pGraf->HasGDIMetaFile() || pGraf->isEmbeddedSvg()))
2013 GDIMetaFile aMetaFile;
2015 if(pGraf->HasGDIMetaFile())
2017 aMetaFile = pGraf->GetTransformedGraphic(SDRGRAFOBJ_TRANSFORMATTR_COLOR|SDRGRAFOBJ_TRANSFORMATTR_MIRROR).GetGDIMetaFile();
2019 else if(pGraf->isEmbeddedSvg())
2021 aMetaFile = pGraf->getMetafileFromEmbeddedSvg();
2024 if(aMetaFile.GetActionSize())
2026 aLogicRect = pGraf->GetLogicRect();
2027 ImpSdrGDIMetaFileImport aFilter(*pMod, pObj->GetLayer(), aLogicRect);
2028 nInsAnz = aFilter.DoImport(aMetaFile, *pOL, nInsPos, pProgrInfo);
2031 if ( pOle2!=NULL && pOle2->GetGraphic() )
2033 aLogicRect = pOle2->GetLogicRect();
2034 ImpSdrGDIMetaFileImport aFilter(*pMod, pObj->GetLayer(), aLogicRect);
2035 nInsAnz = aFilter.DoImport(pOle2->GetGraphic()->GetGDIMetaFile(), *pOL, nInsPos, pProgrInfo);
2037 if (nInsAnz!=0)
2039 // transformation
2040 GeoStat aGeoStat(pGraf ? pGraf->GetGeoStat() : pOle2->GetGeoStat());
2041 sal_uIntPtr nObj=nInsPos;
2043 if(aGeoStat.nShearWink)
2045 aGeoStat.RecalcTan();
2048 if(aGeoStat.nDrehWink)
2050 aGeoStat.RecalcSinCos();
2053 for (sal_uIntPtr i=0; i<nInsAnz; i++)
2055 if( bUndo )
2056 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pOL->GetObj(nObj)));
2058 // update new MarkList
2059 SdrObject* pCandidate = pOL->GetObj(nObj);
2061 // apply original transformation
2062 if(aGeoStat.nShearWink)
2064 pCandidate->NbcShear(aLogicRect.TopLeft(), aGeoStat.nShearWink, aGeoStat.nTan, false);
2067 if(aGeoStat.nDrehWink)
2069 pCandidate->NbcRotate(aLogicRect.TopLeft(), aGeoStat.nDrehWink, aGeoStat.nSin, aGeoStat.nCos);
2072 SdrMark aNewMark(pCandidate, pPV);
2073 aNewMarked.InsertEntry(aNewMark);
2075 nObj++;
2077 aForTheDescription.InsertEntry(*pM);
2079 if( bUndo )
2080 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj));
2082 // remove object from selection and delete
2083 GetMarkedObjectListWriteAccess().DeleteMark(TryToFindMarkedObject(pObj));
2084 pOL->RemoveObject(nInsPos-1);
2086 if( !bUndo )
2087 SdrObject::Free(pObj);
2091 if(aNewMarked.GetMarkCount())
2093 // create new selection
2094 for(sal_uIntPtr a(0); a < aNewMarked.GetMarkCount(); a++)
2096 GetMarkedObjectListWriteAccess().InsertEntry(*aNewMarked.GetMark(a));
2099 SortMarkedObjects();
2102 if( bUndo )
2104 SetUndoComment(ImpGetResStr(STR_EditImportMtf),aForTheDescription.GetMarkDescription());
2105 EndUndo();
2109 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */