xref: /trunk/main/svx/source/svdraw/svdogrp.cxx (revision a5258243)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 #include <sfx2/linkmgr.hxx>
31 
32 #include <ucbhelper/content.hxx>
33 #include <ucbhelper/contentbroker.hxx>
34 #include <unotools/datetime.hxx>
35 
36 #include <svx/svdogrp.hxx>
37 
38 #include <sfx2/lnkbase.hxx>
39 #include <tools/urlobj.hxx>
40 
41 #include <svl/urihelper.hxx>
42 
43 #include <svx/xpool.hxx>
44 #include <svx/xpoly.hxx>
45 
46 #include <svx/svdmodel.hxx>
47 #include <svx/svdpage.hxx>
48 #include "svx/svditer.hxx"
49 #include <svx/svdobj.hxx>
50 #include <svx/svdtrans.hxx>
51 #include <svx/svdetc.hxx>
52 #include <svx/svdattrx.hxx>  // NotPersistItems
53 #include <svx/svdoedge.hxx>  // #32383# Die Verbinder nach Move nochmal anbroadcasten
54 #include "svx/svdglob.hxx"   // StringCache
55 #include "svx/svdstr.hrc"    // Objektname
56 
57 #include <svx/svxids.hrc>
58 #include <svl/whiter.hxx>
59 #include <svx/svdpool.hxx>
60 #include <svx/sdr/properties/groupproperties.hxx>
61 
62 // #110094#
63 #include <svx/sdr/contact/viewcontactofgroup.hxx>
64 #include <basegfx/range/b2drange.hxx>
65 #include <basegfx/polygon/b2dpolygontools.hxx>
66 #include <basegfx/polygon/b2dpolygon.hxx>
67 
68 ////////////////////////////////////////////////////////////////////////////////////////////////////
69 //
70 //   @@@@  @@@@@  @@@@@@   @@@@  @@@@@   @@@@  @@  @@ @@@@@
71 //  @@  @@ @@  @@     @@  @@     @@  @@ @@  @@ @@  @@ @@  @@
72 //  @@  @@ @@@@@      @@  @@ @@@ @@@@@  @@  @@ @@  @@ @@@@@
73 //  @@  @@ @@  @@ @@  @@  @@  @@ @@  @@ @@  @@ @@  @@ @@
74 //   @@@@  @@@@@   @@@@    @@@@@ @@  @@  @@@@   @@@@  @@
75 //
76 ////////////////////////////////////////////////////////////////////////////////////////////////////
77 
78 //////////////////////////////////////////////////////////////////////////////
79 // BaseProperties section
80 
81 sdr::properties::BaseProperties* SdrObjGroup::CreateObjectSpecificProperties()
82 {
83 	return new sdr::properties::GroupProperties(*this);
84 }
85 
86 //////////////////////////////////////////////////////////////////////////////
87 // #110094# DrawContact section
88 
89 sdr::contact::ViewContact* SdrObjGroup::CreateObjectSpecificViewContact()
90 {
91 	return new sdr::contact::ViewContactOfGroup(*this);
92 }
93 
94 //////////////////////////////////////////////////////////////////////////////
95 
96 TYPEINIT1(SdrObjGroup,SdrObject);
97 
98 SdrObjGroup::SdrObjGroup()
99 {
100 	pSub=new SdrObjList(NULL,NULL);
101 	pSub->SetOwnerObj(this);
102 	pSub->SetListKind(SDROBJLIST_GROUPOBJ);
103 	bRefPoint=sal_False;
104 	nDrehWink=0;
105 	nShearWink=0;
106 	bClosedObj=sal_False;
107 }
108 
109 
110 SdrObjGroup::~SdrObjGroup()
111 {
112 	delete pSub;
113 }
114 
115 void SdrObjGroup::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
116 {
117 	rInfo.bNoContortion=sal_False;
118 	SdrObjList* pOL=pSub;
119 	sal_uIntPtr nObjAnz=pOL->GetObjCount();
120 	for (sal_uIntPtr i=0; i<nObjAnz; i++) {
121 		SdrObject* pObj=pOL->GetObj(i);
122 		SdrObjTransformInfoRec aInfo;
123 		pObj->TakeObjInfo(aInfo);
124 		if (!aInfo.bMoveAllowed            ) rInfo.bMoveAllowed            =sal_False;
125 		if (!aInfo.bResizeFreeAllowed      ) rInfo.bResizeFreeAllowed      =sal_False;
126 		if (!aInfo.bResizePropAllowed      ) rInfo.bResizePropAllowed      =sal_False;
127 		if (!aInfo.bRotateFreeAllowed      ) rInfo.bRotateFreeAllowed      =sal_False;
128 		if (!aInfo.bRotate90Allowed        ) rInfo.bRotate90Allowed        =sal_False;
129 		if (!aInfo.bMirrorFreeAllowed      ) rInfo.bMirrorFreeAllowed      =sal_False;
130 		if (!aInfo.bMirror45Allowed        ) rInfo.bMirror45Allowed        =sal_False;
131 		if (!aInfo.bMirror90Allowed        ) rInfo.bMirror90Allowed        =sal_False;
132 		if (!aInfo.bShearAllowed           ) rInfo.bShearAllowed           =sal_False;
133 		if (!aInfo.bEdgeRadiusAllowed	   ) rInfo.bEdgeRadiusAllowed	   =sal_False;
134 		if (!aInfo.bNoOrthoDesired         ) rInfo.bNoOrthoDesired         =sal_False;
135 		if (aInfo.bNoContortion            ) rInfo.bNoContortion           =sal_True;
136 		if (!aInfo.bCanConvToPath          ) rInfo.bCanConvToPath          =sal_False;
137 
138 		if(!aInfo.bCanConvToContour)
139 			rInfo.bCanConvToContour = sal_False;
140 
141 		if (!aInfo.bCanConvToPoly          ) rInfo.bCanConvToPoly          =sal_False;
142 		if (!aInfo.bCanConvToPathLineToArea) rInfo.bCanConvToPathLineToArea=sal_False;
143 		if (!aInfo.bCanConvToPolyLineToArea) rInfo.bCanConvToPolyLineToArea=sal_False;
144 	}
145 	if (nObjAnz==0) {
146 		rInfo.bRotateFreeAllowed=sal_False;
147 		rInfo.bRotate90Allowed  =sal_False;
148 		rInfo.bMirrorFreeAllowed=sal_False;
149 		rInfo.bMirror45Allowed  =sal_False;
150 		rInfo.bMirror90Allowed  =sal_False;
151 		rInfo.bTransparenceAllowed = sal_False;
152 		rInfo.bGradientAllowed = sal_False;
153 		rInfo.bShearAllowed     =sal_False;
154 		rInfo.bEdgeRadiusAllowed=sal_False;
155 		rInfo.bNoContortion     =sal_True;
156 	}
157 	if(nObjAnz != 1)
158 	{
159 		// only allowed if single object selected
160 		rInfo.bTransparenceAllowed = sal_False;
161 		rInfo.bGradientAllowed = sal_False;
162 	}
163 }
164 
165 
166 void SdrObjGroup::SetBoundRectDirty()
167 {
168     // avoid resetting aOutRect which in case of this object is model data,
169     // not re-creatable view data
170 }
171 
172 sal_uInt16 SdrObjGroup::GetObjIdentifier() const
173 {
174 	return sal_uInt16(OBJ_GRUP);
175 }
176 
177 
178 SdrLayerID SdrObjGroup::GetLayer() const
179 {
180 	FASTBOOL b1st=sal_True;
181 	SdrLayerID nLay=SdrLayerID(SdrObject::GetLayer());
182 	SdrObjList* pOL=pSub;
183 	sal_uIntPtr nObjAnz=pOL->GetObjCount();
184 	for (sal_uIntPtr i=0; i<nObjAnz; i++) {
185 		SdrLayerID nLay1=pOL->GetObj(i)->GetLayer();
186 		if (b1st) { nLay=nLay1; b1st=sal_False; }
187 		else if (nLay1!=nLay) return 0;
188 	}
189 	return nLay;
190 }
191 
192 
193 void SdrObjGroup::NbcSetLayer(SdrLayerID nLayer)
194 {
195 	SdrObject::NbcSetLayer(nLayer);
196 	SdrObjList* pOL=pSub;
197 	sal_uIntPtr nObjAnz=pOL->GetObjCount();
198 	for (sal_uIntPtr i=0; i<nObjAnz; i++) {
199 		pOL->GetObj(i)->NbcSetLayer(nLayer);
200 	}
201 }
202 
203 
204 void SdrObjGroup::SetObjList(SdrObjList* pNewObjList)
205 {
206 	SdrObject::SetObjList(pNewObjList);
207 	pSub->SetUpList(pNewObjList);
208 }
209 
210 
211 void SdrObjGroup::SetPage(SdrPage* pNewPage)
212 {
213 	SdrObject::SetPage(pNewPage);
214 	pSub->SetPage(pNewPage);
215 }
216 
217 
218 void SdrObjGroup::SetModel(SdrModel* pNewModel)
219 {
220 	if(pNewModel!=pModel)
221 	{
222 		// #i30648#
223 		// This method also needs to migrate the used ItemSet
224 		// when the destination model uses a different pool
225 		// than the current one. Else it is possible to create
226 		// SdrObjGroups which reference the old pool which might
227 		// be destroyed (as the bug shows).
228 		SdrModel* pOldModel = pModel;
229 
230 		// test for correct pool in ItemSet; move to new pool if necessary
231 		if(pNewModel && GetObjectItemPool() && GetObjectItemPool() != &pNewModel->GetItemPool())
232 		{
233 			MigrateItemPool(GetObjectItemPool(), &pNewModel->GetItemPool(), pNewModel);
234 		}
235 
236 		// call parent
237 		SdrObject::SetModel(pNewModel);
238 
239 		// set new model at content
240 		pSub->SetModel(pNewModel);
241 
242 		// modify properties
243 		GetProperties().SetModel(pOldModel, pNewModel);
244 	}
245 }
246 
247 
248 FASTBOOL SdrObjGroup::HasRefPoint() const
249 {
250 	return bRefPoint;
251 }
252 
253 
254 Point SdrObjGroup::GetRefPoint() const
255 {
256 	return aRefPoint;
257 }
258 
259 
260 void SdrObjGroup::SetRefPoint(const Point& rPnt)
261 {
262 	bRefPoint=sal_True;
263 	aRefPoint=rPnt;
264 }
265 
266 
267 SdrObjList* SdrObjGroup::GetSubList() const
268 {
269 	return pSub;
270 }
271 
272 const Rectangle& SdrObjGroup::GetCurrentBoundRect() const
273 {
274     // --> OD 2007-02-01 #144962#
275     // <aOutRect> has to contain the bounding rectangle
276     if ( pSub->GetObjCount()!=0 )
277     {
278         const_cast<SdrObjGroup*>(this)->aOutRect = pSub->GetAllObjBoundRect();
279     }
280 
281     return aOutRect;
282     // <--
283 }
284 
285 const Rectangle& SdrObjGroup::GetSnapRect() const
286 {
287     // --> OD 2007-02-01 #144962#
288     // <aOutRect> has to contain the bounding rectangle
289     if ( pSub->GetObjCount()!=0 )
290     {
291         return pSub->GetAllObjSnapRect();
292     }
293     else
294     {
295         return aOutRect;
296     }
297     // <--
298 }
299 
300 void SdrObjGroup::operator=(const SdrObject& rObj)
301 {
302 	if(rObj.IsGroupObject())
303 	{
304 		// copy SdrObject stuff
305 		SdrObject::operator=(rObj);
306 
307 		// #i36404#
308 		// copy SubList, init model and page first
309 		SdrObjList& rSourceSubList = *rObj.GetSubList();
310 		pSub->SetPage(rSourceSubList.GetPage());
311 		pSub->SetModel(rSourceSubList.GetModel());
312 		pSub->CopyObjects(*rObj.GetSubList());
313 
314 		// copy local paremeters
315 		nDrehWink  =((SdrObjGroup&)rObj).nDrehWink;
316 		nShearWink =((SdrObjGroup&)rObj).nShearWink;
317 		aRefPoint  =((SdrObjGroup&)rObj).aRefPoint;
318 		bRefPoint  =((SdrObjGroup&)rObj).bRefPoint;
319 	}
320 }
321 
322 
323 void SdrObjGroup::TakeObjNameSingul(XubString& rName) const
324 {
325 	if(!pSub->GetObjCount())
326 	{
327 		rName = ImpGetResStr(STR_ObjNameSingulGRUPEMPTY);
328 	}
329 	else
330 	{
331 		rName = ImpGetResStr(STR_ObjNameSingulGRUP);
332 	}
333 
334 	const String aName(GetName());
335 
336 	if(aName.Len())
337 	{
338 		rName += sal_Unicode(' ');
339 		rName += sal_Unicode('\'');
340 		rName += aName;
341 		rName += sal_Unicode('\'');
342 	}
343 }
344 
345 
346 void SdrObjGroup::TakeObjNamePlural(XubString& rName) const
347 {
348 	if (pSub->GetObjCount()==0) {
349 		rName=ImpGetResStr(STR_ObjNamePluralGRUPEMPTY);
350 	} else {
351 		rName=ImpGetResStr(STR_ObjNamePluralGRUP);
352 	}
353 }
354 
355 
356 void SdrObjGroup::RecalcSnapRect()
357 {
358 	// nicht erforderlich, da die Rects von der SubList verwendet werden.
359 }
360 
361 basegfx::B2DPolyPolygon SdrObjGroup::TakeXorPoly() const
362 {
363 	basegfx::B2DPolyPolygon aRetval;
364 	const sal_uInt32 nObjCount(pSub->GetObjCount());
365 
366 	for(sal_uInt32 a(0L); a < nObjCount; a++)
367 	{
368 		SdrObject* pObj = pSub->GetObj(a);
369 		aRetval.append(pObj->TakeXorPoly());
370 	}
371 
372 	if(!aRetval.count())
373 	{
374 		const basegfx::B2DRange aRange(aOutRect.Left(), aOutRect.Top(), aOutRect.Right(), aOutRect.Bottom());
375 		aRetval.append(basegfx::tools::createPolygonFromRect(aRange));
376 	}
377 
378 	return aRetval;
379 }
380 
381 bool SdrObjGroup::beginSpecialDrag(SdrDragStat& /*rDrag*/) const
382 {
383 	return false;
384 }
385 
386 
387 FASTBOOL SdrObjGroup::BegCreate(SdrDragStat& /*rStat*/)
388 {
389 	return sal_False;
390 }
391 
392 
393 long SdrObjGroup::GetRotateAngle() const
394 {
395 	return nDrehWink;
396 }
397 
398 
399 long SdrObjGroup::GetShearAngle(FASTBOOL /*bVertical*/) const
400 {
401 	return nShearWink;
402 }
403 
404 
405 void SdrObjGroup::NbcSetSnapRect(const Rectangle& rRect)
406 {
407 	Rectangle aOld(GetSnapRect());
408 	long nMulX=rRect.Right()-rRect.Left();
409 	long nDivX=aOld.Right()-aOld.Left();
410 	long nMulY=rRect.Bottom()-rRect.Top();
411 	long nDivY=aOld.Bottom()-aOld.Top();
412 	if (nDivX==0) { nMulX=1; nDivX=1; }
413 	if (nDivY==0) { nMulY=1; nDivY=1; }
414 	if (nMulX!=nDivX || nMulY!=nDivY) {
415 		Fraction aX(nMulX,nDivX);
416 		Fraction aY(nMulY,nDivY);
417 		NbcResize(aOld.TopLeft(),aX,aY);
418 	}
419 	if (rRect.Left()!=aOld.Left() || rRect.Top()!=aOld.Top()) {
420 		NbcMove(Size(rRect.Left()-aOld.Left(),rRect.Top()-aOld.Top()));
421 	}
422 }
423 
424 
425 void SdrObjGroup::NbcSetLogicRect(const Rectangle& rRect)
426 {
427 	NbcSetSnapRect(rRect);
428 }
429 
430 
431 void SdrObjGroup::NbcMove(const Size& rSiz)
432 {
433 	MovePoint(aRefPoint,rSiz);
434 	if (pSub->GetObjCount()!=0) {
435 		SdrObjList* pOL=pSub;
436 		sal_uIntPtr nObjAnz=pOL->GetObjCount();
437 		for (sal_uIntPtr i=0; i<nObjAnz; i++) {
438 			SdrObject* pObj=pOL->GetObj(i);
439 			pObj->NbcMove(rSiz);
440 		}
441 	} else {
442 		MoveRect(aOutRect,rSiz);
443 		SetRectsDirty();
444 	}
445 }
446 
447 
448 void SdrObjGroup::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
449 {
450 	FASTBOOL bXMirr=(xFact.GetNumerator()<0) != (xFact.GetDenominator()<0);
451 	FASTBOOL bYMirr=(yFact.GetNumerator()<0) != (yFact.GetDenominator()<0);
452 	if (bXMirr || bYMirr) {
453 		Point aRef1(GetSnapRect().Center());
454 		if (bXMirr) {
455 			Point aRef2(aRef1);
456 			aRef2.Y()++;
457 			NbcMirrorGluePoints(aRef1,aRef2);
458 		}
459 		if (bYMirr) {
460 			Point aRef2(aRef1);
461 			aRef2.X()++;
462 			NbcMirrorGluePoints(aRef1,aRef2);
463 		}
464 	}
465 	ResizePoint(aRefPoint,rRef,xFact,yFact);
466 	if (pSub->GetObjCount()!=0) {
467 		SdrObjList* pOL=pSub;
468 		sal_uIntPtr nObjAnz=pOL->GetObjCount();
469 		for (sal_uIntPtr i=0; i<nObjAnz; i++) {
470 			SdrObject* pObj=pOL->GetObj(i);
471 			pObj->NbcResize(rRef,xFact,yFact);
472 		}
473 	} else {
474 		ResizeRect(aOutRect,rRef,xFact,yFact);
475 		SetRectsDirty();
476 	}
477 }
478 
479 
480 void SdrObjGroup::NbcRotate(const Point& rRef, long nWink, double sn, double cs)
481 {
482 	SetGlueReallyAbsolute(sal_True);
483 	nDrehWink=NormAngle360(nDrehWink+nWink);
484 	RotatePoint(aRefPoint,rRef,sn,cs);
485 	SdrObjList* pOL=pSub;
486 	sal_uIntPtr nObjAnz=pOL->GetObjCount();
487 	for (sal_uIntPtr i=0; i<nObjAnz; i++) {
488 		SdrObject* pObj=pOL->GetObj(i);
489 		pObj->NbcRotate(rRef,nWink,sn,cs);
490 	}
491 	NbcRotateGluePoints(rRef,nWink,sn,cs);
492 	SetGlueReallyAbsolute(sal_False);
493 }
494 
495 
496 void SdrObjGroup::NbcMirror(const Point& rRef1, const Point& rRef2)
497 {
498 	SetGlueReallyAbsolute(sal_True);
499 	MirrorPoint(aRefPoint,rRef1,rRef2); // fehlende Implementation in SvdEtc !!!
500 	SdrObjList* pOL=pSub;
501 	sal_uIntPtr nObjAnz=pOL->GetObjCount();
502 	for (sal_uIntPtr i=0; i<nObjAnz; i++) {
503 		SdrObject* pObj=pOL->GetObj(i);
504 		pObj->NbcMirror(rRef1,rRef2);
505 	}
506 	NbcMirrorGluePoints(rRef1,rRef2);
507 	SetGlueReallyAbsolute(sal_False);
508 }
509 
510 
511 void SdrObjGroup::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear)
512 {
513 	SetGlueReallyAbsolute(sal_True);
514 	nShearWink+=nWink;
515 	ShearPoint(aRefPoint,rRef,tn);
516 	SdrObjList* pOL=pSub;
517 	sal_uIntPtr nObjAnz=pOL->GetObjCount();
518 	for (sal_uIntPtr i=0; i<nObjAnz; i++) {
519 		SdrObject* pObj=pOL->GetObj(i);
520 		pObj->NbcShear(rRef,nWink,tn,bVShear);
521 	}
522 	NbcShearGluePoints(rRef,nWink,tn,bVShear);
523 	SetGlueReallyAbsolute(sal_False);
524 }
525 
526 
527 void SdrObjGroup::NbcSetAnchorPos(const Point& rPnt)
528 {
529 	aAnchor=rPnt;
530 	Size aSiz(rPnt.X()-aAnchor.X(),rPnt.Y()-aAnchor.Y());
531 	MovePoint(aRefPoint,aSiz);
532 	SdrObjList* pOL=pSub;
533 	sal_uIntPtr nObjAnz=pOL->GetObjCount();
534 	for (sal_uIntPtr i=0; i<nObjAnz; i++) {
535 		SdrObject* pObj=pOL->GetObj(i);
536 		pObj->NbcSetAnchorPos(rPnt);
537 	}
538 }
539 
540 
541 void SdrObjGroup::SetSnapRect(const Rectangle& rRect)
542 {
543 	Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
544 	Rectangle aOld(GetSnapRect());
545 	long nMulX=rRect.Right()-rRect.Left();
546 	long nDivX=aOld.Right()-aOld.Left();
547 	long nMulY=rRect.Bottom()-rRect.Top();
548 	long nDivY=aOld.Bottom()-aOld.Top();
549 	if (nDivX==0) { nMulX=1; nDivX=1; }
550 	if (nDivY==0) { nMulY=1; nDivY=1; }
551 	if (nMulX!=nDivX || nMulY!=nDivY) {
552 		Fraction aX(nMulX,nDivX);
553 		Fraction aY(nMulY,nDivY);
554 		Resize(aOld.TopLeft(),aX,aY);
555 	}
556 	if (rRect.Left()!=aOld.Left() || rRect.Top()!=aOld.Top()) {
557 		Move(Size(rRect.Left()-aOld.Left(),rRect.Top()-aOld.Top()));
558 	}
559 
560 	SetChanged();
561 	BroadcastObjectChange();
562 	SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
563 }
564 
565 
566 void SdrObjGroup::SetLogicRect(const Rectangle& rRect)
567 {
568 	SetSnapRect(rRect);
569 }
570 
571 
572 void SdrObjGroup::Move(const Size& rSiz)
573 {
574 	if (rSiz.Width()!=0 || rSiz.Height()!=0) {
575 		Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
576 		MovePoint(aRefPoint,rSiz);
577 		if (pSub->GetObjCount()!=0) {
578 			// #32383# Erst die Verbinder verschieben, dann den Rest
579 			SdrObjList* pOL=pSub;
580 			sal_uIntPtr nObjAnz=pOL->GetObjCount();
581 			sal_uIntPtr i;
582 			for (i=0; i<nObjAnz; i++) {
583 				SdrObject* pObj=pOL->GetObj(i);
584 				if (pObj->IsEdgeObj()) pObj->Move(rSiz);
585 			}
586 			for (i=0; i<nObjAnz; i++) {
587 				SdrObject* pObj=pOL->GetObj(i);
588 				if (!pObj->IsEdgeObj()) pObj->Move(rSiz);
589 			}
590 		} else {
591 			// #110094#-14 SendRepaintBroadcast();
592 			MoveRect(aOutRect,rSiz);
593 			SetRectsDirty();
594 		}
595 
596 		SetChanged();
597 		BroadcastObjectChange();
598 		SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0);
599 	}
600 }
601 
602 
603 void SdrObjGroup::Resize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
604 {
605 	if (xFact.GetNumerator()!=xFact.GetDenominator() || yFact.GetNumerator()!=yFact.GetDenominator()) {
606 		FASTBOOL bXMirr=(xFact.GetNumerator()<0) != (xFact.GetDenominator()<0);
607 		FASTBOOL bYMirr=(yFact.GetNumerator()<0) != (yFact.GetDenominator()<0);
608 		if (bXMirr || bYMirr) {
609 			Point aRef1(GetSnapRect().Center());
610 			if (bXMirr) {
611 				Point aRef2(aRef1);
612 				aRef2.Y()++;
613 				NbcMirrorGluePoints(aRef1,aRef2);
614 			}
615 			if (bYMirr) {
616 				Point aRef2(aRef1);
617 				aRef2.X()++;
618 				NbcMirrorGluePoints(aRef1,aRef2);
619 			}
620 		}
621 		Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
622 		ResizePoint(aRefPoint,rRef,xFact,yFact);
623 		if (pSub->GetObjCount()!=0) {
624 			// #32383# Erst die Verbinder verschieben, dann den Rest
625 			SdrObjList* pOL=pSub;
626 			sal_uIntPtr nObjAnz=pOL->GetObjCount();
627 			sal_uIntPtr i;
628 			for (i=0; i<nObjAnz; i++) {
629 				SdrObject* pObj=pOL->GetObj(i);
630 				if (pObj->IsEdgeObj()) pObj->Resize(rRef,xFact,yFact);
631 			}
632 			for (i=0; i<nObjAnz; i++) {
633 				SdrObject* pObj=pOL->GetObj(i);
634 				if (!pObj->IsEdgeObj()) pObj->Resize(rRef,xFact,yFact);
635 			}
636 		} else {
637 			// #110094#-14 SendRepaintBroadcast();
638 			ResizeRect(aOutRect,rRef,xFact,yFact);
639 			SetRectsDirty();
640 		}
641 
642 		SetChanged();
643 		BroadcastObjectChange();
644 		SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
645 	}
646 }
647 
648 
649 void SdrObjGroup::Rotate(const Point& rRef, long nWink, double sn, double cs)
650 {
651 	if (nWink!=0) {
652 		SetGlueReallyAbsolute(sal_True);
653 		Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
654 		nDrehWink=NormAngle360(nDrehWink+nWink);
655 		RotatePoint(aRefPoint,rRef,sn,cs);
656 		// #32383# Erst die Verbinder verschieben, dann den Rest
657 		SdrObjList* pOL=pSub;
658 		sal_uIntPtr nObjAnz=pOL->GetObjCount();
659 		sal_uIntPtr i;
660 		for (i=0; i<nObjAnz; i++) {
661 			SdrObject* pObj=pOL->GetObj(i);
662 			if (pObj->IsEdgeObj()) pObj->Rotate(rRef,nWink,sn,cs);
663 		}
664 		for (i=0; i<nObjAnz; i++) {
665 			SdrObject* pObj=pOL->GetObj(i);
666 			if (!pObj->IsEdgeObj()) pObj->Rotate(rRef,nWink,sn,cs);
667 		}
668 		NbcRotateGluePoints(rRef,nWink,sn,cs);
669 		SetGlueReallyAbsolute(sal_False);
670 		SetChanged();
671 		BroadcastObjectChange();
672 		SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
673 	}
674 }
675 
676 
677 void SdrObjGroup::Mirror(const Point& rRef1, const Point& rRef2)
678 {
679 	SetGlueReallyAbsolute(sal_True);
680 	Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
681 	MirrorPoint(aRefPoint,rRef1,rRef2); // fehlende Implementation in SvdEtc !!!
682 	// #32383# Erst die Verbinder verschieben, dann den Rest
683 	SdrObjList* pOL=pSub;
684 	sal_uIntPtr nObjAnz=pOL->GetObjCount();
685 	sal_uIntPtr i;
686 	for (i=0; i<nObjAnz; i++) {
687 		SdrObject* pObj=pOL->GetObj(i);
688 		if (pObj->IsEdgeObj()) pObj->Mirror(rRef1,rRef2);
689 	}
690 	for (i=0; i<nObjAnz; i++) {
691 		SdrObject* pObj=pOL->GetObj(i);
692 		if (!pObj->IsEdgeObj()) pObj->Mirror(rRef1,rRef2);
693 	}
694 	NbcMirrorGluePoints(rRef1,rRef2);
695 	SetGlueReallyAbsolute(sal_False);
696 	SetChanged();
697 	BroadcastObjectChange();
698 	SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
699 }
700 
701 
702 void SdrObjGroup::Shear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear)
703 {
704 	if (nWink!=0) {
705 		SetGlueReallyAbsolute(sal_True);
706 		Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
707 		nShearWink+=nWink;
708 		ShearPoint(aRefPoint,rRef,tn);
709 		// #32383# Erst die Verbinder verschieben, dann den Rest
710 		SdrObjList* pOL=pSub;
711 		sal_uIntPtr nObjAnz=pOL->GetObjCount();
712 		sal_uIntPtr i;
713 		for (i=0; i<nObjAnz; i++) {
714 			SdrObject* pObj=pOL->GetObj(i);
715 			if (pObj->IsEdgeObj()) pObj->Shear(rRef,nWink,tn,bVShear);
716 		}
717 		for (i=0; i<nObjAnz; i++) {
718 			SdrObject* pObj=pOL->GetObj(i);
719 			if (!pObj->IsEdgeObj()) pObj->Shear(rRef,nWink,tn,bVShear);
720 		}
721 		NbcShearGluePoints(rRef,nWink,tn,bVShear);
722 		SetGlueReallyAbsolute(sal_False);
723 		SetChanged();
724 		BroadcastObjectChange();
725 		SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
726 	}
727 }
728 
729 
730 void SdrObjGroup::SetAnchorPos(const Point& rPnt)
731 {
732 	Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
733 	FASTBOOL bChg=aAnchor!=rPnt;
734 	aAnchor=rPnt;
735 	Size aSiz(rPnt.X()-aAnchor.X(),rPnt.Y()-aAnchor.Y());
736 	MovePoint(aRefPoint,aSiz);
737 	// #32383# Erst die Verbinder verschieben, dann den Rest
738 	SdrObjList* pOL=pSub;
739 	sal_uIntPtr nObjAnz=pOL->GetObjCount();
740 	sal_uIntPtr i;
741 	for (i=0; i<nObjAnz; i++) {
742 		SdrObject* pObj=pOL->GetObj(i);
743 		if (pObj->IsEdgeObj()) pObj->SetAnchorPos(rPnt);
744 	}
745 	for (i=0; i<nObjAnz; i++) {
746 		SdrObject* pObj=pOL->GetObj(i);
747 		if (!pObj->IsEdgeObj()) pObj->SetAnchorPos(rPnt);
748 	}
749 	if (bChg) {
750 		SetChanged();
751 		BroadcastObjectChange();
752 		SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0);
753 	}
754 }
755 
756 
757 
758 void SdrObjGroup::NbcSetRelativePos(const Point& rPnt)
759 {
760 	Point aRelPos0(GetSnapRect().TopLeft()-aAnchor);
761 	Size aSiz(rPnt.X()-aRelPos0.X(),rPnt.Y()-aRelPos0.Y());
762 	NbcMove(aSiz); // Der ruft auch das SetRectsDirty()
763 }
764 
765 void SdrObjGroup::SetRelativePos(const Point& rPnt)
766 {
767 	Point aRelPos0(GetSnapRect().TopLeft()-aAnchor);
768 	Size aSiz(rPnt.X()-aRelPos0.X(),rPnt.Y()-aRelPos0.Y());
769 	if (aSiz.Width()!=0 || aSiz.Height()!=0) Move(aSiz); // Der ruft auch das SetRectsDirty() und Broadcast, ...
770 }
771 
772 void SdrObjGroup::NbcReformatText()
773 {
774 	pSub->NbcReformatAllTextObjects();
775 }
776 
777 void SdrObjGroup::ReformatText()
778 {
779 	pSub->ReformatAllTextObjects();
780 }
781 
782 SdrObject* SdrObjGroup::DoConvertToPolyObj(sal_Bool bBezier, bool bAddText) const
783 {
784 	SdrObject* pGroup = new SdrObjGroup;
785 	pGroup->SetModel(GetModel());
786 
787 	for(sal_uInt32 a=0;a<pSub->GetObjCount();a++)
788 	{
789 		SdrObject* pIterObj = pSub->GetObj(a);
790         SdrObject* pResult = pIterObj->DoConvertToPolyObj(bBezier, bAddText);
791 
792         // pResult can be NULL e.g. for empty objects
793         if( pResult )
794             pGroup->GetSubList()->NbcInsertObject(pResult);
795 	}
796 
797 	return pGroup;
798 }
799 
800 // eof
801