xref: /trunk/main/svx/source/svdraw/svdedtv2.cxx (revision 86e1cf34)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include <svx/svdedtv.hxx>
28 #include <editeng/outliner.hxx>
29 #include <svx/svdundo.hxx>
30 #include <svx/svdogrp.hxx>   // fuer's Gruppieren
31 #include <svx/svdovirt.hxx>  // fuer VirtualObject-Bundling (Writer)
32 #include <svx/svdopath.hxx>  // fuer CombineObjects
33 #include <svx/svdpage.hxx>
34 #include <svx/svdpagv.hxx>
35 #include "svx/svditer.hxx"
36 #include <svx/svdograf.hxx>  // fuer Possibilities
37 #include <svx/svdoole2.hxx>  // und Mtf-Import
38 #include "svx/svdstr.hrc"   // Namen aus der Resource
39 #include "svx/svdglob.hxx"  // StringCache
40 #include "svdfmtf.hxx"
41 #include <svx/svdetc.hxx>
42 #include <sfx2/basedlgs.hxx>
43 #include <vcl/msgbox.hxx>
44 #include <editeng/outlobj.hxx>
45 #include <editeng/eeitem.hxx>
46 #include <basegfx/polygon/b2dpolypolygon.hxx>
47 #include <basegfx/polygon/b2dpolypolygontools.hxx>
48 
49 #include <svx/svxdlg.hxx> //CHINA001
50 #include <svx/dialogs.hrc> //CHINA001
51 
52 // #i37011#
53 #include <svx/svdoashp.hxx>
54 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
55 
56 ////////////////////////////////////////////////////////////////////////////////////////////////////
57 ////////////////////////////////////////////////////////////////////////////////////////////////////
58 ////////////////////////////////////////////////////////////////////////////////////////////////////
59 ////////////////////////////////////////////////////////////////////////////////////////////////////
60 //
61 //  @@@@@ @@@@@  @@ @@@@@@  @@ @@ @@ @@@@@ @@   @@
62 //  @@    @@  @@ @@   @@    @@ @@ @@ @@    @@   @@
63 //  @@    @@  @@ @@   @@    @@ @@ @@ @@    @@ @ @@
64 //  @@@@  @@  @@ @@   @@    @@@@@ @@ @@@@  @@@@@@@
65 //  @@    @@  @@ @@   @@     @@@  @@ @@    @@@@@@@
66 //  @@    @@  @@ @@   @@     @@@  @@ @@    @@@ @@@
67 //  @@@@@ @@@@@  @@   @@      @   @@ @@@@@ @@   @@
68 //
69 ////////////////////////////////////////////////////////////////////////////////////////////////////
70 ////////////////////////////////////////////////////////////////////////////////////////////////////
71 
ImpBundleVirtObjOfMarkList()72 void SdrEditView::ImpBundleVirtObjOfMarkList()
73 {
74   // ... fehlende Implementation
75 }
76 
GetMaxToTopObj(SdrObject *) const77 SdrObject* SdrEditView::GetMaxToTopObj(SdrObject* /*pObj*/) const
78 {
79   return NULL;
80 }
81 
GetMaxToBtmObj(SdrObject *) const82 SdrObject* SdrEditView::GetMaxToBtmObj(SdrObject* /*pObj*/) const
83 {
84   return NULL;
85 }
86 
ObjOrderChanged(SdrObject *,sal_uIntPtr,sal_uIntPtr)87 void SdrEditView::ObjOrderChanged(SdrObject* /*pObj*/, sal_uIntPtr /*nOldPos*/, sal_uIntPtr /*nNewPos*/)
88 {
89 }
90 
MovMarkedToTop()91 void SdrEditView::MovMarkedToTop()
92 {
93 	sal_uIntPtr nAnz=GetMarkedObjectCount();
94 	if (nAnz!=0)
95 	{
96 		const bool bUndo = IsUndoEnabled();
97 
98 		if( bUndo )
99 			BegUndo(ImpGetResStr(STR_EditMovToTop),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVTOTOP);
100 
101 		SortMarkedObjects();
102 		sal_uIntPtr nm;
103 		for (nm=0; nm<nAnz; nm++)
104 		{ // Ordnums muessen alle stimmen!
105 			GetMarkedObjectByIndex(nm)->GetOrdNum();
106 		}
107 		sal_Bool bChg=sal_False;
108 		SdrObjList* pOL0=NULL;
109 		sal_uIntPtr nNewPos=0;
110 		for (nm=nAnz; nm>0;)
111 		{
112 			nm--;
113 			SdrMark* pM=GetSdrMarkByIndex(nm);
114 			SdrObject* pObj=pM->GetMarkedSdrObj();
115 			SdrObjList* pOL=pObj->GetObjList();
116 			if (pOL!=pOL0)
117 			{
118 				nNewPos=sal_uIntPtr(pOL->GetObjCount()-1);
119 				pOL0=pOL;
120 			}
121 			sal_uIntPtr nNowPos=pObj->GetOrdNumDirect();
122 			const Rectangle& rBR=pObj->GetCurrentBoundRect();
123 			sal_uIntPtr nCmpPos=nNowPos+1;
124             SdrObject* pMaxObj=GetMaxToTopObj(pObj);
125             if (pMaxObj!=NULL)
126 			{
127                 sal_uIntPtr nMaxPos=pMaxObj->GetOrdNum();
128                 if (nMaxPos!=0)
129 					nMaxPos--;
130                 if (nNewPos>nMaxPos)
131 					nNewPos=nMaxPos; // diesen nicht ueberholen.
132                 if (nNewPos<nNowPos)
133 					nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben
134             }
135 			sal_Bool bEnd=sal_False;
136 			while (nCmpPos<nNewPos && !bEnd)
137 			{
138 				SdrObject* pCmpObj=pOL->GetObj(nCmpPos);
139 				if (pCmpObj==NULL)
140 				{
141 					DBG_ERROR("MovMarkedToTop(): Vergleichsobjekt nicht gefunden");
142 					bEnd=sal_True;
143                 }
144 				else if (pCmpObj==pMaxObj)
145 				{
146                     nNewPos=nCmpPos;
147                     nNewPos--;
148                     bEnd=sal_True;
149 				}
150 				else if (rBR.IsOver(pCmpObj->GetCurrentBoundRect()))
151 				{
152 					nNewPos=nCmpPos;
153 					bEnd=sal_True;
154 				}
155 				else
156 				{
157 					nCmpPos++;
158 				}
159 			}
160 			if (nNowPos!=nNewPos)
161 			{
162 				bChg=sal_True;
163 				pOL->SetObjectOrdNum(nNowPos,nNewPos);
164 				if( bUndo )
165 					AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
166 				ObjOrderChanged(pObj,nNowPos,nNewPos);
167 			}
168 			nNewPos--;
169 		}
170 
171 		if( bUndo )
172 			EndUndo();
173 
174 		if (bChg)
175 			MarkListHasChanged();
176 	}
177 }
178 
MovMarkedToBtm()179 void SdrEditView::MovMarkedToBtm()
180 {
181 	sal_uIntPtr nAnz=GetMarkedObjectCount();
182 	if (nAnz!=0)
183 	{
184 		const bool bUndo = IsUndoEnabled();
185 
186 		if( bUndo )
187 			BegUndo(ImpGetResStr(STR_EditMovToBtm),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVTOBTM);
188 
189 		SortMarkedObjects();
190 		sal_uIntPtr nm;
191 		for (nm=0; nm<nAnz; nm++)
192 		{ // Ordnums muessen alle stimmen!
193 			GetMarkedObjectByIndex(nm)->GetOrdNum();
194 		}
195 
196 		sal_Bool bChg=sal_False;
197 		SdrObjList* pOL0=NULL;
198 		sal_uIntPtr nNewPos=0;
199 		for (nm=0; nm<nAnz; nm++)
200 		{
201 			SdrMark* pM=GetSdrMarkByIndex(nm);
202 			SdrObject* pObj=pM->GetMarkedSdrObj();
203 			SdrObjList* pOL=pObj->GetObjList();
204 			if (pOL!=pOL0)
205 			{
206 				nNewPos=0;
207 				pOL0=pOL;
208 			}
209 			sal_uIntPtr nNowPos=pObj->GetOrdNumDirect();
210 			const Rectangle& rBR=pObj->GetCurrentBoundRect();
211 			sal_uIntPtr nCmpPos=nNowPos; if (nCmpPos>0) nCmpPos--;
212             SdrObject* pMaxObj=GetMaxToBtmObj(pObj);
213             if (pMaxObj!=NULL)
214 			{
215                 sal_uIntPtr nMinPos=pMaxObj->GetOrdNum()+1;
216                 if (nNewPos<nMinPos)
217 					nNewPos=nMinPos; // diesen nicht ueberholen.
218                 if (nNewPos>nNowPos)
219 					nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben
220             }
221 			sal_Bool bEnd=sal_False;
222 			// nNewPos ist an dieser Stelle noch die maximale Position,
223 			// an der das Obj hinruecken darf, ohne seinen Vorgaenger
224 			// (Mehrfachselektion) zu ueberholen.
225 			while (nCmpPos>nNewPos && !bEnd)
226 			{
227 				SdrObject* pCmpObj=pOL->GetObj(nCmpPos);
228 				if (pCmpObj==NULL)
229 				{
230 					DBG_ERROR("MovMarkedToBtm(): Vergleichsobjekt nicht gefunden");
231 					bEnd=sal_True;
232                 }
233 				else if (pCmpObj==pMaxObj)
234 				{
235                     nNewPos=nCmpPos;
236                     nNewPos++;
237                     bEnd=sal_True;
238 				}
239 				else if (rBR.IsOver(pCmpObj->GetCurrentBoundRect()))
240 				{
241 					nNewPos=nCmpPos;
242 					bEnd=sal_True;
243 				}
244 				else
245 				{
246 					nCmpPos--;
247 				}
248 			}
249 			if (nNowPos!=nNewPos)
250 			{
251 				bChg=sal_True;
252 				pOL->SetObjectOrdNum(nNowPos,nNewPos);
253 				if( bUndo )
254 					AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
255 				ObjOrderChanged(pObj,nNowPos,nNewPos);
256 			}
257 			nNewPos++;
258 		}
259 
260 		if(bUndo)
261 			EndUndo();
262 
263 		if(bChg)
264 			MarkListHasChanged();
265 	}
266 }
267 
PutMarkedToTop()268 void SdrEditView::PutMarkedToTop()
269 {
270 	PutMarkedInFrontOfObj(NULL);
271 }
272 
PutMarkedInFrontOfObj(const SdrObject * pRefObj)273 void SdrEditView::PutMarkedInFrontOfObj(const SdrObject* pRefObj)
274 {
275 	sal_uIntPtr nAnz=GetMarkedObjectCount();
276 	if (nAnz!=0)
277 	{
278 		const bool bUndo = IsUndoEnabled();
279 		if( bUndo )
280 			BegUndo(ImpGetResStr(STR_EditPutToTop),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_PUTTOTOP);
281 
282 		SortMarkedObjects();
283 
284 		if (pRefObj!=NULL)
285 		{
286 			// Damit "Vor das Objekt" auch funktioniert wenn die
287 			// markierten Objekte bereits vor dem Objekt stehen
288 			sal_uIntPtr nRefMark=TryToFindMarkedObject(pRefObj);
289 			SdrMark aRefMark;
290 			if (nRefMark!=CONTAINER_ENTRY_NOTFOUND)
291 			{
292 				aRefMark=*GetSdrMarkByIndex(nRefMark);
293 				GetMarkedObjectListWriteAccess().DeleteMark(nRefMark);
294 			}
295 			PutMarkedToBtm();
296 			if (nRefMark!=CONTAINER_ENTRY_NOTFOUND)
297 			{
298 				GetMarkedObjectListWriteAccess().InsertEntry(aRefMark);
299 				SortMarkedObjects();
300 			}
301 		}
302 		sal_uIntPtr nm;
303 		for (nm=0; nm<nAnz; nm++)
304 		{ // Ordnums muessen alle stimmen!
305 			GetMarkedObjectByIndex(nm)->GetOrdNum();
306 		}
307 		sal_Bool bChg=sal_False;
308 		SdrObjList* pOL0=NULL;
309 		sal_uIntPtr nNewPos=0;
310 		for (nm=nAnz; nm>0;)
311 		{
312 			nm--;
313 			SdrMark* pM=GetSdrMarkByIndex(nm);
314 			SdrObject* pObj=pM->GetMarkedSdrObj();
315 			if (pObj!=pRefObj)
316 			{
317 				SdrObjList* pOL=pObj->GetObjList();
318 				if (pOL!=pOL0)
319 				{
320 					nNewPos=sal_uIntPtr(pOL->GetObjCount()-1);
321 					pOL0=pOL;
322 				}
323 				sal_uIntPtr nNowPos=pObj->GetOrdNumDirect();
324                 SdrObject* pMaxObj=GetMaxToTopObj(pObj);
325                 if (pMaxObj!=NULL)
326 				{
327                     sal_uIntPtr nMaxOrd=pMaxObj->GetOrdNum(); // geht leider nicht anders
328                     if (nMaxOrd>0)
329 						nMaxOrd--;
330                     if (nNewPos>nMaxOrd)
331 						nNewPos=nMaxOrd; // nicht ueberholen.
332                     if (nNewPos<nNowPos)
333 						nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben
334                 }
335 				if (pRefObj!=NULL)
336 				{
337 					if (pRefObj->GetObjList()==pObj->GetObjList())
338 					{
339 						sal_uIntPtr nMaxOrd=pRefObj->GetOrdNum(); // geht leider nicht anders
340 						if (nNewPos>nMaxOrd)
341 							nNewPos=nMaxOrd; // nicht ueberholen.
342 						if (nNewPos<nNowPos)
343 							nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben
344 					}
345 					else
346 					{
347 						nNewPos=nNowPos; // andere PageView, also nicht veraendern
348 					}
349 				}
350 				if (nNowPos!=nNewPos)
351 				{
352 					bChg=sal_True;
353 					pOL->SetObjectOrdNum(nNowPos,nNewPos);
354 					if( bUndo )
355 						AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
356 					ObjOrderChanged(pObj,nNowPos,nNewPos);
357 				}
358 				nNewPos--;
359 			} // if (pObj!=pRefObj)
360 		} // for-Schleife ueber alle Markierten Objekte
361 
362 		if( bUndo )
363 			EndUndo();
364 
365 		if(bChg)
366 			MarkListHasChanged();
367 	}
368 }
369 
PutMarkedToBtm()370 void SdrEditView::PutMarkedToBtm()
371 {
372 	PutMarkedBehindObj(NULL);
373 }
374 
PutMarkedBehindObj(const SdrObject * pRefObj)375 void SdrEditView::PutMarkedBehindObj(const SdrObject* pRefObj)
376 {
377 	sal_uIntPtr nAnz=GetMarkedObjectCount();
378 	if (nAnz!=0)
379 	{
380 		const bool bUndo = IsUndoEnabled();
381 
382 		if( bUndo )
383 			BegUndo(ImpGetResStr(STR_EditPutToBtm),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_PUTTOBTM);
384 
385 		SortMarkedObjects();
386 		if (pRefObj!=NULL)
387 		{
388 			// Damit "Hinter das Objekt" auch funktioniert wenn die
389 			// markierten Objekte bereits hinter dem Objekt stehen
390 			sal_uIntPtr nRefMark=TryToFindMarkedObject(pRefObj);
391 			SdrMark aRefMark;
392 			if (nRefMark!=CONTAINER_ENTRY_NOTFOUND)
393 			{
394 				aRefMark=*GetSdrMarkByIndex(nRefMark);
395 				GetMarkedObjectListWriteAccess().DeleteMark(nRefMark);
396 			}
397 			PutMarkedToTop();
398 			if (nRefMark!=CONTAINER_ENTRY_NOTFOUND)
399 			{
400 				GetMarkedObjectListWriteAccess().InsertEntry(aRefMark);
401 				SortMarkedObjects();
402 			}
403 		}
404 		sal_uIntPtr nm;
405 		for (nm=0; nm<nAnz; nm++) { // Ordnums muessen alle stimmen!
406 			GetMarkedObjectByIndex(nm)->GetOrdNum();
407 		}
408 		sal_Bool bChg=sal_False;
409 		SdrObjList* pOL0=NULL;
410 		sal_uIntPtr nNewPos=0;
411 		for (nm=0; nm<nAnz; nm++) {
412 			SdrMark* pM=GetSdrMarkByIndex(nm);
413 			SdrObject* pObj=pM->GetMarkedSdrObj();
414 			if (pObj!=pRefObj) {
415 				SdrObjList* pOL=pObj->GetObjList();
416 				if (pOL!=pOL0) {
417 					nNewPos=0;
418 					pOL0=pOL;
419 				}
420 				sal_uIntPtr nNowPos=pObj->GetOrdNumDirect();
421                 SdrObject* pMinObj=GetMaxToBtmObj(pObj);
422                 if (pMinObj!=NULL) {
423                     sal_uIntPtr nMinOrd=pMinObj->GetOrdNum()+1; // geht leider nicht anders
424                     if (nNewPos<nMinOrd) nNewPos=nMinOrd; // nicht ueberholen.
425                     if (nNewPos>nNowPos) nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben
426                 }
427 				if (pRefObj!=NULL) {
428 					if (pRefObj->GetObjList()==pObj->GetObjList()) {
429 						sal_uIntPtr nMinOrd=pRefObj->GetOrdNum(); // geht leider nicht anders
430 						if (nNewPos<nMinOrd) nNewPos=nMinOrd; // nicht ueberholen.
431 						if (nNewPos>nNowPos) nNewPos=nNowPos; // aber dabei auch nicht in die falsche Richtung schieben
432 					} else {
433 						nNewPos=nNowPos; // andere PageView, also nicht veraendern
434 					}
435 				}
436 				if (nNowPos!=nNewPos) {
437 					bChg=sal_True;
438 					pOL->SetObjectOrdNum(nNowPos,nNewPos);
439 					if( bUndo )
440 						AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
441 					ObjOrderChanged(pObj,nNowPos,nNewPos);
442 				}
443 				nNewPos++;
444 			} // if (pObj!=pRefObj)
445 		} // for-Schleife ueber alle markierten Objekte
446 
447 		if(bUndo)
448 			EndUndo();
449 
450 		if(bChg)
451 			MarkListHasChanged();
452 	}
453 }
454 
ReverseOrderOfMarked()455 void SdrEditView::ReverseOrderOfMarked()
456 {
457 	SortMarkedObjects();
458 	sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
459 	if (nMarkAnz>0)
460 	{
461 		//sal_Bool bNeedBundle=sal_False;
462 		sal_Bool bChg=sal_False;
463 
464 		bool bUndo = IsUndoEnabled();
465 		if( bUndo )
466 			BegUndo(ImpGetResStr(STR_EditRevOrder),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_REVORDER);
467 
468 		sal_uIntPtr a=0;
469 		do {
470 			// Markierung ueber mehrere PageViews berueksichtigen
471 			sal_uIntPtr b=a+1;
472 			while (b<nMarkAnz && GetSdrPageViewOfMarkedByIndex(b) == GetSdrPageViewOfMarkedByIndex(a)) b++;
473 			b--;
474 			SdrObjList* pOL=GetSdrPageViewOfMarkedByIndex(a)->GetObjList();
475 			sal_uIntPtr c=b;
476 			if (a<c) { // Sicherstellen, dass die OrdNums nicht Dirty sind
477 				GetMarkedObjectByIndex(a)->GetOrdNum();
478 			}
479 			while (a<c) {
480 				SdrObject* pObj1=GetMarkedObjectByIndex(a);
481 				SdrObject* pObj2=GetMarkedObjectByIndex(c);
482 				sal_uIntPtr nOrd1=pObj1->GetOrdNumDirect();
483 				sal_uIntPtr nOrd2=pObj2->GetOrdNumDirect();
484 				if( bUndo )
485 				{
486 					AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj1,nOrd1,nOrd2));
487 					AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj2,nOrd2-1,nOrd1));
488 				}
489 				pOL->SetObjectOrdNum(nOrd1,nOrd2);
490 				// Obj 2 ist um eine Position nach vorn gerutscht, deshalb nun nOrd2-1
491 				pOL->SetObjectOrdNum(nOrd2-1,nOrd1);
492 				// Verwendung von Replace statt SetOrdNum wg. Performance (Neuberechnung der Ordnums)
493 				a++; c--;
494 				bChg=sal_True;
495 			}
496 			a=b+1;
497 		} while (a<nMarkAnz);
498 
499 		if(bUndo)
500 			EndUndo();
501 
502 		if(bChg)
503 			MarkListHasChanged();
504 	}
505 }
506 
ImpCheckToTopBtmPossible()507 void SdrEditView::ImpCheckToTopBtmPossible()
508 {
509 	sal_uIntPtr nAnz=GetMarkedObjectCount();
510 	if (nAnz==0)
511 		return;
512 	if (nAnz==1)
513 	{ // Sonderbehandlung fuer Einzelmarkierung
514 		SdrObject* pObj=GetMarkedObjectByIndex(0);
515 		SdrObjList* pOL=pObj->GetObjList();
516 		sal_uIntPtr nMax=pOL->GetObjCount();
517 		sal_uIntPtr nMin=0;
518 		sal_uIntPtr nObjNum=pObj->GetOrdNum();
519 		SdrObject* pRestrict=GetMaxToTopObj(pObj);
520 		if (pRestrict!=NULL) {
521 			sal_uIntPtr nRestrict=pRestrict->GetOrdNum();
522 			if (nRestrict<nMax) nMax=nRestrict;
523 		}
524 		pRestrict=GetMaxToBtmObj(pObj);
525 		if (pRestrict!=NULL) {
526 			sal_uIntPtr nRestrict=pRestrict->GetOrdNum();
527 			if (nRestrict>nMin) nMin=nRestrict;
528 		}
529 		bToTopPossible=nObjNum<sal_uIntPtr(nMax-1);
530 		bToBtmPossible=nObjNum>nMin;
531 	} else { // Mehrfachselektion
532 		sal_uIntPtr nm=0;
533 		SdrObjList* pOL0=NULL;
534 		long nPos0=-1;
535 		while (!bToBtmPossible && nm<nAnz) { // 'nach hinten' checken
536 			SdrObject* pObj=GetMarkedObjectByIndex(nm);
537 			SdrObjList* pOL=pObj->GetObjList();
538 			if (pOL!=pOL0) {
539 				nPos0=-1;
540 				pOL0=pOL;
541 			}
542 			sal_uIntPtr nPos=pObj->GetOrdNum();
543 			bToBtmPossible=nPos>sal_uIntPtr(nPos0+1);
544 			nPos0=long(nPos);
545 			nm++;
546 		}
547 		nm=nAnz;
548 		pOL0=NULL;
549 		nPos0=0x7FFFFFFF;
550 		while (!bToTopPossible && nm>0) { // 'nach vorn' checken
551 			nm--;
552 			SdrObject* pObj=GetMarkedObjectByIndex(nm);
553 			SdrObjList* pOL=pObj->GetObjList();
554 			if (pOL!=pOL0) {
555 				nPos0=pOL->GetObjCount();
556 				pOL0=pOL;
557 			}
558 			sal_uIntPtr nPos=pObj->GetOrdNum();
559 			bToTopPossible=nPos+1<sal_uIntPtr(nPos0);
560 			nPos0=nPos;
561 		}
562 	}
563 }
564 
565 ////////////////////////////////////////////////////////////////////////////////////////////////////
566 //
567 //   @@@@    @@@@   @@   @@  @@@@@   @@  @@  @@  @@@@@
568 //  @@  @@  @@  @@  @@@ @@@  @@  @@  @@  @@@ @@  @@
569 //  @@      @@  @@  @@@@@@@  @@  @@  @@  @@@@@@  @@
570 //  @@      @@  @@  @@@@@@@  @@@@@   @@  @@@@@@  @@@@
571 //  @@      @@  @@  @@ @ @@  @@  @@  @@  @@ @@@  @@
572 //  @@  @@  @@  @@  @@   @@  @@  @@  @@  @@  @@  @@
573 //   @@@@    @@@@   @@   @@  @@@@@   @@  @@  @@  @@@@@
574 //
575 ////////////////////////////////////////////////////////////////////////////////////////////////////
576 
ImpCopyAttributes(const SdrObject * pSource,SdrObject * pDest) const577 void SdrEditView::ImpCopyAttributes(const SdrObject* pSource, SdrObject* pDest) const
578 {
579 	if (pSource!=NULL) {
580 		SdrObjList* pOL=pSource->GetSubList();
581 		if (pOL!=NULL && !pSource->Is3DObj()) { // erstes Nichtgruppenobjekt aus der Gruppe holen
582 			SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS);
583 			pSource=aIter.Next();
584 		}
585 	}
586 
587 	if(pSource && pDest)
588 	{
589 		SfxItemSet aSet(pMod->GetItemPool(),
590 			SDRATTR_START,				SDRATTR_NOTPERSIST_FIRST-1,
591 			SDRATTR_NOTPERSIST_LAST+1,	SDRATTR_END,
592 			EE_ITEMS_START,				EE_ITEMS_END,
593 			0, 0); // #52757#, #52762#
594 
595 		aSet.Put(pSource->GetMergedItemSet());
596 
597 		pDest->ClearMergedItem();
598 		pDest->SetMergedItemSet(aSet);
599 
600 		pDest->NbcSetLayer(pSource->GetLayer());
601 		pDest->NbcSetStyleSheet(pSource->GetStyleSheet(), sal_True);
602 	}
603 }
604 
ImpCanConvertForCombine1(const SdrObject * pObj) const605 sal_Bool SdrEditView::ImpCanConvertForCombine1(const SdrObject* pObj) const
606 {
607 	// #69711 : new condition IsLine() to be able to combine simple Lines
608 	sal_Bool bIsLine(sal_False);
609 
610 	const SdrPathObj* pPath = PTR_CAST(SdrPathObj,pObj);
611 
612 	if(pPath)
613 	{
614 		bIsLine = pPath->IsLine();
615 	}
616 
617 	SdrObjTransformInfoRec aInfo;
618 	pObj->TakeObjInfo(aInfo);
619 
620 	return (aInfo.bCanConvToPath || aInfo.bCanConvToPoly || bIsLine);
621 }
622 
ImpCanConvertForCombine(const SdrObject * pObj) const623 sal_Bool SdrEditView::ImpCanConvertForCombine(const SdrObject* pObj) const
624 {
625 	SdrObjList* pOL = pObj->GetSubList();
626 
627 	if(pOL && !pObj->Is3DObj())
628 	{
629 		SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS);
630 
631 		while(aIter.IsMore())
632 		{
633 			SdrObject* pObj1 = aIter.Next();
634 
635 			// Es muessen alle Member einer Gruppe konvertierbar sein
636 			if(!ImpCanConvertForCombine1(pObj1))
637 			{
638 				return sal_False;
639 			}
640 		}
641 	}
642 	else
643 	{
644 		if(!ImpCanConvertForCombine1(pObj))
645 		{
646 			return sal_False;
647 		}
648 	}
649 
650 	return sal_True;
651 }
652 
ImpGetPolyPolygon1(const SdrObject * pObj,sal_Bool bCombine) const653 basegfx::B2DPolyPolygon SdrEditView::ImpGetPolyPolygon1(const SdrObject* pObj, sal_Bool bCombine) const
654 {
655 	basegfx::B2DPolyPolygon aRetval;
656 	SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj);
657 
658 	if(bCombine && pPath && !pObj->GetOutlinerParaObject())
659 	{
660 		aRetval = pPath->GetPathPoly();
661 	}
662 	else
663 	{
664 		SdrObject* pConvObj = pObj->ConvertToPolyObj(bCombine, sal_False);
665 
666 		if(pConvObj)
667 		{
668 			SdrObjList* pOL = pConvObj->GetSubList();
669 
670 			if(pOL)
671 			{
672 				SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS);
673 
674 				while(aIter.IsMore())
675 				{
676 					SdrObject* pObj1 = aIter.Next();
677 					pPath = PTR_CAST(SdrPathObj, pObj1);
678 
679 					if(pPath)
680 					{
681 						aRetval.append(pPath->GetPathPoly());
682 					}
683 				}
684 			}
685 			else
686 			{
687 				pPath = PTR_CAST(SdrPathObj, pConvObj);
688 
689 				if(pPath)
690 				{
691 					aRetval = pPath->GetPathPoly();
692 				}
693 			}
694 
695 			SdrObject::Free( pConvObj );
696 		}
697 	}
698 
699 	return aRetval;
700 }
701 
ImpGetPolyPolygon(const SdrObject * pObj,sal_Bool bCombine) const702 basegfx::B2DPolyPolygon SdrEditView::ImpGetPolyPolygon(const SdrObject* pObj, sal_Bool bCombine) const
703 {
704 	SdrObjList* pOL = pObj->GetSubList();
705 
706 	if(pOL && !pObj->Is3DObj())
707 	{
708 		basegfx::B2DPolyPolygon aRetval;
709 		SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS);
710 
711 		while(aIter.IsMore())
712 		{
713 			SdrObject* pObj1 = aIter.Next();
714 			aRetval.append(ImpGetPolyPolygon1(pObj1, bCombine));
715 		}
716 
717 		return aRetval;
718 	}
719 	else
720 	{
721 		return ImpGetPolyPolygon1(pObj, bCombine);
722 	}
723 }
724 
ImpCombineToSinglePolygon(const basegfx::B2DPolyPolygon & rPolyPolygon) const725 basegfx::B2DPolygon SdrEditView::ImpCombineToSinglePolygon(const basegfx::B2DPolyPolygon& rPolyPolygon) const
726 {
727 	const sal_uInt32 nPolyCount(rPolyPolygon.count());
728 
729 	if(0L == nPolyCount)
730 	{
731 		return basegfx::B2DPolygon();
732 	}
733 	else if(1L == nPolyCount)
734 	{
735 		return rPolyPolygon.getB2DPolygon(0L);
736 	}
737 	else
738 	{
739 		basegfx::B2DPolygon aRetval(rPolyPolygon.getB2DPolygon(0L));
740 
741 		for(sal_uInt32 a(1L); a < nPolyCount; a++)
742 		{
743 			basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a));
744 
745 			if(aRetval.count())
746 			{
747 				if(aCandidate.count())
748 				{
749 					const basegfx::B2DPoint aCA(aCandidate.getB2DPoint(0L));
750 					const basegfx::B2DPoint aCB(aCandidate.getB2DPoint(aCandidate.count() - 1L));
751 					const basegfx::B2DPoint aRA(aRetval.getB2DPoint(0L));
752 					const basegfx::B2DPoint aRB(aRetval.getB2DPoint(aRetval.count() - 1L));
753 
754 					const double fRACA(basegfx::B2DVector(aCA - aRA).getLength());
755 					const double fRACB(basegfx::B2DVector(aCB - aRA).getLength());
756 					const double fRBCA(basegfx::B2DVector(aCA - aRB).getLength());
757 					const double fRBCB(basegfx::B2DVector(aCB - aRB).getLength());
758 
759 					const double fSmallestRA(fRACA < fRACB ? fRACA : fRACB);
760 					const double fSmallestRB(fRBCA < fRBCB ? fRBCA : fRBCB);
761 
762 					if(fSmallestRA < fSmallestRB)
763 					{
764 						// flip result
765 						aRetval.flip();
766 					}
767 
768 					const double fSmallestCA(fRACA < fRBCA ? fRACA : fRBCA);
769 					const double fSmallestCB(fRACB < fRBCB ? fRACB : fRBCB);
770 
771 					if(fSmallestCB < fSmallestCA)
772 					{
773 						// flip candidate
774 						aCandidate.flip();
775 					}
776 
777 					// append candidate to retval
778 					aRetval.append(aCandidate);
779 				}
780 			}
781 			else
782 			{
783 				aRetval = aCandidate;
784 			}
785 		}
786 
787 		return aRetval;
788 	}
789 }
790 
791 // for distribution dialog function
792 struct ImpDistributeEntry
793 {
794 	SdrObject*					mpObj;
795 	sal_Int32						mnPos;
796 	sal_Int32						mnLength;
797 };
798 
DECLARE_LIST(ImpDistributeEntryList,ImpDistributeEntry *)799 DECLARE_LIST(ImpDistributeEntryList, ImpDistributeEntry*)
800 
801 void SdrEditView::DistributeMarkedObjects()
802 {
803 	sal_uInt32 nMark(GetMarkedObjectCount());
804 
805 	if(nMark > 2)
806 	{
807 		SfxItemSet aNewAttr(pMod->GetItemPool());
808 		//CHINA001 SvxDistributeDialog* pDlg = new SvxDistributeDialog(NULL, aNewAttr);
809 		SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
810 		if(pFact)
811 		{
812 			AbstractSvxDistributeDialog *pDlg = pFact->CreateSvxDistributeDialog(NULL, aNewAttr);
813 			DBG_ASSERT(pDlg, "Dialogdiet fail!");//CHINA001
814 
815 			sal_uInt16 nResult = pDlg->Execute();
816 
817 			if(nResult == RET_OK)
818 			{
819 				SvxDistributeHorizontal eHor = pDlg->GetDistributeHor();
820 				SvxDistributeVertical eVer = pDlg->GetDistributeVer();
821 				ImpDistributeEntryList aEntryList;
822 				sal_uInt32 a, nInsPos, nFullLength;
823 
824 				const bool bUndo = IsUndoEnabled();
825 				if( bUndo )
826 					BegUndo();
827 
828 				if(eHor != SvxDistributeHorizontalNone)
829 				{
830 					// build sorted entry list
831 					nFullLength = 0L;
832 
833 					for(a=0;a<nMark;a++)
834 					{
835 						SdrMark* pMark = GetSdrMarkByIndex(a);
836 						ImpDistributeEntry* pNew = new ImpDistributeEntry;
837 
838 						pNew->mpObj = pMark->GetMarkedSdrObj();
839 						nInsPos = 0;
840 
841 						switch(eHor)
842 						{
843 							case SvxDistributeHorizontalLeft:
844 							{
845 								pNew->mnPos = pNew->mpObj->GetSnapRect().Left();
846 								break;
847 							}
848 							case SvxDistributeHorizontalCenter:
849 							{
850 								pNew->mnPos = (pNew->mpObj->GetSnapRect().Right() + pNew->mpObj->GetSnapRect().Left()) / 2;
851 								break;
852 							}
853 							case SvxDistributeHorizontalDistance:
854 							{
855 								pNew->mnLength = pNew->mpObj->GetSnapRect().GetWidth() + 1;
856 								nFullLength += pNew->mnLength;
857 								pNew->mnPos = (pNew->mpObj->GetSnapRect().Right() + pNew->mpObj->GetSnapRect().Left()) / 2;
858 								break;
859 							}
860 							case SvxDistributeHorizontalRight:
861 							{
862 								pNew->mnPos = pNew->mpObj->GetSnapRect().Right();
863 								break;
864 							}
865 							default: break;
866 						}
867 
868 						while(nInsPos < aEntryList.Count() && aEntryList.GetObject(nInsPos)->mnPos < pNew->mnPos)
869 							nInsPos++;
870 
871 						aEntryList.Insert(pNew, nInsPos);
872 					}
873 
874 					if(eHor == SvxDistributeHorizontalDistance)
875 					{
876 						// calc room in-between
877 						sal_Int32 nWidth = GetAllMarkedBoundRect().GetWidth() + 1;
878 						double fStepWidth = ((double)nWidth - (double)nFullLength) / (double)(aEntryList.Count() - 1);
879 						double fStepStart = (double)aEntryList.GetObject(0)->mnPos;
880 						fStepStart += fStepWidth + (double)((aEntryList.GetObject(0)->mnLength + aEntryList.GetObject(1)->mnLength) / 2);
881 
882 						// move entries 1..n-1
883 						for(a=1;a<aEntryList.Count()-1;a++)
884 						{
885 							ImpDistributeEntry* pCurr = aEntryList.GetObject(a);
886 							ImpDistributeEntry* pNext = aEntryList.GetObject(a+1);
887 							sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos;
888 							if( bUndo )
889 								AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj));
890 							pCurr->mpObj->Move(Size(nDelta, 0));
891 							fStepStart += fStepWidth + (double)((pCurr->mnLength + pNext->mnLength) / 2);
892 						}
893 					}
894 					else
895 					{
896 						// calc distances
897 						sal_Int32 nWidth = aEntryList.GetObject(aEntryList.Count() - 1)->mnPos - aEntryList.GetObject(0)->mnPos;
898 						double fStepWidth = (double)nWidth / (double)(aEntryList.Count() - 1);
899 						double fStepStart = (double)aEntryList.GetObject(0)->mnPos;
900 						fStepStart += fStepWidth;
901 
902 						// move entries 1..n-1
903 						for(a=1;a<aEntryList.Count()-1;a++)
904 						{
905 							ImpDistributeEntry* pCurr = aEntryList.GetObject(a);
906 							sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos;
907 							if( bUndo )
908 								AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj));
909 							pCurr->mpObj->Move(Size(nDelta, 0));
910 							fStepStart += fStepWidth;
911 						}
912 					}
913 
914 					// clear list
915 					while(aEntryList.Count())
916 						delete aEntryList.Remove((sal_uIntPtr)0L);
917 				}
918 
919 				if(eVer != SvxDistributeVerticalNone)
920 				{
921 					// build sorted entry list
922 					nFullLength = 0L;
923 
924 					for(a=0;a<nMark;a++)
925 					{
926 						SdrMark* pMark = GetSdrMarkByIndex(a);
927 						ImpDistributeEntry* pNew = new ImpDistributeEntry;
928 
929 						pNew->mpObj = pMark->GetMarkedSdrObj();
930 						nInsPos = 0;
931 
932 						switch(eVer)
933 						{
934 							case SvxDistributeVerticalTop:
935 							{
936 								pNew->mnPos = pNew->mpObj->GetSnapRect().Top();
937 								break;
938 							}
939 							case SvxDistributeVerticalCenter:
940 							{
941 								pNew->mnPos = (pNew->mpObj->GetSnapRect().Bottom() + pNew->mpObj->GetSnapRect().Top()) / 2;
942 								break;
943 							}
944 							case SvxDistributeVerticalDistance:
945 							{
946 								pNew->mnLength = pNew->mpObj->GetSnapRect().GetHeight() + 1;
947 								nFullLength += pNew->mnLength;
948 								pNew->mnPos = (pNew->mpObj->GetSnapRect().Bottom() + pNew->mpObj->GetSnapRect().Top()) / 2;
949 								break;
950 							}
951 							case SvxDistributeVerticalBottom:
952 							{
953 								pNew->mnPos = pNew->mpObj->GetSnapRect().Bottom();
954 								break;
955 							}
956 							default: break;
957 						}
958 
959 						while(nInsPos < aEntryList.Count() && aEntryList.GetObject(nInsPos)->mnPos < pNew->mnPos)
960 							nInsPos++;
961 
962 						aEntryList.Insert(pNew, nInsPos);
963 					}
964 
965 					if(eVer == SvxDistributeVerticalDistance)
966 					{
967 						// calc room in-between
968 						sal_Int32 nHeight = GetAllMarkedBoundRect().GetHeight() + 1;
969 						double fStepWidth = ((double)nHeight - (double)nFullLength) / (double)(aEntryList.Count() - 1);
970 						double fStepStart = (double)aEntryList.GetObject(0)->mnPos;
971 						fStepStart += fStepWidth + (double)((aEntryList.GetObject(0)->mnLength + aEntryList.GetObject(1)->mnLength) / 2);
972 
973 						// move entries 1..n-1
974 						for(a=1;a<aEntryList.Count()-1;a++)
975 						{
976 							ImpDistributeEntry* pCurr = aEntryList.GetObject(a);
977 							ImpDistributeEntry* pNext = aEntryList.GetObject(a+1);
978 							sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos;
979 							if( bUndo )
980 								AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj));
981 							pCurr->mpObj->Move(Size(0, nDelta));
982 							fStepStart += fStepWidth + (double)((pCurr->mnLength + pNext->mnLength) / 2);
983 						}
984 					}
985 					else
986 					{
987 						// calc distances
988 						sal_Int32 nHeight = aEntryList.GetObject(aEntryList.Count() - 1)->mnPos - aEntryList.GetObject(0)->mnPos;
989 						double fStepWidth = (double)nHeight / (double)(aEntryList.Count() - 1);
990 						double fStepStart = (double)aEntryList.GetObject(0)->mnPos;
991 						fStepStart += fStepWidth;
992 
993 						// move entries 1..n-1
994 						for(a=1;a<aEntryList.Count()-1;a++)
995 						{
996 							ImpDistributeEntry* pCurr = aEntryList.GetObject(a);
997 							sal_Int32 nDelta = (sal_Int32)(fStepStart + 0.5) - pCurr->mnPos;
998 							if( bUndo )
999 								AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pCurr->mpObj));
1000 							pCurr->mpObj->Move(Size(0, nDelta));
1001 							fStepStart += fStepWidth;
1002 						}
1003 					}
1004 
1005 					// clear list
1006 					while(aEntryList.Count())
1007 						delete aEntryList.Remove((sal_uIntPtr)0L);
1008 				}
1009 
1010 				// UNDO-Comment and end of UNDO
1011 				SetUndoComment(ImpGetResStr(STR_DistributeMarkedObjects));
1012 
1013 				if( bUndo )
1014 					EndUndo();
1015 			}
1016 
1017 			delete(pDlg);
1018 		}
1019 	}
1020 }
1021 
MergeMarkedObjects(SdrMergeMode eMode)1022 void SdrEditView::MergeMarkedObjects(SdrMergeMode eMode)
1023 {
1024 	// #i73441# check content
1025 	if(AreObjectsMarked())
1026 	{
1027 		SdrMarkList aRemove;
1028 		SortMarkedObjects();
1029 
1030 		const bool bUndo = IsUndoEnabled();
1031 
1032 		if( bUndo )
1033 			BegUndo();
1034 
1035 		sal_uInt32 nInsPos=0xFFFFFFFF;
1036 		const SdrObject* pAttrObj = NULL;
1037 		basegfx::B2DPolyPolygon aMergePolyPolygonA;
1038 		basegfx::B2DPolyPolygon aMergePolyPolygonB;
1039 
1040 		SdrObjList* pInsOL = NULL;
1041 		SdrPageView* pInsPV = NULL;
1042 		sal_Bool bFirstObjectComplete(sal_False);
1043 
1044 		// make sure selected objects are contour objects
1045 		// since now basegfx::tools::adaptiveSubdivide() is used, it is no longer
1046 		// necessary to use ConvertMarkedToPolyObj which will subdivide curves using the old
1047 		// mechanisms. In a next step the polygon clipper will even be able to clip curves...
1048 		// ConvertMarkedToPolyObj(sal_True);
1049 		ConvertMarkedToPathObj(sal_True);
1050 		OSL_ENSURE(AreObjectsMarked(), "no more objects selected after preparations (!)");
1051 
1052 		for(sal_uInt32 a=0;a<GetMarkedObjectCount();a++)
1053 		{
1054 			SdrMark* pM = GetSdrMarkByIndex(a);
1055 			SdrObject* pObj = pM->GetMarkedSdrObj();
1056 
1057 			if(ImpCanConvertForCombine(pObj))
1058 			{
1059 				if(!pAttrObj)
1060 					pAttrObj = pObj;
1061 
1062 				nInsPos = pObj->GetOrdNum() + 1;
1063 				pInsPV = pM->GetPageView();
1064 				pInsOL = pObj->GetObjList();
1065 
1066 				// #i76891# use single iter from SJ here which works on SdrObjects and takes
1067 				// groups into account by itself
1068 				SdrObjListIter aIter(*pObj, IM_DEEPWITHGROUPS);
1069 
1070 				while(aIter.IsMore())
1071 				{
1072 					SdrObject* pCandidate = aIter.Next();
1073 					SdrPathObj* pPathObj = PTR_CAST(SdrPathObj, pCandidate);
1074 					if(pPathObj)
1075 					{
1076 						basegfx::B2DPolyPolygon aTmpPoly(pPathObj->GetPathPoly());
1077 
1078 						// #i76891# unfortunately ConvertMarkedToPathObj has converted all
1079 						// involved polygon data to curve segments, even if not necessary.
1080 						// It is better to try to reduce to more simple polygons.
1081 						aTmpPoly = basegfx::tools::simplifyCurveSegments(aTmpPoly);
1082 
1083 						// for each part polygon as preparation, remove self-intersections
1084 						// correct orientations and get rid of evtl. neutral polygons.
1085 	                    aTmpPoly = basegfx::tools::prepareForPolygonOperation(aTmpPoly);
1086 
1087 						if(!bFirstObjectComplete)
1088 						{
1089                             // #i111987# Also need to collect ORed source shape when more than
1090                             // a single polygon is involved
1091                             if(aMergePolyPolygonA.count())
1092                             {
1093                                 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA, aTmpPoly);
1094                             }
1095                             else
1096                             {
1097     							aMergePolyPolygonA = aTmpPoly;
1098                             }
1099 						}
1100 						else
1101 						{
1102                             if(aMergePolyPolygonB.count())
1103                             {
1104                                 // to topologically correctly collect the 2nd polygon
1105                                 // group it is necessary to OR the parts (each is seen as
1106                                 // XOR-FillRule polygon and they are drawn over each-other)
1107                                 aMergePolyPolygonB = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonB, aTmpPoly);
1108                             }
1109                             else
1110                             {
1111     							aMergePolyPolygonB = aTmpPoly;
1112                             }
1113 						}
1114 					}
1115 				}
1116 
1117 				// was there something added to the first poly?
1118 				if(!bFirstObjectComplete && aMergePolyPolygonA.count())
1119 				{
1120 					bFirstObjectComplete = sal_True;
1121 				}
1122 
1123 				// move object to temporary delete list
1124 				aRemove.InsertEntry(SdrMark(pObj, pM->GetPageView()));
1125 			}
1126 		}
1127 
1128 		switch(eMode)
1129 		{
1130 			case SDR_MERGE_MERGE:
1131 			{
1132 				// merge all contained parts (OR)
1133                 static bool bTestXOR(false);
1134                 if(bTestXOR)
1135                 {
1136                     aMergePolyPolygonA = basegfx::tools::solvePolygonOperationXor(aMergePolyPolygonA, aMergePolyPolygonB);
1137                 }
1138                 else
1139                 {
1140                     aMergePolyPolygonA = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA, aMergePolyPolygonB);
1141                 }
1142 				break;
1143 			}
1144 			case SDR_MERGE_SUBSTRACT:
1145 			{
1146 				// Substract B from A
1147                 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationDiff(aMergePolyPolygonA, aMergePolyPolygonB);
1148 				break;
1149 			}
1150 			case SDR_MERGE_INTERSECT:
1151 			{
1152 				// AND B and A
1153                 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationAnd(aMergePolyPolygonA, aMergePolyPolygonB);
1154 				break;
1155 			}
1156 		}
1157 
1158 		// #i73441# check insert list before taking actions
1159 		if(pInsOL)
1160 		{
1161 			SdrPathObj* pPath = new SdrPathObj(OBJ_PATHFILL, aMergePolyPolygonA);
1162 			ImpCopyAttributes(pAttrObj, pPath);
1163 			SdrInsertReason aReason(SDRREASON_VIEWCALL, pAttrObj);
1164 			pInsOL->InsertObject(pPath, nInsPos, &aReason);
1165 			if( bUndo )
1166 				AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath));
1167 
1168             // #124760# To have a correct selection with only the new object it is necessary to
1169             // unmark all objects first. If not doing so, there may remain invalid pointers to objects
1170             //TTTT:Not needed for aw080 (!)
1171             UnmarkAllObj(pInsPV);
1172 
1173 			MarkObj(pPath, pInsPV, sal_False, sal_True);
1174 		}
1175 
1176 		aRemove.ForceSort();
1177 		switch(eMode)
1178 		{
1179 			case SDR_MERGE_MERGE:
1180 			{
1181 				SetUndoComment(
1182 					ImpGetResStr(STR_EditMergeMergePoly),
1183 					aRemove.GetMarkDescription());
1184 				break;
1185 			}
1186 			case SDR_MERGE_SUBSTRACT:
1187 			{
1188 				SetUndoComment(
1189 					ImpGetResStr(STR_EditMergeSubstractPoly),
1190 					aRemove.GetMarkDescription());
1191 				break;
1192 			}
1193 			case SDR_MERGE_INTERSECT:
1194 			{
1195 				SetUndoComment(
1196 					ImpGetResStr(STR_EditMergeIntersectPoly),
1197 					aRemove.GetMarkDescription());
1198 				break;
1199 			}
1200 		}
1201 		DeleteMarkedList(aRemove);
1202 
1203 		if( bUndo )
1204 			EndUndo();
1205 	}
1206 }
1207 
CombineMarkedObjects(sal_Bool bNoPolyPoly)1208 void SdrEditView::CombineMarkedObjects(sal_Bool bNoPolyPoly)
1209 {
1210 	// #105899# Start of Combine-Undo put to front, else ConvertMarkedToPolyObj would
1211 	// create a 2nd Undo-action and Undo-Comment.
1212 
1213 	bool bUndo = IsUndoEnabled();
1214 
1215 	// Undo-String will be set later
1216 	if( bUndo )
1217 		BegUndo(String(), String(), bNoPolyPoly ? SDRREPFUNC_OBJ_COMBINE_ONEPOLY : SDRREPFUNC_OBJ_COMBINE_POLYPOLY);
1218 
1219 	// #105899# First, guarantee that all objects are converted to polyobjects,
1220 	// especially for SdrGrafObj with bitmap filling this is necessary to not
1221 	// loose the bitmap filling.
1222 
1223 	// #i12392#
1224 	// ConvertMarkedToPolyObj was too strong here, it will loose quality and
1225 	// information when curve objects are combined. This can be replaced by
1226 	// using ConvertMarkedToPathObj without changing the previous fix.
1227 
1228 	// #i21250#
1229 	// Instead of simply passing sal_True as LineToArea, use bNoPolyPoly as info
1230 	// if this command is a 'Combine' or a 'Connect' command. On Connect it's sal_True.
1231 	// To not concert line segments with a set line width to polygons in that case,
1232 	// use this info. Do not convert LineToArea on Connect commands.
1233 	// ConvertMarkedToPathObj(!bNoPolyPoly);
1234 
1235 	// #114310#
1236 	// This is used for Combine and Connect. In no case it is necessary to force
1237 	// the content to curve, but it is also not good to force to polygons. Thus,
1238 	// curve is the less information losing one. Remember: This place is not
1239 	// used for merge.
1240 	// LineToArea is never necessary, both commands are able to take over the
1241 	// set line style and to display it correctly. Thus, i will use a
1242 	// ConvertMarkedToPathObj with a sal_False in any case. Only drawback is that
1243 	// simple polygons will be changed to curves, but with no information loss.
1244 	ConvertMarkedToPathObj(sal_False /* bLineToArea */);
1245 
1246 	// continue as before
1247 	basegfx::B2DPolyPolygon aPolyPolygon;
1248 	SdrObjList* pAktOL = 0L;
1249 	SdrMarkList aRemoveMerker;
1250 
1251 	SortMarkedObjects();
1252 	sal_uInt32 nInsPos(0xFFFFFFFF);
1253 	SdrObjList* pInsOL = 0L;
1254 	SdrPageView* pInsPV = 0L;
1255 	const sal_uInt32 nAnz(GetMarkedObjectCount());
1256 	const SdrObject* pAttrObj = 0L;
1257 
1258 	for(sal_uInt32 a(nAnz); a > 0L; )
1259 	{
1260 		a--;
1261 		SdrMark* pM = GetSdrMarkByIndex(a);
1262 		SdrObject* pObj = pM->GetMarkedSdrObj();
1263 		SdrObjList* pThisOL = pObj->GetObjList();
1264 
1265 		if(pAktOL != pThisOL)
1266 		{
1267 			pAktOL = pThisOL;
1268 		}
1269 
1270 		if(ImpCanConvertForCombine(pObj))
1271 		{
1272 			// Obj merken fuer Attribute kopieren
1273 			pAttrObj = pObj;
1274 
1275 			// unfortunately ConvertMarkedToPathObj has converted all
1276 			// involved polygon data to curve segments, even if not necessary.
1277 			// It is better to try to reduce to more simple polygons.
1278 			basegfx::B2DPolyPolygon aTmpPoly(basegfx::tools::simplifyCurveSegments(ImpGetPolyPolygon(pObj, sal_True)));
1279 			aPolyPolygon.insert(0L, aTmpPoly);
1280 
1281 			if(!pInsOL)
1282 			{
1283 				nInsPos = pObj->GetOrdNum() + 1L;
1284 				pInsPV = pM->GetPageView();
1285 				pInsOL = pObj->GetObjList();
1286 			}
1287 
1288 			aRemoveMerker.InsertEntry(SdrMark(pObj, pM->GetPageView()));
1289 		}
1290 	}
1291 
1292 	if(bNoPolyPoly)
1293 	{
1294 		basegfx::B2DPolygon aCombinedPolygon(ImpCombineToSinglePolygon(aPolyPolygon));
1295 		aPolyPolygon.clear();
1296 		aPolyPolygon.append(aCombinedPolygon);
1297 	}
1298 
1299 	const sal_uInt32 nPolyCount(aPolyPolygon.count());
1300 
1301 	if(nPolyCount)
1302 	{
1303 		SdrObjKind eKind = OBJ_PATHFILL;
1304 
1305 		if(nPolyCount > 1L)
1306 		{
1307 			aPolyPolygon.setClosed(true);
1308 		}
1309 		else
1310 		{
1311 			// auf Polyline Checken
1312 			const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(0L));
1313 			const sal_uInt32 nPointCount(aPolygon.count());
1314 
1315 			if(nPointCount <= 2L)
1316 			{
1317 				eKind = OBJ_PATHLINE;
1318 			}
1319 			else
1320 			{
1321 				if(!aPolygon.isClosed())
1322 				{
1323 					const basegfx::B2DPoint aPointA(aPolygon.getB2DPoint(0L));
1324 					const basegfx::B2DPoint aPointB(aPolygon.getB2DPoint(nPointCount - 1L));
1325 					const double fDistance(basegfx::B2DVector(aPointB - aPointA).getLength());
1326 					const double fJoinTolerance(10.0);
1327 
1328 					if(fDistance < fJoinTolerance)
1329 					{
1330 						aPolyPolygon.setClosed(true);
1331 					}
1332 					else
1333 					{
1334 						eKind = OBJ_PATHLINE;
1335 					}
1336 				}
1337 			}
1338 		}
1339 
1340 		SdrPathObj* pPath = new SdrPathObj(eKind,aPolyPolygon);
1341 
1342 		// Attribute des untersten Objekts
1343 		ImpCopyAttributes(pAttrObj, pPath);
1344 
1345 		// #100408# If LineStyle of pAttrObj is XLINE_NONE force to XLINE_SOLID to make visible.
1346 		const XLineStyle eLineStyle = ((const XLineStyleItem&)pAttrObj->GetMergedItem(XATTR_LINESTYLE)).GetValue();
1347 		const XFillStyle eFillStyle = ((const XFillStyleItem&)pAttrObj->GetMergedItem(XATTR_FILLSTYLE)).GetValue();
1348 
1349 		// #110635#
1350 		// Take fill style/closed state of pAttrObj in account when deciding to change the line style
1351 		sal_Bool bIsClosedPathObj(pAttrObj->ISA(SdrPathObj) && ((SdrPathObj*)pAttrObj)->IsClosed());
1352 
1353 		if(XLINE_NONE == eLineStyle && (XFILL_NONE == eFillStyle || !bIsClosedPathObj))
1354 		{
1355 			pPath->SetMergedItem(XLineStyleItem(XLINE_SOLID));
1356 		}
1357 
1358 		SdrInsertReason aReason(SDRREASON_VIEWCALL,pAttrObj);
1359 		pInsOL->InsertObject(pPath,nInsPos,&aReason);
1360 		if( bUndo )
1361 			AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath));
1362 
1363 		// #111111#
1364 		// Here was a severe error: Without UnmarkAllObj, the new object was marked
1365 		// additionally to the two ones which are deleted below. As long as those are
1366 		// in the UNDO there is no problem, but as soon as they get deleted, the
1367 		// MarkList will contain deleted objects -> GPF.
1368 		UnmarkAllObj(pInsPV);
1369 		MarkObj(pPath, pInsPV, sal_False, sal_True);
1370 	}
1371 
1372 	// UndoComment aus den tatsaechlich verwendeten Objekten zusammenbauen
1373 	aRemoveMerker.ForceSort(); // wichtig fuer Remove (s.u.)
1374 	if( bUndo )
1375 		SetUndoComment(ImpGetResStr(bNoPolyPoly?STR_EditCombine_OnePoly:STR_EditCombine_PolyPoly),aRemoveMerker.GetMarkDescription());
1376 
1377 	// die tatsaechlich verwendeten Objekten aus der Liste entfernen
1378 	DeleteMarkedList(aRemoveMerker);
1379 	if( bUndo )
1380 		EndUndo();
1381 }
1382 
1383 ////////////////////////////////////////////////////////////////////////////////////////////////////
1384 //
1385 //  @@@@@   @@   @@@@   @@   @@   @@@@   @@  @@  @@@@@@  @@     @@@@@
1386 //  @@  @@  @@  @@  @@  @@@ @@@  @@  @@  @@@ @@    @@    @@     @@
1387 //  @@  @@  @@  @@      @@@@@@@  @@  @@  @@@@@@    @@    @@     @@
1388 //  @@  @@  @@   @@@@   @@@@@@@  @@@@@@  @@@@@@    @@    @@     @@@@
1389 //  @@  @@  @@      @@  @@ @ @@  @@  @@  @@ @@@    @@    @@     @@
1390 //  @@  @@  @@  @@  @@  @@   @@  @@  @@  @@  @@    @@    @@     @@
1391 //  @@@@@   @@   @@@@   @@   @@  @@  @@  @@  @@    @@    @@@@@  @@@@@
1392 //
1393 ////////////////////////////////////////////////////////////////////////////////////////////////////
1394 
ImpCanDismantle(const basegfx::B2DPolyPolygon & rPpolyPolygon,sal_Bool bMakeLines) const1395 sal_Bool SdrEditView::ImpCanDismantle(const basegfx::B2DPolyPolygon& rPpolyPolygon, sal_Bool bMakeLines) const
1396 {
1397 	sal_Bool bCan(sal_False);
1398 	const sal_uInt32 nPolygonCount(rPpolyPolygon.count());
1399 
1400 	if(nPolygonCount >= 2L)
1401 	{
1402 		// #i69172# dismantle makes sense with 2 or more polygons in a polyPolygon
1403 		bCan = sal_True;
1404 	}
1405 	else if(bMakeLines && 1L == nPolygonCount)
1406 	{
1407 		// #i69172# ..or with at least 2 edges (curves or lines)
1408 		const basegfx::B2DPolygon aPolygon(rPpolyPolygon.getB2DPolygon(0L));
1409 		const sal_uInt32 nPointCount(aPolygon.count());
1410 
1411 		if(nPointCount > 2L)
1412 		{
1413 			bCan = sal_True;
1414 		}
1415 	}
1416 
1417 	return bCan;
1418 }
1419 
ImpCanDismantle(const SdrObject * pObj,sal_Bool bMakeLines) const1420 sal_Bool SdrEditView::ImpCanDismantle(const SdrObject* pObj, sal_Bool bMakeLines) const
1421 {
1422 	sal_Bool bOtherObjs(sal_False);    // sal_True=andere Objekte ausser PathObj's vorhanden
1423 	sal_Bool bMin1PolyPoly(sal_False); // sal_True=mind. 1 PolyPolygon mit mehr als ein Polygon vorhanden
1424 	SdrObjList* pOL = pObj->GetSubList();
1425 
1426 	if(pOL)
1427 	{
1428 		// Aha, Gruppenobjekt. Also alle Member ansehen.
1429 		// Alle muessen PathObjs sein !
1430 		SdrObjListIter aIter(*pOL, IM_DEEPNOGROUPS);
1431 
1432 		while(aIter.IsMore() && !bOtherObjs)
1433 		{
1434 			const SdrObject* pObj1 = aIter.Next();
1435 			const SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj1);
1436 
1437 			if(pPath)
1438 			{
1439 				if(ImpCanDismantle(pPath->GetPathPoly(), bMakeLines))
1440 				{
1441 					bMin1PolyPoly = sal_True;
1442 				}
1443 
1444 				SdrObjTransformInfoRec aInfo;
1445 				pObj1->TakeObjInfo(aInfo);
1446 
1447 				if(!aInfo.bCanConvToPath)
1448 				{
1449 					// Passiert z.B. im Falle Fontwork (Joe, 28-11-95)
1450 					bOtherObjs = sal_True;
1451 				}
1452 			}
1453 			else
1454 			{
1455 				bOtherObjs = sal_True;
1456 			}
1457 		}
1458 	}
1459 	else
1460 	{
1461 		const SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj);
1462 		const SdrObjCustomShape* pCustomShape = PTR_CAST(SdrObjCustomShape, pObj);
1463 
1464 		// #i37011#
1465 		if(pPath)
1466 		{
1467 			if(ImpCanDismantle(pPath->GetPathPoly(),bMakeLines))
1468 			{
1469 				bMin1PolyPoly = sal_True;
1470 			}
1471 
1472 			SdrObjTransformInfoRec aInfo;
1473 			pObj->TakeObjInfo(aInfo);
1474 
1475 			// #69711 : new condition IsLine() to be able to break simple Lines
1476 			if(!(aInfo.bCanConvToPath || aInfo.bCanConvToPoly) && !pPath->IsLine())
1477 			{
1478 				// Passiert z.B. im Falle Fontwork (Joe, 28-11-95)
1479 				bOtherObjs = sal_True;
1480 			}
1481 		}
1482 		else if(pCustomShape)
1483 		{
1484 			if(bMakeLines)
1485 			{
1486 				// allow break command
1487 				bMin1PolyPoly = sal_True;
1488 			}
1489 		}
1490 		else
1491 		{
1492 			bOtherObjs = sal_True;
1493 		}
1494 	}
1495 	return bMin1PolyPoly && !bOtherObjs;
1496 }
1497 
ImpDismantleOneObject(const SdrObject * pObj,SdrObjList & rOL,sal_uIntPtr & rPos,SdrPageView * pPV,sal_Bool bMakeLines)1498 void SdrEditView::ImpDismantleOneObject(const SdrObject* pObj, SdrObjList& rOL, sal_uIntPtr& rPos, SdrPageView* pPV, sal_Bool bMakeLines)
1499 {
1500 	const SdrPathObj* pSrcPath = PTR_CAST(SdrPathObj, pObj);
1501 	const SdrObjCustomShape* pCustomShape = PTR_CAST(SdrObjCustomShape, pObj);
1502 
1503 	const bool bUndo = IsUndoEnabled();
1504 
1505 	if(pSrcPath)
1506 	{
1507 		// #i74631# redesigned due to XpolyPolygon removal and explicit constructors
1508 		SdrObject* pLast = 0; // fuer die Zuweisung des OutlinerParaObject
1509 		const basegfx::B2DPolyPolygon& rPolyPolygon(pSrcPath->GetPathPoly());
1510 		const sal_uInt32 nPolyCount(rPolyPolygon.count());
1511 
1512 		for(sal_uInt32 a(0); a < nPolyCount; a++)
1513 		{
1514 			const basegfx::B2DPolygon& rCandidate(rPolyPolygon.getB2DPolygon(a));
1515 			const sal_uInt32 nPointCount(rCandidate.count());
1516 
1517 			if(!bMakeLines || nPointCount < 2)
1518 			{
1519 				SdrPathObj* pPath = new SdrPathObj((SdrObjKind)pSrcPath->GetObjIdentifier(), basegfx::B2DPolyPolygon(rCandidate));
1520 				ImpCopyAttributes(pSrcPath, pPath);
1521 				pLast = pPath;
1522 				SdrInsertReason aReason(SDRREASON_VIEWCALL, pSrcPath);
1523 				rOL.InsertObject(pPath, rPos, &aReason);
1524 				if( bUndo )
1525 					AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, sal_True));
1526 				MarkObj(pPath, pPV, sal_False, sal_True);
1527 				rPos++;
1528 			}
1529 			else
1530 			{
1531 				const sal_uInt32 nLoopCount(rCandidate.isClosed() ? nPointCount : nPointCount - 1);
1532 
1533 				for(sal_uInt32 b(0); b < nLoopCount; b++)
1534 				{
1535 					SdrObjKind eKind(OBJ_PLIN);
1536 					basegfx::B2DPolygon aNewPolygon;
1537 					const sal_uInt32 nNextIndex((b + 1) % nPointCount);
1538 
1539 					aNewPolygon.append(rCandidate.getB2DPoint(b));
1540 
1541 					if(rCandidate.areControlPointsUsed())
1542 					{
1543 						aNewPolygon.appendBezierSegment(
1544 							rCandidate.getNextControlPoint(b),
1545 							rCandidate.getPrevControlPoint(nNextIndex),
1546 							rCandidate.getB2DPoint(nNextIndex));
1547 						eKind = OBJ_PATHLINE;
1548 					}
1549 					else
1550 					{
1551 						aNewPolygon.append(rCandidate.getB2DPoint(nNextIndex));
1552 					}
1553 
1554 					SdrPathObj* pPath = new SdrPathObj(eKind, basegfx::B2DPolyPolygon(aNewPolygon));
1555 					ImpCopyAttributes(pSrcPath, pPath);
1556 					pLast = pPath;
1557 					SdrInsertReason aReason(SDRREASON_VIEWCALL, pSrcPath);
1558 					rOL.InsertObject(pPath, rPos, &aReason);
1559 					if( bUndo )
1560 						AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, sal_True));
1561 					MarkObj(pPath, pPV, sal_False, sal_True);
1562 					rPos++;
1563 				}
1564 			}
1565 		}
1566 
1567 		if(pLast && pSrcPath->GetOutlinerParaObject())
1568 		{
1569 			pLast->SetOutlinerParaObject(new OutlinerParaObject(*pSrcPath->GetOutlinerParaObject()));
1570 		}
1571 	}
1572 	else if(pCustomShape)
1573 	{
1574 		if(bMakeLines)
1575 		{
1576 			// break up custom shape
1577 			const SdrObject* pReplacement = pCustomShape->GetSdrObjectFromCustomShape();
1578 
1579 			if(pReplacement)
1580 			{
1581 				SdrObject* pCandidate = pReplacement->Clone();
1582 				DBG_ASSERT(pCandidate, "SdrEditView::ImpDismantleOneObject: Could not clone SdrObject (!)");
1583 				pCandidate->SetModel(pCustomShape->GetModel());
1584 
1585 				if(((SdrShadowItem&)pCustomShape->GetMergedItem(SDRATTR_SHADOW)).GetValue())
1586 				{
1587 					if(pReplacement->ISA(SdrObjGroup))
1588 					{
1589 						pCandidate->SetMergedItem(SdrShadowItem(sal_True));
1590 					}
1591 				}
1592 
1593 				SdrInsertReason aReason(SDRREASON_VIEWCALL, pCustomShape);
1594 				rOL.InsertObject(pCandidate, rPos, &aReason);
1595 				if( bUndo )
1596 					AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pCandidate, true));
1597 				MarkObj(pCandidate, pPV, sal_False, sal_True);
1598 
1599 				if(pCustomShape->HasText() && !pCustomShape->IsTextPath())
1600 				{
1601 					// #i37011# also create a text object and add at rPos + 1
1602 					SdrTextObj* pTextObj = (SdrTextObj*)SdrObjFactory::MakeNewObject(
1603 						pCustomShape->GetObjInventor(), OBJ_TEXT, 0L, pCustomShape->GetModel());
1604 
1605 					// Copy text content
1606 					OutlinerParaObject* pParaObj = pCustomShape->GetOutlinerParaObject();
1607 					if(pParaObj)
1608 					{
1609 						pTextObj->NbcSetOutlinerParaObject(new OutlinerParaObject(*pParaObj));
1610 					}
1611 
1612 					// copy all attributes
1613 					SfxItemSet aTargetItemSet(pCustomShape->GetMergedItemSet());
1614 
1615 					// clear fill and line style
1616 					aTargetItemSet.Put(XLineStyleItem(XLINE_NONE));
1617 					aTargetItemSet.Put(XFillStyleItem(XFILL_NONE));
1618 
1619 					// get the text bounds and set at text object
1620 					Rectangle aTextBounds = pCustomShape->GetSnapRect();
1621 					if(pCustomShape->GetTextBounds(aTextBounds))
1622 					{
1623 						pTextObj->SetSnapRect(aTextBounds);
1624 					}
1625 
1626 					// if rotated, copy GeoStat, too.
1627 					const GeoStat& rSourceGeo = pCustomShape->GetGeoStat();
1628 					if(rSourceGeo.nDrehWink)
1629 					{
1630 						pTextObj->NbcRotate(
1631 							pCustomShape->GetSnapRect().Center(), rSourceGeo.nDrehWink,
1632 							rSourceGeo.nSin, rSourceGeo.nCos);
1633 					}
1634 
1635 					// set modified ItemSet at text object
1636 					pTextObj->SetMergedItemSet(aTargetItemSet);
1637 
1638 					// insert object
1639 					rOL.InsertObject(pTextObj, rPos + 1, &aReason);
1640 					if( bUndo )
1641 						AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pTextObj, true));
1642 					MarkObj(pTextObj, pPV, sal_False, sal_True);
1643 				}
1644 			}
1645 		}
1646 	}
1647 }
1648 
DismantleMarkedObjects(sal_Bool bMakeLines)1649 void SdrEditView::DismantleMarkedObjects(sal_Bool bMakeLines)
1650 {
1651 	//sal_uInt32 nCnt(0);
1652 	// Temporaere Marklist
1653 	SdrMarkList aRemoveMerker;
1654 
1655 	SortMarkedObjects();
1656 
1657 	const bool bUndo = IsUndoEnabled();
1658 
1659 	if( bUndo )
1660 	{
1661 		// Der Comment wird spaeter zusammengebaut
1662 		BegUndo(String(), String(),
1663 			bMakeLines ? SDRREPFUNC_OBJ_DISMANTLE_LINES : SDRREPFUNC_OBJ_DISMANTLE_POLYS);
1664 	}
1665 
1666 	sal_uIntPtr nm;
1667 	sal_uIntPtr nAnz=GetMarkedObjectCount();
1668 	SdrObjList* pOL0=NULL;
1669 	for (nm=nAnz; nm>0;) {
1670 		nm--;
1671 		SdrMark* pM=GetSdrMarkByIndex(nm);
1672 		SdrObject* pObj=pM->GetMarkedSdrObj();
1673 		SdrPageView* pPV=pM->GetPageView();
1674 		SdrObjList* pOL=pObj->GetObjList();
1675 		if (pOL!=pOL0) { pOL0=pOL; pObj->GetOrdNum(); } // sicherstellen, dass OrdNums stimmen!
1676 		if (ImpCanDismantle(pObj,bMakeLines)) {
1677 			aRemoveMerker.InsertEntry(SdrMark(pObj,pM->GetPageView()));
1678 			sal_uIntPtr nPos0=pObj->GetOrdNumDirect();
1679 			sal_uIntPtr nPos=nPos0+1;
1680 			SdrObjList* pSubList=pObj->GetSubList();
1681 			if (pSubList!=NULL && !pObj->Is3DObj()) {
1682 				SdrObjListIter aIter(*pSubList,IM_DEEPNOGROUPS);
1683 				while (aIter.IsMore()) {
1684 					const SdrObject* pObj1=aIter.Next();
1685 					ImpDismantleOneObject(pObj1,*pOL,nPos,pPV,bMakeLines);
1686 				}
1687 			} else {
1688 				ImpDismantleOneObject(pObj,*pOL,nPos,pPV,bMakeLines);
1689 			}
1690 			if( bUndo )
1691 				AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj,sal_True));
1692 			pOL->RemoveObject(nPos0);
1693 
1694 			if( !bUndo )
1695 				SdrObject::Free(pObj);
1696 		}
1697 	}
1698 
1699 	if( bUndo )
1700 	{
1701 		// UndoComment aus den tatsaechlich verwendeten Objekten zusammenbauen
1702 		SetUndoComment(ImpGetResStr(bMakeLines?STR_EditDismantle_Lines:STR_EditDismantle_Polys),aRemoveMerker.GetMarkDescription());
1703 		// die tatsaechlich verwendeten Objekten aus der Liste entfernen
1704 		EndUndo();
1705 	}
1706 }
1707 
1708 ////////////////////////////////////////////////////////////////////////////////////////////////////
1709 //
1710 //   #### ####   ###  #   # ####
1711 //  #     #   # #   # #   # #   #
1712 //  #  ## ####  #   # #   # ####
1713 //  #   # #   # #   # #   # #
1714 //   #### #   #  ###   ###  #
1715 //
1716 ////////////////////////////////////////////////////////////////////////////////////////////////////
1717 
GroupMarked(const SdrObject * pUserGrp)1718 void SdrEditView::GroupMarked(const SdrObject* pUserGrp)
1719 {
1720 	if (AreObjectsMarked())
1721 	{
1722 		SortMarkedObjects();
1723 
1724 		const bool bUndo = IsUndoEnabled();
1725 		if( bUndo )
1726 		{
1727 			BegUndo(ImpGetResStr(STR_EditGroup),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_GROUP);
1728 
1729 			const sal_uIntPtr nAnz = GetMarkedObjectCount();
1730 			for(sal_uIntPtr nm = nAnz; nm>0; )
1731 			{
1732 				// UndoActions fuer alle betroffenen Objekte anlegen
1733 				nm--;
1734 				SdrMark* pM=GetSdrMarkByIndex(nm);
1735 				SdrObject* pObj = pM->GetMarkedSdrObj();
1736 					std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pObj ) );
1737 					AddUndoActions( vConnectorUndoActions );
1738 					AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject( *pObj ));
1739 			}
1740 		}
1741 
1742 		SdrMarkList aNewMark;
1743 		SdrPageView* pPV = GetSdrPageView();
1744 
1745 		if(pPV)
1746 		{
1747 			SdrObjList* pAktLst=pPV->GetObjList();
1748 			SdrObjList* pSrcLst=pAktLst;
1749 			SdrObjList* pSrcLst0=pSrcLst;
1750 			SdrPage*    pPage=pPV->GetPage();
1751 			// sicherstellen, dass die OrdNums stimmen
1752 			if (pSrcLst->IsObjOrdNumsDirty())
1753 				pSrcLst->RecalcObjOrdNums();
1754 			SdrObject*  pGrp=NULL;
1755 			SdrObject*  pRefObj=NULL; // Referenz fuer InsertReason (-> rumankern im Writer)
1756 			SdrObject*  pRefObj1=NULL; // Referenz fuer InsertReason (-> rumankern im Writer)
1757 			SdrObjList* pDstLst=NULL;
1758 			// Falls alle markierten Objekte aus Fremden Obj-Listen
1759 			// kommen, kommt das Gruppenobjekt an das Ende der Liste.
1760 			sal_uIntPtr       nInsPos=pSrcLst->GetObjCount();
1761 			sal_Bool    bNeedInsPos=sal_True;
1762 			for (sal_uIntPtr nm=GetMarkedObjectCount(); nm>0;)
1763 			{
1764 				nm--;
1765 				SdrMark* pM=GetSdrMarkByIndex(nm);
1766 				if (pM->GetPageView()==pPV)
1767 				{
1768 					if (pGrp==NULL)
1769 					{
1770 						if (pUserGrp!=NULL)
1771 							pGrp=pUserGrp->Clone();
1772 						if (pGrp==NULL)
1773 							pGrp=new SdrObjGroup;
1774 						pDstLst=pGrp->GetSubList();
1775 						DBG_ASSERT(pDstLst!=NULL,"Angebliches Gruppenobjekt liefert keine Objektliste");
1776 					}
1777 					SdrObject* pObj=pM->GetMarkedSdrObj();
1778 					pSrcLst=pObj->GetObjList();
1779 					if (pSrcLst!=pSrcLst0)
1780 					{
1781 						if (pSrcLst->IsObjOrdNumsDirty())
1782 							pSrcLst->RecalcObjOrdNums();
1783 					}
1784 					sal_Bool bForeignList=pSrcLst!=pAktLst;
1785 					sal_Bool bGrouped=pSrcLst!=pPage;
1786 					if (!bForeignList && bNeedInsPos)
1787 					{
1788 						nInsPos=pObj->GetOrdNum(); // ua, damit sind alle ObjOrdNum der Page gesetzt
1789 						nInsPos++;
1790 						bNeedInsPos=sal_False;
1791 					}
1792 					pSrcLst->RemoveObject(pObj->GetOrdNumDirect());
1793 					if (!bForeignList)
1794 						nInsPos--; // InsertPos korregieren
1795 					SdrInsertReason aReason(SDRREASON_VIEWCALL);
1796 					pDstLst->InsertObject(pObj,0,&aReason);
1797 					GetMarkedObjectListWriteAccess().DeleteMark(nm);
1798 					if (pRefObj1==NULL)
1799 						pRefObj1=pObj; // Das oberste sichtbare Objekt
1800 					if (!bGrouped)
1801 					{
1802 						if (pRefObj==NULL)
1803 							pRefObj=pObj; // Das oberste sichtbare nicht gruppierte Objekt
1804 					}
1805 					pSrcLst0=pSrcLst;
1806 				}
1807 			}
1808 			if (pRefObj==NULL)
1809 				pRefObj=pRefObj1;
1810 			if (pGrp!=NULL)
1811 			{
1812 				aNewMark.InsertEntry(SdrMark(pGrp,pPV));
1813 				sal_uIntPtr nAnz=pDstLst->GetObjCount();
1814 				SdrInsertReason aReason(SDRREASON_VIEWCALL,pRefObj);
1815 				pAktLst->InsertObject(pGrp,nInsPos,&aReason);
1816 				if( bUndo )
1817 				{
1818 					AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pGrp,true)); // Kein Recalc!
1819 					for (sal_uIntPtr no=0; no<nAnz; no++)
1820 					{
1821 						AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pDstLst->GetObj(no)));
1822 					}
1823 				}
1824 			}
1825 		}
1826 		GetMarkedObjectListWriteAccess().Merge(aNewMark);
1827 		MarkListHasChanged();
1828 
1829 		if( bUndo )
1830 			EndUndo();
1831 	}
1832 }
1833 
1834 ////////////////////////////////////////////////////////////////////////////////////////////////////
1835 //
1836 //  #   # #   #  #### ####   ###  #   # ####
1837 //  #   # ##  # #     #   # #   # #   # #   #
1838 //  #   # # # # #  ## ####  #   # #   # ####
1839 //  #   # #  ## #   # #   # #   # #   # #
1840 //   ###  #   #  #### #   #  ###   ###  #
1841 //
1842 ////////////////////////////////////////////////////////////////////////////////////////////////////
1843 
UnGroupMarked()1844 void SdrEditView::UnGroupMarked()
1845 {
1846 	SdrMarkList aNewMark;
1847 
1848 	const bool bUndo = IsUndoEnabled();
1849 	if( bUndo )
1850 		BegUndo(String(), String(), SDRREPFUNC_OBJ_UNGROUP);
1851 
1852 	sal_uIntPtr nCount=0;
1853 	XubString aName1;
1854 	XubString aName;
1855 	sal_Bool bNameOk=sal_False;
1856 	for (sal_uIntPtr nm=GetMarkedObjectCount(); nm>0;) {
1857 		nm--;
1858 		SdrMark* pM=GetSdrMarkByIndex(nm);
1859 		SdrObject* pGrp=pM->GetMarkedSdrObj();
1860 		SdrObjList* pSrcLst=pGrp->GetSubList();
1861 		if (pSrcLst!=NULL) {
1862 			nCount++;
1863 			if (nCount==1) {
1864 				pGrp->TakeObjNameSingul(aName);  // Bezeichnung der Gruppe holen
1865 				pGrp->TakeObjNamePlural(aName1); // Bezeichnung der Gruppe holen
1866 				bNameOk=sal_True;
1867 			} else {
1868 				if (nCount==2) aName=aName1; // Pluralname setzen
1869 				if (bNameOk) {
1870 					XubString aStr;
1871 					pGrp->TakeObjNamePlural(aStr); // Bezeichnung der Gruppe holen
1872 
1873 					if(!aStr.Equals(aName))
1874 						bNameOk = sal_False;
1875 				}
1876 			}
1877 			sal_uIntPtr nDstCnt=pGrp->GetOrdNum();
1878 			SdrObjList* pDstLst=pM->GetPageView()->GetObjList();
1879 
1880 			// FIRST move contained objects to parent of group, so that
1881 			// the contained objects are NOT migrated to the UNDO-ItemPool
1882 			// when AddUndo(new SdrUndoDelObj(*pGrp)) is called.
1883 			sal_uIntPtr nAnz=pSrcLst->GetObjCount();
1884 			sal_uIntPtr no;
1885 
1886 			if( bUndo )
1887 			{
1888 				for (no=nAnz; no>0;)
1889 				{
1890 					no--;
1891 					SdrObject* pObj=pSrcLst->GetObj(no);
1892 					AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject(*pObj));
1893 				}
1894 			}
1895 			for (no=0; no<nAnz; no++)
1896 			{
1897 				SdrObject* pObj=pSrcLst->RemoveObject(0);
1898 				SdrInsertReason aReason(SDRREASON_VIEWCALL,pGrp);
1899 				pDstLst->InsertObject(pObj,nDstCnt,&aReason);
1900 				if( bUndo )
1901 					AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pObj,true));
1902 				nDstCnt++;
1903 				// Kein SortCheck beim einfuegen in die MarkList, denn das
1904 				// wuerde wg. pObj->GetOrdNum() jedesmal ein RecalcOrdNums()
1905 				// provozieren:
1906 				aNewMark.InsertEntry(SdrMark(pObj,pM->GetPageView()),sal_False);
1907 			}
1908 
1909 			if( bUndo )
1910 			{
1911 				// Now it is safe to add the delete-UNDO which trigers the
1912 				// MigrateItemPool now only for itself, not for the subobjects.
1913 				// nDstCnt is right, because previous inserts move group
1914 				// object deeper and increase nDstCnt.
1915 				AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pGrp));
1916 			}
1917 			pDstLst->RemoveObject(nDstCnt);
1918 
1919 			if( !bUndo )
1920 				SdrObject::Free(pGrp);
1921 
1922 			GetMarkedObjectListWriteAccess().DeleteMark(nm);
1923 		}
1924 	}
1925 	if (nCount!=0)
1926 	{
1927 		if (!bNameOk)
1928 			aName=ImpGetResStr(STR_ObjNamePluralGRUP); // Oberbegriff Gruppenobjekte verwenden, wenn verschiedene Objekte.
1929 		SetUndoComment(ImpGetResStr(STR_EditUngroup),aName);
1930 	}
1931 
1932 	if( bUndo )
1933 		EndUndo();
1934 
1935 	if (nCount!=0)
1936 	{
1937 		GetMarkedObjectListWriteAccess().Merge(aNewMark,sal_True); // Durch das obige Einsortieren ist aNewMark genau verkehrtherum
1938 		MarkListHasChanged();
1939 	}
1940 }
1941 
1942 ////////////////////////////////////////////////////////////////////////////////////////////////////
1943 //
1944 //   ###   ###  #   # #   # ##### ####  #####   #####  ###    ####   ###  #  #   #
1945 //  #   # #   # ##  # #   # #     #   #   #       #   #   #   #   # #   # #   # #
1946 //  #     #   # # # # #   # ####  ####    #       #   #   #   ####  #   # #    #
1947 //  #   # #   # #  ##  # #  #     #   #   #       #   #   #   #     #   # #    #
1948 //   ###   ###  #   #   #   ##### #   #   #       #    ###    #      ###  #### #
1949 //
1950 ////////////////////////////////////////////////////////////////////////////////////////////////////
1951 
ImpConvertOneObj(SdrObject * pObj,sal_Bool bPath,sal_Bool bLineToArea)1952 SdrObject* SdrEditView::ImpConvertOneObj(SdrObject* pObj, sal_Bool bPath, sal_Bool bLineToArea)
1953 {
1954 	SdrObject* pNewObj = pObj->ConvertToPolyObj(bPath, bLineToArea);
1955 	if (pNewObj!=NULL)
1956 	{
1957 		SdrObjList* pOL=pObj->GetObjList();
1958 		DBG_ASSERT(pOL!=NULL,"ConvertTo: Obj liefert keine ObjList");
1959 		if (pOL!=NULL)
1960 		{
1961 			const bool bUndo = IsUndoEnabled();
1962 			if( bUndo )
1963 				AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoReplaceObject(*pObj,*pNewObj));
1964 
1965 			pOL->ReplaceObject(pNewObj,pObj->GetOrdNum());
1966 
1967 			if( !bUndo )
1968 				SdrObject::Free(pObj);
1969 		}
1970 	}
1971 	return pNewObj;
1972 }
1973 
ImpConvertTo(sal_Bool bPath,sal_Bool bLineToArea)1974 void SdrEditView::ImpConvertTo(sal_Bool bPath, sal_Bool bLineToArea)
1975 {
1976 	sal_Bool bMrkChg=sal_False;
1977 	sal_Bool bModChg=sal_False;
1978 	if (AreObjectsMarked()) {
1979 		sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
1980 		sal_uInt16 nDscrID=0;
1981 		if(bLineToArea)
1982 		{
1983 			if(nMarkAnz == 1)
1984 				nDscrID = STR_EditConvToContour;
1985 			else
1986 				nDscrID = STR_EditConvToContours;
1987 
1988 			BegUndo(ImpGetResStr(nDscrID), GetDescriptionOfMarkedObjects());
1989 		}
1990 		else
1991 		{
1992 			if (bPath) {
1993 				if (nMarkAnz==1) nDscrID=STR_EditConvToCurve;
1994 				else nDscrID=STR_EditConvToCurves;
1995 				BegUndo(ImpGetResStr(nDscrID),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_CONVERTTOPATH);
1996 			} else {
1997 				if (nMarkAnz==1) nDscrID=STR_EditConvToPoly;
1998 				else nDscrID=STR_EditConvToPolys;
1999 				BegUndo(ImpGetResStr(nDscrID),GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_CONVERTTOPOLY);
2000 			}
2001 		}
2002 		for (sal_uIntPtr nm=nMarkAnz; nm>0;) {
2003 			nm--;
2004 			SdrMark* pM=GetSdrMarkByIndex(nm);
2005 			SdrObject* pObj=pM->GetMarkedSdrObj();
2006 			SdrPageView* pPV=pM->GetPageView();
2007 			if (pObj->IsGroupObject() && !pObj->Is3DObj()) {
2008 				SdrObject* pGrp=pObj;
2009 				SdrObjListIter aIter(*pGrp,IM_DEEPNOGROUPS);
2010 				while (aIter.IsMore()) {
2011 					pObj=aIter.Next();
2012 					if (ImpConvertOneObj(pObj,bPath,bLineToArea)) bModChg=sal_True;
2013 				}
2014 			} else {
2015 				SdrObject* pNewObj=ImpConvertOneObj(pObj,bPath,bLineToArea);
2016 				if (pNewObj!=NULL) {
2017 					bModChg=sal_True;
2018 					bMrkChg=sal_True;
2019 					GetMarkedObjectListWriteAccess().ReplaceMark(SdrMark(pNewObj,pPV),nm);
2020 				}
2021 			}
2022 		}
2023 		EndUndo();
2024 		if (bMrkChg) AdjustMarkHdl();
2025 		if (bMrkChg) MarkListHasChanged();
2026 	}
2027 }
2028 
ConvertMarkedToPathObj(sal_Bool bLineToArea)2029 void SdrEditView::ConvertMarkedToPathObj(sal_Bool bLineToArea)
2030 {
2031 	ImpConvertTo(sal_True, bLineToArea);
2032 }
2033 
ConvertMarkedToPolyObj(sal_Bool bLineToArea)2034 void SdrEditView::ConvertMarkedToPolyObj(sal_Bool bLineToArea)
2035 {
2036 	ImpConvertTo(sal_False, bLineToArea);
2037 }
2038 
2039 ////////////////////////////////////////////////////////////////////////////////////////////////////
2040 //
2041 //  #   # ##### #####  ###  ##### # #    #####      # #   # ####   ###  ####  #####
2042 //  ## ## #       #   #   # #     # #    #          # ## ## #   # #   # #   #   #
2043 //  # # # ####    #   ##### ###   # #    ####  ###  # # # # ####  #   # ####    #
2044 //  #   # #       #   #   # #     # #    #          # #   # #     #   # #   #   #
2045 //  #   # #####   #   #   # #     # #### #####      # #   # #      ###  #   #   #
2046 //
2047 ////////////////////////////////////////////////////////////////////////////////////////////////////
2048 
DoImportMarkedMtf(SvdProgressInfo * pProgrInfo)2049 void SdrEditView::DoImportMarkedMtf(SvdProgressInfo *pProgrInfo)
2050 {
2051 	const bool bUndo = IsUndoEnabled();
2052 
2053 	if( bUndo )
2054 		BegUndo(String(), String(), SDRREPFUNC_OBJ_IMPORTMTF);
2055 
2056 	SortMarkedObjects();
2057 	SdrMarkList aForTheDescription;
2058 	SdrMarkList aNewMarked;
2059 	sal_uIntPtr nAnz=GetMarkedObjectCount();
2060 
2061 	for (sal_uIntPtr nm=nAnz; nm>0;)
2062 	{ // Undo Objekte fuer alle neuen Objekte erzeugen
2063 		// zwischen den Metafiles auf Abbruch testen
2064 		if( pProgrInfo != NULL )
2065 		{
2066 			pProgrInfo->SetNextObject();
2067 			if(!pProgrInfo->ReportActions(0))
2068 				break;
2069 		}
2070 
2071 		nm--;
2072 		SdrMark*     pM=GetSdrMarkByIndex(nm);
2073 		SdrObject*   pObj=pM->GetMarkedSdrObj();
2074 		SdrPageView* pPV=pM->GetPageView();
2075 		SdrObjList*  pOL=pObj->GetObjList();
2076 		sal_uIntPtr        nInsPos=pObj->GetOrdNum()+1;
2077 		SdrGrafObj*  pGraf=PTR_CAST(SdrGrafObj,pObj);
2078 		SdrOle2Obj*  pOle2=PTR_CAST(SdrOle2Obj,pObj);
2079 		sal_uIntPtr        nInsAnz=0;
2080         Rectangle aLogicRect;
2081 
2082 		if(pGraf && (pGraf->HasGDIMetaFile() || pGraf->isEmbeddedSvg()))
2083         {
2084             GDIMetaFile aMetaFile;
2085 
2086             if(pGraf->HasGDIMetaFile())
2087             {
2088                 aMetaFile = pGraf->GetTransformedGraphic(SDRGRAFOBJ_TRANSFORMATTR_COLOR|SDRGRAFOBJ_TRANSFORMATTR_MIRROR).GetGDIMetaFile();
2089             }
2090             else if(pGraf->isEmbeddedSvg())
2091             {
2092                 aMetaFile = pGraf->getMetafileFromEmbeddedSvg();
2093             }
2094 
2095             if(aMetaFile.GetActionCount())
2096             {
2097                 aLogicRect = pGraf->GetLogicRect();
2098                 ImpSdrGDIMetaFileImport aFilter(*pMod, pObj->GetLayer(), aLogicRect);
2099                 nInsAnz = aFilter.DoImport(aMetaFile, *pOL, nInsPos, pProgrInfo);
2100             }
2101         }
2102         if ( pOle2!=NULL && pOle2->GetGraphic() )
2103 		{
2104             aLogicRect = pOle2->GetLogicRect();
2105 			ImpSdrGDIMetaFileImport aFilter(*pMod, pObj->GetLayer(), aLogicRect);
2106             nInsAnz = aFilter.DoImport(pOle2->GetGraphic()->GetGDIMetaFile(), *pOL, nInsPos, pProgrInfo);
2107 		}
2108 		if (nInsAnz!=0)
2109 		{
2110             // transformation
2111             GeoStat aGeoStat(pGraf ? pGraf->GetGeoStat() : pOle2->GetGeoStat());
2112             sal_uIntPtr nObj=nInsPos;
2113 
2114 	        if(aGeoStat.nShearWink)
2115             {
2116                 aGeoStat.RecalcTan();
2117             }
2118 
2119             if(aGeoStat.nDrehWink)
2120             {
2121 	            aGeoStat.RecalcSinCos();
2122             }
2123 
2124             for (sal_uIntPtr i=0; i<nInsAnz; i++)
2125 			{
2126                 if( bUndo )
2127 					AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pOL->GetObj(nObj)));
2128 
2129 				// Neue MarkList pflegen
2130                 SdrObject* pCandidate = pOL->GetObj(nObj);
2131 
2132                 // apply original transformation
2133 	            if(aGeoStat.nShearWink)
2134                 {
2135                     pCandidate->NbcShear(aLogicRect.TopLeft(), aGeoStat.nShearWink, aGeoStat.nTan, false);
2136                 }
2137 
2138 	            if(aGeoStat.nDrehWink)
2139                 {
2140                     pCandidate->NbcRotate(aLogicRect.TopLeft(), aGeoStat.nDrehWink, aGeoStat.nSin, aGeoStat.nCos);
2141                 }
2142 
2143                 SdrMark aNewMark(pCandidate, pPV);
2144 				aNewMarked.InsertEntry(aNewMark);
2145 
2146 				nObj++;
2147 			}
2148 			aForTheDescription.InsertEntry(*pM);
2149 
2150 			if( bUndo )
2151 				AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj));
2152 
2153 			// Objekt aus selektion loesen und loeschen
2154 			GetMarkedObjectListWriteAccess().DeleteMark(TryToFindMarkedObject(pObj));
2155 			pOL->RemoveObject(nInsPos-1);
2156 
2157 			if( !bUndo )
2158 				SdrObject::Free(pObj);
2159 		}
2160 	}
2161 
2162 	// MarkObj... fehlt... jetzt nicht mehr (AW)
2163 	if(aNewMarked.GetMarkCount())
2164 	{
2165 		// Neue Selektion bilden
2166 		for(sal_uIntPtr a(0); a < aNewMarked.GetMarkCount(); a++)
2167 		{
2168 			GetMarkedObjectListWriteAccess().InsertEntry(*aNewMarked.GetMark(a));
2169 		}
2170 
2171 		SortMarkedObjects();
2172 	}
2173 
2174 	if( bUndo )
2175 	{
2176 		SetUndoComment(ImpGetResStr(STR_EditImportMtf),aForTheDescription.GetMarkDescription());
2177 		EndUndo();
2178 	}
2179 }
2180 
2181