Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / svx / source / svdraw / svdedtv2.cxx
blob4fd186a518e5622321a2f4bd1aaa8c96ff6c783c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <svx/svdedtv.hxx>
31 #include <editeng/outliner.hxx>
32 #include <svx/svdundo.hxx>
33 #include <svx/svdogrp.hxx> // for grouping objects
34 #include <svx/svdovirt.hxx> // for VirtualObject bundling (Writer)
35 #include <svx/svdopath.hxx> // for CombineObjects
36 #include <svx/svdpage.hxx>
37 #include <svx/svdpagv.hxx>
38 #include "svx/svditer.hxx"
39 #include <svx/svdograf.hxx> // for Possibilities
40 #include <svx/svdoole2.hxx> // and Mtf-Import
41 #include "svx/svdstr.hrc" // names taken from the resource
42 #include "svx/svdglob.hxx" // StringCache
43 #include "svdfmtf.hxx"
44 #include <svx/svdetc.hxx>
45 #include <sfx2/basedlgs.hxx>
46 #include <vcl/msgbox.hxx>
47 #include <editeng/outlobj.hxx>
48 #include <editeng/eeitem.hxx>
49 #include <basegfx/polygon/b2dpolypolygon.hxx>
50 #include <basegfx/polygon/b2dpolypolygontools.hxx>
52 #include <svx/svxdlg.hxx>
53 #include <svx/dialogs.hrc>
55 // #i37011#
56 #include <svx/svdoashp.hxx>
57 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
59 #include <vector>
60 using ::std::vector;
62 SdrObject* SdrEditView::GetMaxToTopObj(SdrObject* /*pObj*/) const
64 return NULL;
67 SdrObject* SdrEditView::GetMaxToBtmObj(SdrObject* /*pObj*/) const
69 return NULL;
72 void SdrEditView::ObjOrderChanged(SdrObject* /*pObj*/, sal_uIntPtr /*nOldPos*/, sal_uIntPtr /*nNewPos*/)
76 void SdrEditView::MovMarkedToTop()
78 sal_uIntPtr nAnz=GetMarkedObjectCount();
79 if (nAnz!=0)
81 const bool bUndo = IsUndoEnabled();
83 if( bUndo )
84 BegUndo(ImpGetResStr(STR_EditMovToTop),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVTOTOP);
86 SortMarkedObjects();
87 sal_uIntPtr nm;
88 for (nm=0; nm<nAnz; nm++)
89 { // All Ordnums have to be correct!
90 GetMarkedObjectByIndex(nm)->GetOrdNum();
92 sal_Bool bChg=sal_False;
93 SdrObjList* pOL0=NULL;
94 sal_uIntPtr nNewPos=0;
95 for (nm=nAnz; nm>0;)
97 nm--;
98 SdrMark* pM=GetSdrMarkByIndex(nm);
99 SdrObject* pObj=pM->GetMarkedSdrObj();
100 SdrObjList* pOL=pObj->GetObjList();
101 if (pOL!=pOL0)
103 nNewPos=sal_uIntPtr(pOL->GetObjCount()-1);
104 pOL0=pOL;
106 sal_uIntPtr nNowPos=pObj->GetOrdNumDirect();
107 const Rectangle& rBR=pObj->GetCurrentBoundRect();
108 sal_uIntPtr nCmpPos=nNowPos+1;
109 SdrObject* pMaxObj=GetMaxToTopObj(pObj);
110 if (pMaxObj!=NULL)
112 sal_uIntPtr nMaxPos=pMaxObj->GetOrdNum();
113 if (nMaxPos!=0)
114 nMaxPos--;
115 if (nNewPos>nMaxPos)
116 nNewPos=nMaxPos; // neither go faster...
117 if (nNewPos<nNowPos)
118 nNewPos=nNowPos; // nor go in the other direction
120 sal_Bool bEnd=sal_False;
121 while (nCmpPos<nNewPos && !bEnd)
123 SdrObject* pCmpObj=pOL->GetObj(nCmpPos);
124 if (pCmpObj==NULL)
126 OSL_FAIL("MovMarkedToTop(): Reference object not found.");
127 bEnd=sal_True;
129 else if (pCmpObj==pMaxObj)
131 nNewPos=nCmpPos;
132 nNewPos--;
133 bEnd=sal_True;
135 else if (rBR.IsOver(pCmpObj->GetCurrentBoundRect()))
137 nNewPos=nCmpPos;
138 bEnd=sal_True;
140 else
142 nCmpPos++;
145 if (nNowPos!=nNewPos)
147 bChg=sal_True;
148 pOL->SetObjectOrdNum(nNowPos,nNewPos);
149 if( bUndo )
150 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
151 ObjOrderChanged(pObj,nNowPos,nNewPos);
153 nNewPos--;
156 if( bUndo )
157 EndUndo();
159 if (bChg)
160 MarkListHasChanged();
164 void SdrEditView::MovMarkedToBtm()
166 sal_uIntPtr nAnz=GetMarkedObjectCount();
167 if (nAnz!=0)
169 const bool bUndo = IsUndoEnabled();
171 if( bUndo )
172 BegUndo(ImpGetResStr(STR_EditMovToBtm),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVTOBTM);
174 SortMarkedObjects();
175 sal_uIntPtr nm;
176 for (nm=0; nm<nAnz; nm++)
177 { // All Ordnums have to be correct!
178 GetMarkedObjectByIndex(nm)->GetOrdNum();
181 sal_Bool bChg=sal_False;
182 SdrObjList* pOL0=NULL;
183 sal_uIntPtr nNewPos=0;
184 for (nm=0; nm<nAnz; nm++)
186 SdrMark* pM=GetSdrMarkByIndex(nm);
187 SdrObject* pObj=pM->GetMarkedSdrObj();
188 SdrObjList* pOL=pObj->GetObjList();
189 if (pOL!=pOL0)
191 nNewPos=0;
192 pOL0=pOL;
194 sal_uIntPtr nNowPos=pObj->GetOrdNumDirect();
195 const Rectangle& rBR=pObj->GetCurrentBoundRect();
196 sal_uIntPtr nCmpPos=nNowPos; if (nCmpPos>0) nCmpPos--;
197 SdrObject* pMaxObj=GetMaxToBtmObj(pObj);
198 if (pMaxObj!=NULL)
200 sal_uIntPtr nMinPos=pMaxObj->GetOrdNum()+1;
201 if (nNewPos<nMinPos)
202 nNewPos=nMinPos; // neither go faster...
203 if (nNewPos>nNowPos)
204 nNewPos=nNowPos; // nor go in the other direction
206 sal_Bool bEnd=sal_False;
207 // nNewPos in this case is the "maximum" position
208 // the object may reach without going faster than the object before
209 // it (multiple selection).
210 while (nCmpPos>nNewPos && !bEnd)
212 SdrObject* pCmpObj=pOL->GetObj(nCmpPos);
213 if (pCmpObj==NULL)
215 OSL_FAIL("MovMarkedToBtm(): Reference object not found.");
216 bEnd=sal_True;
218 else if (pCmpObj==pMaxObj)
220 nNewPos=nCmpPos;
221 nNewPos++;
222 bEnd=sal_True;
224 else if (rBR.IsOver(pCmpObj->GetCurrentBoundRect()))
226 nNewPos=nCmpPos;
227 bEnd=sal_True;
229 else
231 nCmpPos--;
234 if (nNowPos!=nNewPos)
236 bChg=sal_True;
237 pOL->SetObjectOrdNum(nNowPos,nNewPos);
238 if( bUndo )
239 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
240 ObjOrderChanged(pObj,nNowPos,nNewPos);
242 nNewPos++;
245 if(bUndo)
246 EndUndo();
248 if(bChg)
249 MarkListHasChanged();
253 void SdrEditView::PutMarkedToTop()
255 PutMarkedInFrontOfObj(NULL);
258 void SdrEditView::PutMarkedInFrontOfObj(const SdrObject* pRefObj)
260 sal_uIntPtr nAnz=GetMarkedObjectCount();
261 if (nAnz!=0)
263 const bool bUndo = IsUndoEnabled();
264 if( bUndo )
265 BegUndo(ImpGetResStr(STR_EditPutToTop),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_PUTTOTOP);
267 SortMarkedObjects();
269 if (pRefObj!=NULL)
271 // Make "in front of the object" work, even if the
272 // selected objects are already in front of the other object
273 sal_uIntPtr nRefMark=TryToFindMarkedObject(pRefObj);
274 SdrMark aRefMark;
275 if (nRefMark!=CONTAINER_ENTRY_NOTFOUND)
277 aRefMark=*GetSdrMarkByIndex(nRefMark);
278 GetMarkedObjectListWriteAccess().DeleteMark(nRefMark);
280 PutMarkedToBtm();
281 if (nRefMark!=CONTAINER_ENTRY_NOTFOUND)
283 GetMarkedObjectListWriteAccess().InsertEntry(aRefMark);
284 SortMarkedObjects();
287 sal_uIntPtr nm;
288 for (nm=0; nm<nAnz; nm++)
289 { // All Ordnums have to be correct!
290 GetMarkedObjectByIndex(nm)->GetOrdNum();
292 sal_Bool bChg=sal_False;
293 SdrObjList* pOL0=NULL;
294 sal_uIntPtr nNewPos=0;
295 for (nm=nAnz; nm>0;)
297 nm--;
298 SdrMark* pM=GetSdrMarkByIndex(nm);
299 SdrObject* pObj=pM->GetMarkedSdrObj();
300 if (pObj!=pRefObj)
302 SdrObjList* pOL=pObj->GetObjList();
303 if (pOL!=pOL0)
305 nNewPos=sal_uIntPtr(pOL->GetObjCount()-1);
306 pOL0=pOL;
308 sal_uIntPtr nNowPos=pObj->GetOrdNumDirect();
309 SdrObject* pMaxObj=GetMaxToTopObj(pObj);
310 if (pMaxObj!=NULL)
312 sal_uIntPtr nMaxOrd=pMaxObj->GetOrdNum(); // sadly doesn't work any other way
313 if (nMaxOrd>0)
314 nMaxOrd--;
315 if (nNewPos>nMaxOrd)
316 nNewPos=nMaxOrd; // neither go faster...
317 if (nNewPos<nNowPos)
318 nNewPos=nNowPos; // nor go into the other direction
320 if (pRefObj!=NULL)
322 if (pRefObj->GetObjList()==pObj->GetObjList())
324 sal_uIntPtr nMaxOrd=pRefObj->GetOrdNum(); // sadly doesn't work any other way
325 if (nNewPos>nMaxOrd)
326 nNewPos=nMaxOrd; // neither go faster...
327 if (nNewPos<nNowPos)
328 nNewPos=nNowPos; // nor go into the other direction
330 else
332 nNewPos=nNowPos; // different PageView, so don't change
335 if (nNowPos!=nNewPos)
337 bChg=sal_True;
338 pOL->SetObjectOrdNum(nNowPos,nNewPos);
339 if( bUndo )
340 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
341 ObjOrderChanged(pObj,nNowPos,nNewPos);
343 nNewPos--;
344 } // if (pObj!=pRefObj)
345 } // for loop over all selected objects
347 if( bUndo )
348 EndUndo();
350 if(bChg)
351 MarkListHasChanged();
355 void SdrEditView::PutMarkedToBtm()
357 PutMarkedBehindObj(NULL);
360 void SdrEditView::PutMarkedBehindObj(const SdrObject* pRefObj)
362 sal_uIntPtr nAnz=GetMarkedObjectCount();
363 if (nAnz!=0)
365 const bool bUndo = IsUndoEnabled();
367 if( bUndo )
368 BegUndo(ImpGetResStr(STR_EditPutToBtm),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_PUTTOBTM);
370 SortMarkedObjects();
371 if (pRefObj!=NULL)
373 // Make "behind the object" work, even if the
374 // selected objects are already behind the other object
375 sal_uIntPtr nRefMark=TryToFindMarkedObject(pRefObj);
376 SdrMark aRefMark;
377 if (nRefMark!=CONTAINER_ENTRY_NOTFOUND)
379 aRefMark=*GetSdrMarkByIndex(nRefMark);
380 GetMarkedObjectListWriteAccess().DeleteMark(nRefMark);
382 PutMarkedToTop();
383 if (nRefMark!=CONTAINER_ENTRY_NOTFOUND)
385 GetMarkedObjectListWriteAccess().InsertEntry(aRefMark);
386 SortMarkedObjects();
389 sal_uIntPtr nm;
390 for (nm=0; nm<nAnz; nm++) { // All Ordnums have to be correct!
391 GetMarkedObjectByIndex(nm)->GetOrdNum();
393 sal_Bool bChg=sal_False;
394 SdrObjList* pOL0=NULL;
395 sal_uIntPtr nNewPos=0;
396 for (nm=0; nm<nAnz; nm++) {
397 SdrMark* pM=GetSdrMarkByIndex(nm);
398 SdrObject* pObj=pM->GetMarkedSdrObj();
399 if (pObj!=pRefObj) {
400 SdrObjList* pOL=pObj->GetObjList();
401 if (pOL!=pOL0) {
402 nNewPos=0;
403 pOL0=pOL;
405 sal_uIntPtr nNowPos=pObj->GetOrdNumDirect();
406 SdrObject* pMinObj=GetMaxToBtmObj(pObj);
407 if (pMinObj!=NULL) {
408 sal_uIntPtr nMinOrd=pMinObj->GetOrdNum()+1; // sadly doesn't work any differently
409 if (nNewPos<nMinOrd) nNewPos=nMinOrd; // neither go faster...
410 if (nNewPos>nNowPos) nNewPos=nNowPos; // nor go into the other direction
412 if (pRefObj!=NULL) {
413 if (pRefObj->GetObjList()==pObj->GetObjList()) {
414 sal_uIntPtr nMinOrd=pRefObj->GetOrdNum(); // sadly doesn't work any differently
415 if (nNewPos<nMinOrd) nNewPos=nMinOrd; // neither go faster...
416 if (nNewPos>nNowPos) nNewPos=nNowPos; // nor go into the other direction
417 } else {
418 nNewPos=nNowPos; // different PageView, so don't change
421 if (nNowPos!=nNewPos) {
422 bChg=sal_True;
423 pOL->SetObjectOrdNum(nNowPos,nNewPos);
424 if( bUndo )
425 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
426 ObjOrderChanged(pObj,nNowPos,nNewPos);
428 nNewPos++;
429 } // if (pObj!=pRefObj)
430 } // for loop over all selected objects
432 if(bUndo)
433 EndUndo();
435 if(bChg)
436 MarkListHasChanged();
440 void SdrEditView::ReverseOrderOfMarked()
442 SortMarkedObjects();
443 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
444 if (nMarkAnz>0)
446 sal_Bool bChg=sal_False;
448 bool bUndo = IsUndoEnabled();
449 if( bUndo )
450 BegUndo(ImpGetResStr(STR_EditRevOrder),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_REVORDER);
452 sal_uIntPtr a=0;
453 do {
454 // take into account selection across multiple PageViews
455 sal_uIntPtr b=a+1;
456 while (b<nMarkAnz && GetSdrPageViewOfMarkedByIndex(b) == GetSdrPageViewOfMarkedByIndex(a)) b++;
457 b--;
458 SdrObjList* pOL=GetSdrPageViewOfMarkedByIndex(a)->GetObjList();
459 sal_uIntPtr c=b;
460 if (a<c) { // make sure OrdNums aren't dirty
461 GetMarkedObjectByIndex(a)->GetOrdNum();
463 while (a<c) {
464 SdrObject* pObj1=GetMarkedObjectByIndex(a);
465 SdrObject* pObj2=GetMarkedObjectByIndex(c);
466 sal_uIntPtr nOrd1=pObj1->GetOrdNumDirect();
467 sal_uIntPtr nOrd2=pObj2->GetOrdNumDirect();
468 if( bUndo )
470 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj1,nOrd1,nOrd2));
471 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj2,nOrd2-1,nOrd1));
473 pOL->SetObjectOrdNum(nOrd1,nOrd2);
474 // Obj 2 has moved forward by one position, so now nOrd2-1
475 pOL->SetObjectOrdNum(nOrd2-1,nOrd1);
476 // use Replace instead of SetOrdNum for performance reasons (recalculation of Ordnums)
477 a++; c--;
478 bChg=sal_True;
480 a=b+1;
481 } while (a<nMarkAnz);
483 if(bUndo)
484 EndUndo();
486 if(bChg)
487 MarkListHasChanged();
491 void SdrEditView::ImpCheckToTopBtmPossible()
493 sal_uIntPtr nAnz=GetMarkedObjectCount();
494 if (nAnz==0)
495 return;
496 if (nAnz==1)
497 { // special-casing for single selection
498 SdrObject* pObj=GetMarkedObjectByIndex(0);
499 SdrObjList* pOL=pObj->GetObjList();
500 sal_uIntPtr nMax=pOL->GetObjCount();
501 sal_uIntPtr nMin=0;
502 sal_uIntPtr nObjNum=pObj->GetOrdNum();
503 SdrObject* pRestrict=GetMaxToTopObj(pObj);
504 if (pRestrict!=NULL) {
505 sal_uIntPtr nRestrict=pRestrict->GetOrdNum();
506 if (nRestrict<nMax) nMax=nRestrict;
508 pRestrict=GetMaxToBtmObj(pObj);
509 if (pRestrict!=NULL) {
510 sal_uIntPtr nRestrict=pRestrict->GetOrdNum();
511 if (nRestrict>nMin) nMin=nRestrict;
513 bToTopPossible=nObjNum<sal_uIntPtr(nMax-1);
514 bToBtmPossible=nObjNum>nMin;
515 } else { // multiple selection
516 sal_uIntPtr nm=0;
517 SdrObjList* pOL0=NULL;
518 long nPos0=-1;
519 while (!bToBtmPossible && nm<nAnz) { // check 'send to background'
520 SdrObject* pObj=GetMarkedObjectByIndex(nm);
521 SdrObjList* pOL=pObj->GetObjList();
522 if (pOL!=pOL0) {
523 nPos0=-1;
524 pOL0=pOL;
526 sal_uIntPtr nPos=pObj->GetOrdNum();
527 bToBtmPossible=nPos>sal_uIntPtr(nPos0+1);
528 nPos0=long(nPos);
529 nm++;
531 nm=nAnz;
532 pOL0=NULL;
533 nPos0=0x7FFFFFFF;
534 while (!bToTopPossible && nm>0) { // check 'bring to front'
535 nm--;
536 SdrObject* pObj=GetMarkedObjectByIndex(nm);
537 SdrObjList* pOL=pObj->GetObjList();
538 if (pOL!=pOL0) {
539 nPos0=pOL->GetObjCount();
540 pOL0=pOL;
542 sal_uIntPtr nPos=pObj->GetOrdNum();
543 bToTopPossible=nPos+1<sal_uIntPtr(nPos0);
544 nPos0=nPos;
549 ////////////////////////////////////////////////////////////////////////////////////////////////////
550 // Combine
551 ////////////////////////////////////////////////////////////////////////////////////////////////////
553 void SdrEditView::ImpCopyAttributes(const SdrObject* pSource, SdrObject* pDest) const
555 if (pSource!=NULL) {
556 SdrObjList* pOL=pSource->GetSubList();
557 if (pOL!=NULL && !pSource->Is3DObj()) { // get first non-group object from group
558 SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS);
559 pSource=aIter.Next();
563 if(pSource && pDest)
565 SfxItemSet aSet(pMod->GetItemPool(),
566 SDRATTR_START, SDRATTR_NOTPERSIST_FIRST-1,
567 SDRATTR_NOTPERSIST_LAST+1, SDRATTR_END,
568 EE_ITEMS_START, EE_ITEMS_END,
569 0, 0);
571 aSet.Put(pSource->GetMergedItemSet());
573 pDest->ClearMergedItem();
574 pDest->SetMergedItemSet(aSet);
576 pDest->NbcSetLayer(pSource->GetLayer());
577 pDest->NbcSetStyleSheet(pSource->GetStyleSheet(), sal_True);
581 sal_Bool SdrEditView::ImpCanConvertForCombine1(const SdrObject* pObj) const
583 // new condition IsLine() to be able to combine simple Lines
584 sal_Bool bIsLine(sal_False);
586 const SdrPathObj* pPath = PTR_CAST(SdrPathObj,pObj);
588 if(pPath)
590 bIsLine = pPath->IsLine();
593 SdrObjTransformInfoRec aInfo;
594 pObj->TakeObjInfo(aInfo);
596 return (aInfo.bCanConvToPath || aInfo.bCanConvToPoly || bIsLine);
599 sal_Bool SdrEditView::ImpCanConvertForCombine(const SdrObject* pObj) const
601 SdrObjList* pOL = pObj->GetSubList();
603 if(pOL && !pObj->Is3DObj())
605 SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS);
607 while(aIter.IsMore())
609 SdrObject* pObj1 = aIter.Next();
611 // all members of a group have to be convertible
612 if(!ImpCanConvertForCombine1(pObj1))
614 return sal_False;
618 else
620 if(!ImpCanConvertForCombine1(pObj))
622 return sal_False;
626 return sal_True;
629 basegfx::B2DPolyPolygon SdrEditView::ImpGetPolyPolygon1(const SdrObject* pObj, sal_Bool bCombine) const
631 basegfx::B2DPolyPolygon aRetval;
632 SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj);
634 if(bCombine && pPath && !pObj->GetOutlinerParaObject())
636 aRetval = pPath->GetPathPoly();
638 else
640 SdrObject* pConvObj = pObj->ConvertToPolyObj(bCombine, sal_False);
642 if(pConvObj)
644 SdrObjList* pOL = pConvObj->GetSubList();
646 if(pOL)
648 SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS);
650 while(aIter.IsMore())
652 SdrObject* pObj1 = aIter.Next();
653 pPath = PTR_CAST(SdrPathObj, pObj1);
655 if(pPath)
657 aRetval.append(pPath->GetPathPoly());
661 else
663 pPath = PTR_CAST(SdrPathObj, pConvObj);
665 if(pPath)
667 aRetval = pPath->GetPathPoly();
671 SdrObject::Free( pConvObj );
675 return aRetval;
678 basegfx::B2DPolyPolygon SdrEditView::ImpGetPolyPolygon(const SdrObject* pObj, sal_Bool bCombine) const
680 SdrObjList* pOL = pObj->GetSubList();
682 if(pOL && !pObj->Is3DObj())
684 basegfx::B2DPolyPolygon aRetval;
685 SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS);
687 while(aIter.IsMore())
689 SdrObject* pObj1 = aIter.Next();
690 aRetval.append(ImpGetPolyPolygon1(pObj1, bCombine));
693 return aRetval;
695 else
697 return ImpGetPolyPolygon1(pObj, bCombine);
701 basegfx::B2DPolygon SdrEditView::ImpCombineToSinglePolygon(const basegfx::B2DPolyPolygon& rPolyPolygon) const
703 const sal_uInt32 nPolyCount(rPolyPolygon.count());
705 if(0L == nPolyCount)
707 return basegfx::B2DPolygon();
709 else if(1L == nPolyCount)
711 return rPolyPolygon.getB2DPolygon(0L);
713 else
715 basegfx::B2DPolygon aRetval(rPolyPolygon.getB2DPolygon(0L));
717 for(sal_uInt32 a(1L); a < nPolyCount; a++)
719 basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a));
721 if(aRetval.count())
723 if(aCandidate.count())
725 const basegfx::B2DPoint aCA(aCandidate.getB2DPoint(0L));
726 const basegfx::B2DPoint aCB(aCandidate.getB2DPoint(aCandidate.count() - 1L));
727 const basegfx::B2DPoint aRA(aRetval.getB2DPoint(0L));
728 const basegfx::B2DPoint aRB(aRetval.getB2DPoint(aRetval.count() - 1L));
730 const double fRACA(basegfx::B2DVector(aCA - aRA).getLength());
731 const double fRACB(basegfx::B2DVector(aCB - aRA).getLength());
732 const double fRBCA(basegfx::B2DVector(aCA - aRB).getLength());
733 const double fRBCB(basegfx::B2DVector(aCB - aRB).getLength());
735 const double fSmallestRA(fRACA < fRACB ? fRACA : fRACB);
736 const double fSmallestRB(fRBCA < fRBCB ? fRBCA : fRBCB);
738 if(fSmallestRA < fSmallestRB)
740 // flip result
741 aRetval.flip();
744 const double fSmallestCA(fRACA < fRBCA ? fRACA : fRBCA);
745 const double fSmallestCB(fRACB < fRBCB ? fRACB : fRBCB);
747 if(fSmallestCB < fSmallestCA)
749 // flip candidate
750 aCandidate.flip();
753 // append candidate to retval
754 aRetval.append(aCandidate);
757 else
759 aRetval = aCandidate;
763 return aRetval;
767 // for distribution dialog function
768 struct ImpDistributeEntry
770 SdrObject* mpObj;
771 sal_Int32 mnPos;
772 sal_Int32 mnLength;
775 typedef vector< ImpDistributeEntry*> ImpDistributeEntryList;
777 void SdrEditView::DistributeMarkedObjects()
779 sal_uInt32 nMark(GetMarkedObjectCount());
781 if(nMark > 2)
783 SfxItemSet aNewAttr(pMod->GetItemPool());
785 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
786 if(pFact)
788 AbstractSvxDistributeDialog *pDlg = pFact->CreateSvxDistributeDialog(NULL, aNewAttr);
789 DBG_ASSERT(pDlg, "Dialogdiet fail!");
791 sal_uInt16 nResult = pDlg->Execute();
793 if(nResult == RET_OK)
795 SvxDistributeHorizontal eHor = pDlg->GetDistributeHor();
796 SvxDistributeVertical eVer = pDlg->GetDistributeVer();
797 ImpDistributeEntryList aEntryList;
798 ImpDistributeEntryList::iterator itEntryList;
799 sal_uInt32 nFullLength;
801 const bool bUndo = IsUndoEnabled();
802 if( bUndo )
803 BegUndo();
805 if(eHor != SvxDistributeHorizontalNone)
807 // build sorted entry list
808 nFullLength = 0L;
810 for( sal_uInt32 a = 0; a < nMark; a++ )
812 SdrMark* pMark = GetSdrMarkByIndex(a);
813 ImpDistributeEntry* pNew = new ImpDistributeEntry;
815 pNew->mpObj = pMark->GetMarkedSdrObj();
817 switch(eHor)
819 case SvxDistributeHorizontalLeft:
821 pNew->mnPos = pNew->mpObj->GetSnapRect().Left();
822 break;
824 case SvxDistributeHorizontalCenter:
826 pNew->mnPos = (pNew->mpObj->GetSnapRect().Right() + pNew->mpObj->GetSnapRect().Left()) / 2;
827 break;
829 case SvxDistributeHorizontalDistance:
831 pNew->mnLength = pNew->mpObj->GetSnapRect().GetWidth() + 1;
832 nFullLength += pNew->mnLength;
833 pNew->mnPos = (pNew->mpObj->GetSnapRect().Right() + pNew->mpObj->GetSnapRect().Left()) / 2;
834 break;
836 case SvxDistributeHorizontalRight:
838 pNew->mnPos = pNew->mpObj->GetSnapRect().Right();
839 break;
841 default: break;
844 for ( itEntryList = aEntryList.begin();
845 itEntryList < aEntryList.end() && (*itEntryList)->mnPos < pNew->mnPos;
846 ++itEntryList )
848 if ( itEntryList < aEntryList.end() )
849 aEntryList.insert( itEntryList, pNew );
850 else
851 aEntryList.push_back( pNew );
854 if(eHor == SvxDistributeHorizontalDistance)
856 // calculate room in-between
857 sal_Int32 nWidth = GetAllMarkedBoundRect().GetWidth() + 1;
858 double fStepWidth = ((double)nWidth - (double)nFullLength) / (double)(aEntryList.size() - 1);
859 double fStepStart = (double)aEntryList[ 0 ]->mnPos;
860 fStepStart += fStepWidth + (double)((aEntryList[ 0 ]->mnLength + aEntryList[ 1 ]->mnLength) / 2);
862 // move entries 1..n-1
863 for( size_t i = 1, n = aEntryList.size()-1; i < n; ++i )
865 ImpDistributeEntry* pCurr = aEntryList[ i ];
866 ImpDistributeEntry* pNext = aEntryList[ i + 1];
867 sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos;
868 if( bUndo )
869 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj));
870 pCurr->mpObj->Move(Size(nDelta, 0));
871 fStepStart += fStepWidth + (double)((pCurr->mnLength + pNext->mnLength) / 2);
874 else
876 // calculate distances
877 sal_Int32 nWidth = aEntryList[ aEntryList.size() - 1 ]->mnPos - aEntryList[ 0 ]->mnPos;
878 double fStepWidth = (double)nWidth / (double)(aEntryList.size() - 1);
879 double fStepStart = (double)aEntryList[ 0 ]->mnPos;
880 fStepStart += fStepWidth;
882 // move entries 1..n-1
883 for( size_t i = 1 ; i < aEntryList.size()-1 ; ++i )
885 ImpDistributeEntry* pCurr = aEntryList[ i ];
886 sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos;
887 if( bUndo )
888 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj));
889 pCurr->mpObj->Move(Size(nDelta, 0));
890 fStepStart += fStepWidth;
894 // clear list
895 for ( size_t i = 0, n = aEntryList.size(); i < n; ++i )
896 delete aEntryList[ i ];
897 aEntryList.clear();
900 if(eVer != SvxDistributeVerticalNone)
902 // build sorted entry list
903 nFullLength = 0L;
905 for( sal_uInt32 a = 0; a < nMark; a++ )
907 SdrMark* pMark = GetSdrMarkByIndex(a);
908 ImpDistributeEntry* pNew = new ImpDistributeEntry;
910 pNew->mpObj = pMark->GetMarkedSdrObj();
912 switch(eVer)
914 case SvxDistributeVerticalTop:
916 pNew->mnPos = pNew->mpObj->GetSnapRect().Top();
917 break;
919 case SvxDistributeVerticalCenter:
921 pNew->mnPos = (pNew->mpObj->GetSnapRect().Bottom() + pNew->mpObj->GetSnapRect().Top()) / 2;
922 break;
924 case SvxDistributeVerticalDistance:
926 pNew->mnLength = pNew->mpObj->GetSnapRect().GetHeight() + 1;
927 nFullLength += pNew->mnLength;
928 pNew->mnPos = (pNew->mpObj->GetSnapRect().Bottom() + pNew->mpObj->GetSnapRect().Top()) / 2;
929 break;
931 case SvxDistributeVerticalBottom:
933 pNew->mnPos = pNew->mpObj->GetSnapRect().Bottom();
934 break;
936 default: break;
939 for ( itEntryList = aEntryList.begin();
940 itEntryList < aEntryList.end() && (*itEntryList)->mnPos < pNew->mnPos;
941 ++itEntryList )
943 if ( itEntryList < aEntryList.end() )
944 aEntryList.insert( itEntryList, pNew );
945 else
946 aEntryList.push_back( pNew );
949 if(eVer == SvxDistributeVerticalDistance)
951 // calculate room in-between
952 sal_Int32 nHeight = GetAllMarkedBoundRect().GetHeight() + 1;
953 double fStepWidth = ((double)nHeight - (double)nFullLength) / (double)(aEntryList.size() - 1);
954 double fStepStart = (double)aEntryList[ 0 ]->mnPos;
955 fStepStart += fStepWidth + (double)((aEntryList[ 0 ]->mnLength + aEntryList[ 1 ]->mnLength) / 2);
957 // move entries 1..n-1
958 for( size_t i = 1, n = aEntryList.size()-1; i < n; ++i)
960 ImpDistributeEntry* pCurr = aEntryList[ i ];
961 ImpDistributeEntry* pNext = aEntryList[ i + 1 ];
962 sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos;
963 if( bUndo )
964 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj));
965 pCurr->mpObj->Move(Size(0, nDelta));
966 fStepStart += fStepWidth + (double)((pCurr->mnLength + pNext->mnLength) / 2);
969 else
971 // calculate distances
972 sal_Int32 nHeight = aEntryList[ aEntryList.size() - 1 ]->mnPos - aEntryList[ 0 ]->mnPos;
973 double fStepWidth = (double)nHeight / (double)(aEntryList.size() - 1);
974 double fStepStart = (double)aEntryList[ 0 ]->mnPos;
975 fStepStart += fStepWidth;
977 // move entries 1..n-1
978 for(size_t i = 1, n = aEntryList.size()-1; i < n; ++i)
980 ImpDistributeEntry* pCurr = aEntryList[ i ];
981 sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos;
982 if( bUndo )
983 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj));
984 pCurr->mpObj->Move(Size(0, nDelta));
985 fStepStart += fStepWidth;
989 // clear list
990 for ( size_t i = 0, n = aEntryList.size(); i < n; ++i )
991 delete aEntryList[ i ];
992 aEntryList.clear();
995 // UNDO-Comment and end of UNDO
996 SetUndoComment(ImpGetResStr(STR_DistributeMarkedObjects));
998 if( bUndo )
999 EndUndo();
1002 delete(pDlg);
1007 void SdrEditView::MergeMarkedObjects(SdrMergeMode eMode)
1009 // #i73441# check content
1010 if(AreObjectsMarked())
1012 SdrMarkList aRemove;
1013 SortMarkedObjects();
1015 const bool bUndo = IsUndoEnabled();
1017 if( bUndo )
1018 BegUndo();
1020 sal_uInt32 nInsPos=0xFFFFFFFF;
1021 const SdrObject* pAttrObj = NULL;
1022 basegfx::B2DPolyPolygon aMergePolyPolygonA;
1023 basegfx::B2DPolyPolygon aMergePolyPolygonB;
1025 SdrObjList* pInsOL = NULL;
1026 SdrPageView* pInsPV = NULL;
1027 sal_Bool bFirstObjectComplete(sal_False);
1029 // make sure selected objects are contour objects
1030 // since now basegfx::tools::adaptiveSubdivide() is used, it is no longer
1031 // necessary to use ConvertMarkedToPolyObj which will subdivide curves using the old
1032 // mechanisms. In a next step the polygon clipper will even be able to clip curves...
1033 // ConvertMarkedToPolyObj(sal_True);
1034 ConvertMarkedToPathObj(sal_True);
1035 OSL_ENSURE(AreObjectsMarked(), "no more objects selected after preparations (!)");
1037 for(sal_uInt32 a=0;a<GetMarkedObjectCount();a++)
1039 SdrMark* pM = GetSdrMarkByIndex(a);
1040 SdrObject* pObj = pM->GetMarkedSdrObj();
1042 if(ImpCanConvertForCombine(pObj))
1044 if(!pAttrObj)
1045 pAttrObj = pObj;
1047 nInsPos = pObj->GetOrdNum() + 1;
1048 pInsPV = pM->GetPageView();
1049 pInsOL = pObj->GetObjList();
1051 // #i76891# use single iteration from SJ here which works on SdrObjects and takes
1052 // groups into account by itself
1053 SdrObjListIter aIter(*pObj, IM_DEEPWITHGROUPS);
1055 while(aIter.IsMore())
1057 SdrObject* pCandidate = aIter.Next();
1058 SdrPathObj* pPathObj = PTR_CAST(SdrPathObj, pCandidate);
1059 if(pPathObj)
1061 basegfx::B2DPolyPolygon aTmpPoly(pPathObj->GetPathPoly());
1063 // #i76891# unfortunately ConvertMarkedToPathObj has converted all
1064 // involved polygon data to curve segments, even if not necessary.
1065 // It is better to try to reduce to more simple polygons.
1066 aTmpPoly = basegfx::tools::simplifyCurveSegments(aTmpPoly);
1068 // for each part polygon as preparation, remove self-intersections
1069 // correct orientations and get rid of possible neutral polygons.
1070 aTmpPoly = basegfx::tools::prepareForPolygonOperation(aTmpPoly);
1072 if(!bFirstObjectComplete)
1074 // #i111987# Also need to collect ORed source shape when more than
1075 // a single polygon is involved
1076 if(aMergePolyPolygonA.count())
1078 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA, aTmpPoly);
1080 else
1082 aMergePolyPolygonA = aTmpPoly;
1085 else
1087 if(aMergePolyPolygonB.count())
1089 // to topologically correctly collect the 2nd polygon
1090 // group it is necessary to OR the parts (each is seen as
1091 // XOR-FillRule polygon and they are drawn over each-other)
1092 aMergePolyPolygonB = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonB, aTmpPoly);
1094 else
1096 aMergePolyPolygonB = aTmpPoly;
1102 // was there something added to the first polygon?
1103 if(!bFirstObjectComplete && aMergePolyPolygonA.count())
1105 bFirstObjectComplete = sal_True;
1108 // move object to temporary delete list
1109 aRemove.InsertEntry(SdrMark(pObj, pM->GetPageView()));
1113 switch(eMode)
1115 case SDR_MERGE_MERGE:
1117 // merge all contained parts (OR)
1118 static bool bTestXOR(false);
1119 if(bTestXOR)
1121 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationXor(aMergePolyPolygonA, aMergePolyPolygonB);
1123 else
1125 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA, aMergePolyPolygonB);
1127 break;
1129 case SDR_MERGE_SUBSTRACT:
1131 // Substract B from A
1132 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationDiff(aMergePolyPolygonA, aMergePolyPolygonB);
1133 break;
1135 case SDR_MERGE_INTERSECT:
1137 // AND B and A
1138 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationAnd(aMergePolyPolygonA, aMergePolyPolygonB);
1139 break;
1143 // #i73441# check insert list before taking actions
1144 if(pInsOL)
1146 SdrPathObj* pPath = new SdrPathObj(OBJ_PATHFILL, aMergePolyPolygonA);
1147 ImpCopyAttributes(pAttrObj, pPath);
1148 SdrInsertReason aReason(SDRREASON_VIEWCALL, pAttrObj);
1149 pInsOL->InsertObject(pPath, nInsPos, &aReason);
1150 if( bUndo )
1151 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath));
1152 MarkObj(pPath, pInsPV, sal_False, sal_True);
1155 aRemove.ForceSort();
1156 switch(eMode)
1158 case SDR_MERGE_MERGE:
1160 SetUndoComment(
1161 ImpGetResStr(STR_EditMergeMergePoly),
1162 aRemove.GetMarkDescription());
1163 break;
1165 case SDR_MERGE_SUBSTRACT:
1167 SetUndoComment(
1168 ImpGetResStr(STR_EditMergeSubstractPoly),
1169 aRemove.GetMarkDescription());
1170 break;
1172 case SDR_MERGE_INTERSECT:
1174 SetUndoComment(
1175 ImpGetResStr(STR_EditMergeIntersectPoly),
1176 aRemove.GetMarkDescription());
1177 break;
1180 DeleteMarkedList(aRemove);
1182 if( bUndo )
1183 EndUndo();
1187 void SdrEditView::CombineMarkedObjects(sal_Bool bNoPolyPoly)
1189 // #105899# Start of Combine-Undo put to front, else ConvertMarkedToPolyObj would
1190 // create a 2nd Undo-action and Undo-Comment.
1192 bool bUndo = IsUndoEnabled();
1194 // Undo-String will be set later
1195 if( bUndo )
1196 BegUndo(String(), String(), bNoPolyPoly ? SDRREPFUNC_OBJ_COMBINE_ONEPOLY : SDRREPFUNC_OBJ_COMBINE_POLYPOLY);
1198 // #105899# First, guarantee that all objects are converted to polyobjects,
1199 // especially for SdrGrafObj with bitmap filling this is necessary to not
1200 // loose the bitmap filling.
1202 // #i12392#
1203 // ConvertMarkedToPolyObj was too strong here, it will loose quality and
1204 // information when curve objects are combined. This can be replaced by
1205 // using ConvertMarkedToPathObj without changing the previous fix.
1207 // #i21250#
1208 // Instead of simply passing sal_True as LineToArea, use bNoPolyPoly as info
1209 // if this command is a 'Combine' or a 'Connect' command. On Connect it's sal_True.
1210 // To not concert line segments with a set line width to polygons in that case,
1211 // use this info. Do not convert LineToArea on Connect commands.
1212 // ConvertMarkedToPathObj(!bNoPolyPoly);
1214 // This is used for Combine and Connect. In no case it is necessary to force
1215 // the content to curve, but it is also not good to force to polygons. Thus,
1216 // curve is the less information loosing one. Remember: This place is not
1217 // used for merge.
1218 // LineToArea is never necessary, both commands are able to take over the
1219 // set line style and to display it correctly. Thus, i will use a
1220 // ConvertMarkedToPathObj with a sal_False in any case. Only drawback is that
1221 // simple polygons will be changed to curves, but with no information loss.
1222 ConvertMarkedToPathObj(sal_False /* bLineToArea */);
1224 // continue as before
1225 basegfx::B2DPolyPolygon aPolyPolygon;
1226 SdrObjList* pAktOL = 0L;
1227 SdrMarkList aRemoveMerker;
1229 SortMarkedObjects();
1230 sal_uInt32 nInsPos(0xFFFFFFFF);
1231 SdrObjList* pInsOL = 0L;
1232 SdrPageView* pInsPV = 0L;
1233 const sal_uInt32 nAnz(GetMarkedObjectCount());
1234 const SdrObject* pAttrObj = 0L;
1236 for(sal_uInt32 a(nAnz); a > 0L; )
1238 a--;
1239 SdrMark* pM = GetSdrMarkByIndex(a);
1240 SdrObject* pObj = pM->GetMarkedSdrObj();
1241 SdrObjList* pThisOL = pObj->GetObjList();
1243 if(pAktOL != pThisOL)
1245 pAktOL = pThisOL;
1248 if(ImpCanConvertForCombine(pObj))
1250 // remember objects to be able to copy attributes
1251 pAttrObj = pObj;
1253 // unfortunately ConvertMarkedToPathObj has converted all
1254 // involved polygon data to curve segments, even if not necessary.
1255 // It is better to try to reduce to more simple polygons.
1256 basegfx::B2DPolyPolygon aTmpPoly(basegfx::tools::simplifyCurveSegments(ImpGetPolyPolygon(pObj, sal_True)));
1257 aPolyPolygon.insert(0L, aTmpPoly);
1259 if(!pInsOL)
1261 nInsPos = pObj->GetOrdNum() + 1L;
1262 pInsPV = pM->GetPageView();
1263 pInsOL = pObj->GetObjList();
1266 aRemoveMerker.InsertEntry(SdrMark(pObj, pM->GetPageView()));
1270 if(bNoPolyPoly)
1272 basegfx::B2DPolygon aCombinedPolygon(ImpCombineToSinglePolygon(aPolyPolygon));
1273 aPolyPolygon.clear();
1274 aPolyPolygon.append(aCombinedPolygon);
1277 const sal_uInt32 nPolyCount(aPolyPolygon.count());
1279 if(nPolyCount)
1281 SdrObjKind eKind = OBJ_PATHFILL;
1283 if(nPolyCount > 1L)
1285 aPolyPolygon.setClosed(true);
1287 else
1289 // check for Polyline
1290 const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(0L));
1291 const sal_uInt32 nPointCount(aPolygon.count());
1293 if(nPointCount <= 2L)
1295 eKind = OBJ_PATHLINE;
1297 else
1299 if(!aPolygon.isClosed())
1301 const basegfx::B2DPoint aPointA(aPolygon.getB2DPoint(0L));
1302 const basegfx::B2DPoint aPointB(aPolygon.getB2DPoint(nPointCount - 1L));
1303 const double fDistance(basegfx::B2DVector(aPointB - aPointA).getLength());
1304 const double fJoinTolerance(10.0);
1306 if(fDistance < fJoinTolerance)
1308 aPolyPolygon.setClosed(true);
1310 else
1312 eKind = OBJ_PATHLINE;
1318 SdrPathObj* pPath = new SdrPathObj(eKind,aPolyPolygon);
1320 // attributes of the lowest object
1321 ImpCopyAttributes(pAttrObj, pPath);
1323 // If LineStyle of pAttrObj is XLINE_NONE force to XLINE_SOLID to make visible.
1324 const XLineStyle eLineStyle = ((const XLineStyleItem&)pAttrObj->GetMergedItem(XATTR_LINESTYLE)).GetValue();
1325 const XFillStyle eFillStyle = ((const XFillStyleItem&)pAttrObj->GetMergedItem(XATTR_FILLSTYLE)).GetValue();
1327 // Take fill style/closed state of pAttrObj in account when deciding to change the line style
1328 sal_Bool bIsClosedPathObj(pAttrObj->ISA(SdrPathObj) && ((SdrPathObj*)pAttrObj)->IsClosed());
1330 if(XLINE_NONE == eLineStyle && (XFILL_NONE == eFillStyle || !bIsClosedPathObj))
1332 pPath->SetMergedItem(XLineStyleItem(XLINE_SOLID));
1335 SdrInsertReason aReason(SDRREASON_VIEWCALL,pAttrObj);
1336 pInsOL->InsertObject(pPath,nInsPos,&aReason);
1337 if( bUndo )
1338 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath));
1340 // Here was a severe error: Without UnmarkAllObj, the new object was marked
1341 // additionally to the two ones which are deleted below. As long as those are
1342 // in the UNDO there is no problem, but as soon as they get deleted, the
1343 // MarkList will contain deleted objects -> GPF.
1344 UnmarkAllObj(pInsPV);
1345 MarkObj(pPath, pInsPV, sal_False, sal_True);
1348 // build an UndoComment from the objects actually used
1349 aRemoveMerker.ForceSort(); // important for remove (see below)
1350 if( bUndo )
1351 SetUndoComment(ImpGetResStr(bNoPolyPoly?STR_EditCombine_OnePoly:STR_EditCombine_PolyPoly),aRemoveMerker.GetMarkDescription());
1353 // remove objects actually used from the list
1354 DeleteMarkedList(aRemoveMerker);
1355 if( bUndo )
1356 EndUndo();
1359 ////////////////////////////////////////////////////////////////////////////////////////////////////
1360 // Dismantle
1361 ////////////////////////////////////////////////////////////////////////////////////////////////////
1363 sal_Bool SdrEditView::ImpCanDismantle(const basegfx::B2DPolyPolygon& rPpolyPolygon, sal_Bool bMakeLines) const
1365 sal_Bool bCan(sal_False);
1366 const sal_uInt32 nPolygonCount(rPpolyPolygon.count());
1368 if(nPolygonCount >= 2L)
1370 // #i69172# dismantle makes sense with 2 or more polygons in a polyPolygon
1371 bCan = sal_True;
1373 else if(bMakeLines && 1L == nPolygonCount)
1375 // #i69172# ..or with at least 2 edges (curves or lines)
1376 const basegfx::B2DPolygon aPolygon(rPpolyPolygon.getB2DPolygon(0L));
1377 const sal_uInt32 nPointCount(aPolygon.count());
1379 if(nPointCount > 2L)
1381 bCan = sal_True;
1385 return bCan;
1388 sal_Bool SdrEditView::ImpCanDismantle(const SdrObject* pObj, sal_Bool bMakeLines) const
1390 sal_Bool bOtherObjs(sal_False); // sal_True=objects other than PathObj's existent
1391 sal_Bool bMin1PolyPoly(sal_False); // sal_True=at least 1 PolyPolygon with more than one Polygon existent
1392 SdrObjList* pOL = pObj->GetSubList();
1394 if(pOL)
1396 // group object -- check all members if they're PathObjs
1397 SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS);
1399 while(aIter.IsMore() && !bOtherObjs)
1401 const SdrObject* pObj1 = aIter.Next();
1402 const SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj1);
1404 if(pPath)
1406 if(ImpCanDismantle(pPath->GetPathPoly(), bMakeLines))
1408 bMin1PolyPoly = sal_True;
1411 SdrObjTransformInfoRec aInfo;
1412 pObj1->TakeObjInfo(aInfo);
1414 if(!aInfo.bCanConvToPath)
1416 // happens e. g. in the case of FontWork
1417 bOtherObjs = sal_True;
1420 else
1422 bOtherObjs = sal_True;
1426 else
1428 const SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj);
1429 const SdrObjCustomShape* pCustomShape = PTR_CAST(SdrObjCustomShape, pObj);
1431 // #i37011#
1432 if(pPath)
1434 if(ImpCanDismantle(pPath->GetPathPoly(),bMakeLines))
1436 bMin1PolyPoly = sal_True;
1439 SdrObjTransformInfoRec aInfo;
1440 pObj->TakeObjInfo(aInfo);
1442 // new condition IsLine() to be able to break simple Lines
1443 if(!(aInfo.bCanConvToPath || aInfo.bCanConvToPoly) && !pPath->IsLine())
1445 // happens e. g. in the case of FontWork
1446 bOtherObjs = sal_True;
1449 else if(pCustomShape)
1451 if(bMakeLines)
1453 // allow break command
1454 bMin1PolyPoly = sal_True;
1457 else
1459 bOtherObjs = sal_True;
1462 return bMin1PolyPoly && !bOtherObjs;
1465 void SdrEditView::ImpDismantleOneObject(const SdrObject* pObj, SdrObjList& rOL, sal_uIntPtr& rPos, SdrPageView* pPV, sal_Bool bMakeLines)
1467 const SdrPathObj* pSrcPath = PTR_CAST(SdrPathObj, pObj);
1468 const SdrObjCustomShape* pCustomShape = PTR_CAST(SdrObjCustomShape, pObj);
1470 const bool bUndo = IsUndoEnabled();
1472 if(pSrcPath)
1474 // #i74631# redesigned due to XpolyPolygon removal and explicit constructors
1475 SdrObject* pLast = 0; // to be able to apply OutlinerParaObject
1476 const basegfx::B2DPolyPolygon& rPolyPolygon(pSrcPath->GetPathPoly());
1477 const sal_uInt32 nPolyCount(rPolyPolygon.count());
1479 for(sal_uInt32 a(0); a < nPolyCount; a++)
1481 const basegfx::B2DPolygon& rCandidate(rPolyPolygon.getB2DPolygon(a));
1482 const sal_uInt32 nPointCount(rCandidate.count());
1484 if(!bMakeLines || nPointCount < 2)
1486 SdrPathObj* pPath = new SdrPathObj((SdrObjKind)pSrcPath->GetObjIdentifier(), basegfx::B2DPolyPolygon(rCandidate));
1487 ImpCopyAttributes(pSrcPath, pPath);
1488 pLast = pPath;
1489 SdrInsertReason aReason(SDRREASON_VIEWCALL, pSrcPath);
1490 rOL.InsertObject(pPath, rPos, &aReason);
1491 if( bUndo )
1492 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, sal_True));
1493 MarkObj(pPath, pPV, sal_False, sal_True);
1494 rPos++;
1496 else
1498 const sal_uInt32 nLoopCount(rCandidate.isClosed() ? nPointCount : nPointCount - 1);
1500 for(sal_uInt32 b(0); b < nLoopCount; b++)
1502 SdrObjKind eKind(OBJ_PLIN);
1503 basegfx::B2DPolygon aNewPolygon;
1504 const sal_uInt32 nNextIndex((b + 1) % nPointCount);
1506 aNewPolygon.append(rCandidate.getB2DPoint(b));
1508 if(rCandidate.areControlPointsUsed())
1510 aNewPolygon.appendBezierSegment(
1511 rCandidate.getNextControlPoint(b),
1512 rCandidate.getPrevControlPoint(nNextIndex),
1513 rCandidate.getB2DPoint(nNextIndex));
1514 eKind = OBJ_PATHLINE;
1516 else
1518 aNewPolygon.append(rCandidate.getB2DPoint(nNextIndex));
1521 SdrPathObj* pPath = new SdrPathObj(eKind, basegfx::B2DPolyPolygon(aNewPolygon));
1522 ImpCopyAttributes(pSrcPath, pPath);
1523 pLast = pPath;
1524 SdrInsertReason aReason(SDRREASON_VIEWCALL, pSrcPath);
1525 rOL.InsertObject(pPath, rPos, &aReason);
1526 if( bUndo )
1527 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, sal_True));
1528 MarkObj(pPath, pPV, sal_False, sal_True);
1529 rPos++;
1534 if(pLast && pSrcPath->GetOutlinerParaObject())
1536 pLast->SetOutlinerParaObject(new OutlinerParaObject(*pSrcPath->GetOutlinerParaObject()));
1539 else if(pCustomShape)
1541 if(bMakeLines)
1543 // break up custom shape
1544 const SdrObject* pReplacement = pCustomShape->GetSdrObjectFromCustomShape();
1546 if(pReplacement)
1548 SdrObject* pCandidate = pReplacement->Clone();
1549 DBG_ASSERT(pCandidate, "SdrEditView::ImpDismantleOneObject: Could not clone SdrObject (!)");
1550 pCandidate->SetModel(pCustomShape->GetModel());
1552 if(((SdrShadowItem&)pCustomShape->GetMergedItem(SDRATTR_SHADOW)).GetValue())
1554 if(pReplacement->ISA(SdrObjGroup))
1556 pCandidate->SetMergedItem(SdrShadowItem(sal_True));
1560 SdrInsertReason aReason(SDRREASON_VIEWCALL, pCustomShape);
1561 rOL.InsertObject(pCandidate, rPos, &aReason);
1562 if( bUndo )
1563 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pCandidate, true));
1564 MarkObj(pCandidate, pPV, sal_False, sal_True);
1566 if(pCustomShape->HasText() && !pCustomShape->IsTextPath())
1568 // #i37011# also create a text object and add at rPos + 1
1569 SdrTextObj* pTextObj = (SdrTextObj*)SdrObjFactory::MakeNewObject(
1570 pCustomShape->GetObjInventor(), OBJ_TEXT, 0L, pCustomShape->GetModel());
1572 // Copy text content
1573 OutlinerParaObject* pParaObj = pCustomShape->GetOutlinerParaObject();
1574 if(pParaObj)
1576 pTextObj->NbcSetOutlinerParaObject(new OutlinerParaObject(*pParaObj));
1579 // copy all attributes
1580 SfxItemSet aTargetItemSet(pCustomShape->GetMergedItemSet());
1582 // clear fill and line style
1583 aTargetItemSet.Put(XLineStyleItem(XLINE_NONE));
1584 aTargetItemSet.Put(XFillStyleItem(XFILL_NONE));
1586 // get the text bounds and set at text object
1587 Rectangle aTextBounds = pCustomShape->GetSnapRect();
1588 if(pCustomShape->GetTextBounds(aTextBounds))
1590 pTextObj->SetSnapRect(aTextBounds);
1593 // if rotated, copy GeoStat, too.
1594 const GeoStat& rSourceGeo = pCustomShape->GetGeoStat();
1595 if(rSourceGeo.nDrehWink)
1597 pTextObj->NbcRotate(
1598 pCustomShape->GetSnapRect().Center(), rSourceGeo.nDrehWink,
1599 rSourceGeo.nSin, rSourceGeo.nCos);
1602 // set modified ItemSet at text object
1603 pTextObj->SetMergedItemSet(aTargetItemSet);
1605 // insert object
1606 rOL.InsertObject(pTextObj, rPos + 1, &aReason);
1607 if( bUndo )
1608 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pTextObj, true));
1609 MarkObj(pTextObj, pPV, sal_False, sal_True);
1616 void SdrEditView::DismantleMarkedObjects(sal_Bool bMakeLines)
1618 // temporary MarkList
1619 SdrMarkList aRemoveMerker;
1621 SortMarkedObjects();
1623 const bool bUndo = IsUndoEnabled();
1625 if( bUndo )
1627 // comment is constructed later
1628 BegUndo(String(), String(),
1629 bMakeLines ? SDRREPFUNC_OBJ_DISMANTLE_LINES : SDRREPFUNC_OBJ_DISMANTLE_POLYS);
1632 sal_uIntPtr nm;
1633 sal_uIntPtr nAnz=GetMarkedObjectCount();
1634 SdrObjList* pOL0=NULL;
1635 for (nm=nAnz; nm>0;) {
1636 nm--;
1637 SdrMark* pM=GetSdrMarkByIndex(nm);
1638 SdrObject* pObj=pM->GetMarkedSdrObj();
1639 SdrPageView* pPV=pM->GetPageView();
1640 SdrObjList* pOL=pObj->GetObjList();
1641 if (pOL!=pOL0) { pOL0=pOL; pObj->GetOrdNum(); } // make sure OrdNums are correct!
1642 if (ImpCanDismantle(pObj,bMakeLines)) {
1643 aRemoveMerker.InsertEntry(SdrMark(pObj,pM->GetPageView()));
1644 sal_uIntPtr nPos0=pObj->GetOrdNumDirect();
1645 sal_uIntPtr nPos=nPos0+1;
1646 SdrObjList* pSubList=pObj->GetSubList();
1647 if (pSubList!=NULL && !pObj->Is3DObj()) {
1648 SdrObjListIter aIter(*pSubList,IM_DEEPNOGROUPS);
1649 while (aIter.IsMore()) {
1650 const SdrObject* pObj1=aIter.Next();
1651 ImpDismantleOneObject(pObj1,*pOL,nPos,pPV,bMakeLines);
1653 } else {
1654 ImpDismantleOneObject(pObj,*pOL,nPos,pPV,bMakeLines);
1656 if( bUndo )
1657 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj,sal_True));
1658 pOL->RemoveObject(nPos0);
1660 if( !bUndo )
1661 SdrObject::Free(pObj);
1665 if( bUndo )
1667 // construct UndoComment from objects actually used
1668 SetUndoComment(ImpGetResStr(bMakeLines?STR_EditDismantle_Lines:STR_EditDismantle_Polys),aRemoveMerker.GetMarkDescription());
1669 // remove objects actually used from the list
1670 EndUndo();
1674 ////////////////////////////////////////////////////////////////////////////////////////////////////
1675 // Group
1676 ////////////////////////////////////////////////////////////////////////////////////////////////////
1678 void SdrEditView::GroupMarked(const SdrObject* pUserGrp)
1680 if (AreObjectsMarked())
1682 SortMarkedObjects();
1684 const bool bUndo = IsUndoEnabled();
1685 if( bUndo )
1687 BegUndo(ImpGetResStr(STR_EditGroup),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_GROUP);
1689 const sal_uIntPtr nAnz = GetMarkedObjectCount();
1690 for(sal_uIntPtr nm = nAnz; nm>0; )
1692 // add UndoActions for all affected objects
1693 nm--;
1694 SdrMark* pM=GetSdrMarkByIndex(nm);
1695 SdrObject* pObj = pM->GetMarkedSdrObj();
1696 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pObj ) );
1697 AddUndoActions( vConnectorUndoActions );
1698 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject( *pObj ));
1702 SdrMarkList aNewMark;
1703 SdrPageView* pPV = GetSdrPageView();
1705 if(pPV)
1707 SdrObjList* pAktLst=pPV->GetObjList();
1708 SdrObjList* pSrcLst=pAktLst;
1709 SdrObjList* pSrcLst0=pSrcLst;
1710 SdrPage* pPage=pPV->GetPage();
1711 // make sure OrdNums are correct
1712 if (pSrcLst->IsObjOrdNumsDirty())
1713 pSrcLst->RecalcObjOrdNums();
1714 SdrObject* pGrp=NULL;
1715 SdrObject* pRefObj=NULL; // reference for InsertReason (-> anchors in Writer)
1716 SdrObject* pRefObj1=NULL; // reference for InsertReason (-> anchors in Writer)
1717 SdrObjList* pDstLst=NULL;
1718 // if all selected objects come from foreign object lists.
1719 // the group object is the last one in the list.
1720 sal_uIntPtr nInsPos=pSrcLst->GetObjCount();
1721 sal_Bool bNeedInsPos=sal_True;
1722 for (sal_uIntPtr nm=GetMarkedObjectCount(); nm>0;)
1724 nm--;
1725 SdrMark* pM=GetSdrMarkByIndex(nm);
1726 if (pM->GetPageView()==pPV)
1728 if (pGrp==NULL)
1730 if (pUserGrp!=NULL)
1731 pGrp=pUserGrp->Clone();
1732 if (pGrp==NULL)
1733 pGrp=new SdrObjGroup;
1734 pDstLst=pGrp->GetSubList();
1735 DBG_ASSERT(pDstLst!=NULL,"Alleged group object doesn't return object list.");
1737 SdrObject* pObj=pM->GetMarkedSdrObj();
1738 pSrcLst=pObj->GetObjList();
1739 if (pSrcLst!=pSrcLst0)
1741 if (pSrcLst->IsObjOrdNumsDirty())
1742 pSrcLst->RecalcObjOrdNums();
1744 sal_Bool bForeignList=pSrcLst!=pAktLst;
1745 sal_Bool bGrouped=pSrcLst!=pPage;
1746 if (!bForeignList && bNeedInsPos)
1748 nInsPos=pObj->GetOrdNum(); // this way, all ObjOrdNum of the page are set
1749 nInsPos++;
1750 bNeedInsPos=sal_False;
1752 pSrcLst->RemoveObject(pObj->GetOrdNumDirect());
1753 if (!bForeignList)
1754 nInsPos--; // correct InsertPos
1755 SdrInsertReason aReason(SDRREASON_VIEWCALL);
1756 pDstLst->InsertObject(pObj,0,&aReason);
1757 GetMarkedObjectListWriteAccess().DeleteMark(nm);
1758 if (pRefObj1==NULL)
1759 pRefObj1=pObj; // the topmost visible object
1760 if (!bGrouped)
1762 if (pRefObj==NULL)
1763 pRefObj=pObj; // the topmost visible non-group object
1765 pSrcLst0=pSrcLst;
1768 if (pRefObj==NULL)
1769 pRefObj=pRefObj1;
1770 if (pGrp!=NULL)
1772 aNewMark.InsertEntry(SdrMark(pGrp,pPV));
1773 sal_uIntPtr nAnz=pDstLst->GetObjCount();
1774 SdrInsertReason aReason(SDRREASON_VIEWCALL,pRefObj);
1775 pAktLst->InsertObject(pGrp,nInsPos,&aReason);
1776 if( bUndo )
1778 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pGrp,true)); // no recalculation!
1779 for (sal_uIntPtr no=0; no<nAnz; no++)
1781 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pDstLst->GetObj(no)));
1786 GetMarkedObjectListWriteAccess().Merge(aNewMark);
1787 MarkListHasChanged();
1789 if( bUndo )
1790 EndUndo();
1794 ////////////////////////////////////////////////////////////////////////////////////////////////////
1795 // Ungroup
1796 ////////////////////////////////////////////////////////////////////////////////////////////////////
1798 void SdrEditView::UnGroupMarked()
1800 SdrMarkList aNewMark;
1802 const bool bUndo = IsUndoEnabled();
1803 if( bUndo )
1804 BegUndo(String(), String(), SDRREPFUNC_OBJ_UNGROUP);
1806 sal_uIntPtr nCount=0;
1807 XubString aName1;
1808 XubString aName;
1809 sal_Bool bNameOk=sal_False;
1810 for (sal_uIntPtr nm=GetMarkedObjectCount(); nm>0;) {
1811 nm--;
1812 SdrMark* pM=GetSdrMarkByIndex(nm);
1813 SdrObject* pGrp=pM->GetMarkedSdrObj();
1814 SdrObjList* pSrcLst=pGrp->GetSubList();
1815 if (pSrcLst!=NULL) {
1816 nCount++;
1817 if (nCount==1) {
1818 pGrp->TakeObjNameSingul(aName); // retrieve name of group
1819 pGrp->TakeObjNamePlural(aName1); // retrieve name of group
1820 bNameOk=sal_True;
1821 } else {
1822 if (nCount==2) aName=aName1; // set plural name
1823 if (bNameOk) {
1824 XubString aStr;
1825 pGrp->TakeObjNamePlural(aStr); // retrieve name of group
1827 if(!aStr.Equals(aName))
1828 bNameOk = sal_False;
1831 sal_uIntPtr nDstCnt=pGrp->GetOrdNum();
1832 SdrObjList* pDstLst=pM->GetPageView()->GetObjList();
1834 // FIRST move contained objects to parent of group, so that
1835 // the contained objects are NOT migrated to the UNDO-ItemPool
1836 // when AddUndo(new SdrUndoDelObj(*pGrp)) is called.
1837 sal_uIntPtr nAnz=pSrcLst->GetObjCount();
1838 sal_uIntPtr no;
1840 if( bUndo )
1842 for (no=nAnz; no>0;)
1844 no--;
1845 SdrObject* pObj=pSrcLst->GetObj(no);
1846 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject(*pObj));
1849 for (no=0; no<nAnz; no++)
1851 SdrObject* pObj=pSrcLst->RemoveObject(0);
1852 SdrInsertReason aReason(SDRREASON_VIEWCALL,pGrp);
1853 pDstLst->InsertObject(pObj,nDstCnt,&aReason);
1854 if( bUndo )
1855 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pObj,true));
1856 nDstCnt++;
1857 // No SortCheck when inserting into MarkList, because that would
1858 // provoke a RecalcOrdNums() each time because of pObj->GetOrdNum():
1859 aNewMark.InsertEntry(SdrMark(pObj,pM->GetPageView()),sal_False);
1862 if( bUndo )
1864 // Now it is safe to add the delete-UNDO which triggers the
1865 // MigrateItemPool now only for itself, not for the sub-objects.
1866 // nDstCnt is right, because previous inserts move group
1867 // object deeper and increase nDstCnt.
1868 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pGrp));
1870 pDstLst->RemoveObject(nDstCnt);
1872 if( !bUndo )
1873 SdrObject::Free(pGrp);
1875 GetMarkedObjectListWriteAccess().DeleteMark(nm);
1878 if (nCount!=0)
1880 if (!bNameOk)
1881 aName=ImpGetResStr(STR_ObjNamePluralGRUP); // Use the term "Group Objects," if different objects are grouped.
1882 SetUndoComment(ImpGetResStr(STR_EditUngroup),aName);
1885 if( bUndo )
1886 EndUndo();
1888 if (nCount!=0)
1890 GetMarkedObjectListWriteAccess().Merge(aNewMark,sal_True); // Because of the sorting above, aNewMark is reversed
1891 MarkListHasChanged();
1895 ////////////////////////////////////////////////////////////////////////////////////////////////////
1896 // ConvertToPoly
1897 ////////////////////////////////////////////////////////////////////////////////////////////////////
1899 SdrObject* SdrEditView::ImpConvertOneObj(SdrObject* pObj, sal_Bool bPath, sal_Bool bLineToArea)
1901 SdrObject* pNewObj = pObj->ConvertToPolyObj(bPath, bLineToArea);
1902 if (pNewObj!=NULL)
1904 SdrObjList* pOL=pObj->GetObjList();
1905 DBG_ASSERT(pOL!=NULL,"ConvertTo: Object doesn't return object list");
1906 if (pOL!=NULL)
1908 const bool bUndo = IsUndoEnabled();
1909 if( bUndo )
1910 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoReplaceObject(*pObj,*pNewObj));
1912 pOL->ReplaceObject(pNewObj,pObj->GetOrdNum());
1914 if( !bUndo )
1915 SdrObject::Free(pObj);
1918 return pNewObj;
1921 void SdrEditView::ImpConvertTo(sal_Bool bPath, sal_Bool bLineToArea)
1923 sal_Bool bMrkChg=sal_False;
1924 if (AreObjectsMarked()) {
1925 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
1926 sal_uInt16 nDscrID=0;
1927 if(bLineToArea)
1929 if(nMarkAnz == 1)
1930 nDscrID = STR_EditConvToContour;
1931 else
1932 nDscrID = STR_EditConvToContours;
1934 BegUndo(ImpGetResStr(nDscrID), GetDescriptionOfMarkedObjects());
1936 else
1938 if (bPath) {
1939 if (nMarkAnz==1) nDscrID=STR_EditConvToCurve;
1940 else nDscrID=STR_EditConvToCurves;
1941 BegUndo(ImpGetResStr(nDscrID),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_CONVERTTOPATH);
1942 } else {
1943 if (nMarkAnz==1) nDscrID=STR_EditConvToPoly;
1944 else nDscrID=STR_EditConvToPolys;
1945 BegUndo(ImpGetResStr(nDscrID),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_CONVERTTOPOLY);
1948 for (sal_uIntPtr nm=nMarkAnz; nm>0;) {
1949 nm--;
1950 SdrMark* pM=GetSdrMarkByIndex(nm);
1951 SdrObject* pObj=pM->GetMarkedSdrObj();
1952 SdrPageView* pPV=pM->GetPageView();
1953 if (pObj->IsGroupObject() && !pObj->Is3DObj()) {
1954 SdrObject* pGrp=pObj;
1955 SdrObjListIter aIter(*pGrp,IM_DEEPNOGROUPS);
1956 while (aIter.IsMore()) {
1957 pObj=aIter.Next();
1958 ImpConvertOneObj(pObj,bPath,bLineToArea);
1960 } else {
1961 SdrObject* pNewObj=ImpConvertOneObj(pObj,bPath,bLineToArea);
1962 if (pNewObj!=NULL) {
1963 bMrkChg=sal_True;
1964 GetMarkedObjectListWriteAccess().ReplaceMark(SdrMark(pNewObj,pPV),nm);
1968 EndUndo();
1969 if (bMrkChg) AdjustMarkHdl();
1970 if (bMrkChg) MarkListHasChanged();
1974 void SdrEditView::ConvertMarkedToPathObj(sal_Bool bLineToArea)
1976 ImpConvertTo(sal_True, bLineToArea);
1979 void SdrEditView::ConvertMarkedToPolyObj(sal_Bool bLineToArea)
1981 ImpConvertTo(sal_False, bLineToArea);
1984 ////////////////////////////////////////////////////////////////////////////////////////////////////
1985 // Metafile Import
1986 ////////////////////////////////////////////////////////////////////////////////////////////////////
1988 void SdrEditView::DoImportMarkedMtf(SvdProgressInfo *pProgrInfo)
1990 const bool bUndo = IsUndoEnabled();
1992 if( bUndo )
1993 BegUndo(String(), String(), SDRREPFUNC_OBJ_IMPORTMTF);
1995 SortMarkedObjects();
1996 SdrMarkList aForTheDescription;
1997 SdrMarkList aNewMarked;
1998 sal_uIntPtr nAnz=GetMarkedObjectCount();
2000 for (sal_uIntPtr nm=nAnz; nm>0;)
2001 { // create Undo objects for all new objects
2002 // check for cancellation between the metafiles
2003 if( pProgrInfo != NULL )
2005 pProgrInfo->SetNextObject();
2006 if(!pProgrInfo->ReportActions(0))
2007 break;
2010 nm--;
2011 SdrMark* pM=GetSdrMarkByIndex(nm);
2012 SdrObject* pObj=pM->GetMarkedSdrObj();
2013 SdrPageView* pPV=pM->GetPageView();
2014 SdrObjList* pOL=pObj->GetObjList();
2015 sal_uIntPtr nInsPos=pObj->GetOrdNum()+1;
2016 SdrGrafObj* pGraf=PTR_CAST(SdrGrafObj,pObj);
2017 SdrOle2Obj* pOle2=PTR_CAST(SdrOle2Obj,pObj);
2018 sal_uIntPtr nInsAnz=0;
2019 if (pGraf!=NULL && pGraf->HasGDIMetaFile())
2021 ImpSdrGDIMetaFileImport aFilter(*pMod);
2022 aFilter.SetScaleRect(pGraf->GetSnapRect());
2023 aFilter.SetLayer(pObj->GetLayer());
2024 nInsAnz=aFilter.DoImport(pGraf->GetTransformedGraphic().GetGDIMetaFile(),*pOL,nInsPos,pProgrInfo);
2026 if ( pOle2!=NULL && pOle2->GetGraphic() )
2028 ImpSdrGDIMetaFileImport aFilter(*pMod);
2029 aFilter.SetScaleRect(pOle2->GetLogicRect());
2030 aFilter.SetLayer(pObj->GetLayer());
2031 nInsAnz=aFilter.DoImport(pOle2->GetGraphic()->GetGDIMetaFile(),*pOL,nInsPos,pProgrInfo);
2033 if (nInsAnz!=0)
2035 sal_uIntPtr nObj=nInsPos;
2036 for (sal_uIntPtr i=0; i<nInsAnz; i++)
2038 if( bUndo )
2039 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pOL->GetObj(nObj)));
2041 // update new MarkList
2042 SdrMark aNewMark(pOL->GetObj(nObj), pPV);
2043 aNewMarked.InsertEntry(aNewMark);
2045 nObj++;
2047 aForTheDescription.InsertEntry(*pM);
2049 if( bUndo )
2050 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj));
2052 // remove object from selection and delete
2053 GetMarkedObjectListWriteAccess().DeleteMark(TryToFindMarkedObject(pObj));
2054 pOL->RemoveObject(nInsPos-1);
2056 if( !bUndo )
2057 SdrObject::Free(pObj);
2061 if(aNewMarked.GetMarkCount())
2063 // create new selection
2064 for(sal_uIntPtr a(0); a < aNewMarked.GetMarkCount(); a++)
2066 GetMarkedObjectListWriteAccess().InsertEntry(*aNewMarked.GetMark(a));
2069 SortMarkedObjects();
2072 if( bUndo )
2074 SetUndoComment(ImpGetResStr(STR_EditImportMtf),aForTheDescription.GetMarkDescription());
2075 EndUndo();
2079 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */