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