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