xref: /trunk/main/svx/source/svdraw/svdogrp.cxx (revision 31e7663741e34cfcf6888dd6fd94230d62f83fc3)
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