xref: /AOO41X/main/svx/source/svdraw/svdedtv1.cxx (revision 54628ca40d27d15cc98fe861da7fff7e60c2f7d6)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include <svx/svdedtv.hxx>
28 #include <math.h>
29 
30 #ifndef _MATH_H
31 #define _MATH_H
32 #endif
33 #include <tools/bigint.hxx>
34 #include <svl/itemiter.hxx>
35 #include <vcl/msgbox.hxx>
36 #include <svx/rectenum.hxx>
37 #include <svx/svxids.hrc>   // fuer SID_ATTR_TRANSFORM_...
38 #include <svx/svdattr.hxx>  // fuer Get/SetGeoAttr
39 #include "svx/svditext.hxx"
40 #include "svx/svditer.hxx"
41 #include <svx/svdtrans.hxx>
42 #include <svx/svdundo.hxx>
43 #include <svx/svdpage.hxx>
44 #include <svx/svdpagv.hxx>
45 #include <svx/svdlayer.hxx> // fuer MergeNotPersistAttr
46 #include <svx/svdattrx.hxx> // fuer MergeNotPersistAttr
47 #include <svx/svdetc.hxx>   // fuer SearchOutlinerItems
48 #include <svx/svdopath.hxx>  // fuer Crook
49 #include "svx/svdstr.hrc"   // Namen aus der Resource
50 #include "svx/svdglob.hxx"  // StringCache
51 #include <editeng/eeitem.hxx>
52 #include <svl/aeitem.hxx>
53 #include <svl/whiter.hxx>
54 #include <svx/sdr/contact/objectcontact.hxx>
55 #include <svx/sdr/contact/viewcontact.hxx>
56 #include <svx/e3dsceneupdater.hxx>
57 #include <svx/obj3d.hxx>
58 
59 ////////////////////////////////////////////////////////////////////////////////////////////////////
60 ////////////////////////////////////////////////////////////////////////////////////////////////////
61 ////////////////////////////////////////////////////////////////////////////////////////////////////
62 ////////////////////////////////////////////////////////////////////////////////////////////////////
63 //
64 //  @@@@@ @@@@@  @@ @@@@@@  @@ @@ @@ @@@@@ @@   @@
65 //  @@    @@  @@ @@   @@    @@ @@ @@ @@    @@   @@
66 //  @@    @@  @@ @@   @@    @@ @@ @@ @@    @@ @ @@
67 //  @@@@  @@  @@ @@   @@    @@@@@ @@ @@@@  @@@@@@@
68 //  @@    @@  @@ @@   @@     @@@  @@ @@    @@@@@@@
69 //  @@    @@  @@ @@   @@     @@@  @@ @@    @@@ @@@
70 //  @@@@@ @@@@@  @@   @@      @   @@ @@@@@ @@   @@
71 //
72 ////////////////////////////////////////////////////////////////////////////////////////////////////
73 ////////////////////////////////////////////////////////////////////////////////////////////////////
74 
75 void SdrEditView::SetMarkedObjRect(const Rectangle& rRect, sal_Bool bCopy)
76 {
77     DBG_ASSERT(!rRect.IsEmpty(),"SetMarkedObjRect() mit leerem Rect mach keinen Sinn");
78     if (rRect.IsEmpty()) return;
79     sal_uIntPtr nAnz=GetMarkedObjectCount();
80     if (nAnz==0) return;
81     Rectangle aR0(GetMarkedObjRect());
82     DBG_ASSERT(!aR0.IsEmpty(),"SetMarkedObjRect(): GetMarkedObjRect() ist leer");
83     if (aR0.IsEmpty()) return;
84     long x0=aR0.Left();
85     long y0=aR0.Top();
86     long w0=aR0.Right()-x0;
87     long h0=aR0.Bottom()-y0;
88     long x1=rRect.Left();
89     long y1=rRect.Top();
90     long w1=rRect.Right()-x1;
91     long h1=rRect.Bottom()-y1;
92     XubString aStr;
93     ImpTakeDescriptionStr(STR_EditPosSize,aStr);
94     if (bCopy)
95         aStr+=ImpGetResStr(STR_EditWithCopy);
96 
97     const bool bUndo = IsUndoEnabled();
98     if( bUndo )
99         BegUndo(aStr);
100 
101     if (bCopy)
102         CopyMarkedObj();
103 
104     for (sal_uIntPtr nm=0; nm<nAnz; nm++)
105     {
106         SdrMark* pM=GetSdrMarkByIndex(nm);
107         SdrObject* pO=pM->GetMarkedSdrObj();
108         if( bUndo )
109             AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
110 
111         Rectangle aR1(pO->GetSnapRect());
112         if (!aR1.IsEmpty())
113         {
114             if (aR1==aR0)
115             {
116                 aR1=rRect;
117             }
118             else
119             { // aR1 von aR0 nach rRect transformieren
120                 aR1.Move(-x0,-y0);
121                 BigInt l(aR1.Left());
122                 BigInt r(aR1.Right());
123                 BigInt t(aR1.Top());
124                 BigInt b(aR1.Bottom());
125                 if (w0!=0) {
126                     l*=w1; l/=w0;
127                     r*=w1; r/=w0;
128                 } else {
129                     l=0; r=w1;
130                 }
131                 if (h0!=0) {
132                     t*=h1; t/=h0;
133                     b*=h1; b/=h0;
134                 } else {
135                     t=0; b=h1;
136                 }
137                 aR1.Left  ()=long(l);
138                 aR1.Right ()=long(r);
139                 aR1.Top   ()=long(t);
140                 aR1.Bottom()=long(b);
141                 aR1.Move(x1,y1);
142             }
143             pO->SetSnapRect(aR1);
144         } else {
145             DBG_ERROR("SetMarkedObjRect(): pObj->GetSnapRect() liefert leeres Rect");
146         }
147     }
148     if( bUndo )
149         EndUndo();
150 }
151 
152 std::vector< SdrUndoAction* > SdrEditView::CreateConnectorUndo( SdrObject& rO )
153 {
154     std::vector< SdrUndoAction* > vUndoActions;
155 
156     if ( rO.GetBroadcaster() )
157     {
158         const SdrPage* pPage = rO.GetPage();
159         if ( pPage )
160         {
161             SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS );
162             while( aIter.IsMore() )
163             {
164                 SdrObject* pPartObj = aIter.Next();
165                 if ( pPartObj->ISA( SdrEdgeObj ) )
166                 {
167                     if ( ( pPartObj->GetConnectedNode( sal_False ) == &rO ) ||
168                          ( pPartObj->GetConnectedNode( sal_True  ) == &rO ) )
169                     {
170                         vUndoActions.push_back( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject( *pPartObj ) );
171                     }
172                 }
173             }
174         }
175     }
176     return vUndoActions;
177 }
178 
179 void SdrEditView::AddUndoActions( std::vector< SdrUndoAction* >& rUndoActions )
180 {
181     std::vector< SdrUndoAction* >::iterator aUndoActionIter( rUndoActions.begin() );
182     while( aUndoActionIter != rUndoActions.end() )
183         AddUndo( *aUndoActionIter++ );
184 }
185 
186 void SdrEditView::MoveMarkedObj(const Size& rSiz, bool bCopy)
187 {
188     const bool bUndo = IsUndoEnabled();
189 
190     if( bUndo )
191     {
192         XubString aStr(ImpGetResStr(STR_EditMove));
193         if (bCopy)
194             aStr+=ImpGetResStr(STR_EditWithCopy);
195         // benoetigt eigene UndoGroup wegen Parameter
196         BegUndo(aStr,GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVE);
197     }
198 
199     if (bCopy)
200         CopyMarkedObj();
201 
202     sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
203     for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
204     {
205         SdrMark* pM=GetSdrMarkByIndex(nm);
206         SdrObject* pO=pM->GetMarkedSdrObj();
207         if( bUndo )
208         {
209             std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
210             AddUndoActions( vConnectorUndoActions );
211             AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pO,rSiz));
212         }
213         pO->Move(rSiz);
214     }
215 
216     if( bUndo )
217         EndUndo();
218 }
219 
220 void SdrEditView::ResizeMarkedObj(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bCopy)
221 {
222     const bool bUndo = IsUndoEnabled();
223     if( bUndo )
224     {
225         XubString aStr;
226         ImpTakeDescriptionStr(STR_EditResize,aStr);
227         if (bCopy)
228             aStr+=ImpGetResStr(STR_EditWithCopy);
229         BegUndo(aStr);
230     }
231 
232     if (bCopy)
233         CopyMarkedObj();
234 
235     sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
236     for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
237     {
238         SdrMark* pM=GetSdrMarkByIndex(nm);
239         SdrObject* pO=pM->GetMarkedSdrObj();
240         if( bUndo )
241         {
242             std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
243             AddUndoActions( vConnectorUndoActions );
244             AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
245         }
246         pO->Resize(rRef,xFact,yFact);
247     }
248 
249     if( bUndo )
250         EndUndo();
251 }
252 
253 long SdrEditView::GetMarkedObjRotate() const
254 {
255     sal_Bool b1st=sal_True;
256     sal_Bool bOk=sal_True;
257     long nWink=0;
258     sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
259     for (sal_uIntPtr nm=0; nm<nMarkAnz && bOk; nm++) {
260         SdrMark* pM=GetSdrMarkByIndex(nm);
261         SdrObject* pO=pM->GetMarkedSdrObj();
262         long nWink2=pO->GetRotateAngle();
263         if (b1st) nWink=nWink2;
264         else if (nWink2!=nWink) bOk=sal_False;
265         b1st=sal_False;
266     }
267     if (!bOk) nWink=0;
268     return nWink;
269 }
270 
271 void SdrEditView::RotateMarkedObj(const Point& rRef, long nWink, bool bCopy)
272 {
273     const bool bUndo = IsUndoEnabled();
274     if( bUndo )
275     {
276         XubString aStr;
277         ImpTakeDescriptionStr(STR_EditRotate,aStr);
278         if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy);
279         BegUndo(aStr);
280     }
281 
282     if (bCopy)
283         CopyMarkedObj();
284 
285     double nSin=sin(nWink*nPi180);
286     double nCos=cos(nWink*nPi180);
287     const sal_uInt32 nMarkAnz(GetMarkedObjectCount());
288 
289     if(nMarkAnz)
290     {
291         std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
292 
293         for(sal_uInt32 nm(0); nm < nMarkAnz; nm++)
294         {
295             SdrMark* pM = GetSdrMarkByIndex(nm);
296             SdrObject* pO = pM->GetMarkedSdrObj();
297 
298             if( bUndo )
299             {
300                 // extra undo actions for changed connector which now may hold it's layouted path (SJ)
301                 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
302                 AddUndoActions( vConnectorUndoActions );
303 
304                 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
305             }
306 
307             // set up a scene updater if object is a 3d object
308             if(dynamic_cast< E3dObject* >(pO))
309             {
310                 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO));
311             }
312 
313             pO->Rotate(rRef,nWink,nSin,nCos);
314         }
315 
316         // fire scene updaters
317         while(!aUpdaters.empty())
318         {
319             delete aUpdaters.back();
320             aUpdaters.pop_back();
321         }
322     }
323 
324     if( bUndo )
325         EndUndo();
326 }
327 
328 void SdrEditView::MirrorMarkedObj(const Point& rRef1, const Point& rRef2, bool bCopy)
329 {
330     const bool bUndo = IsUndoEnabled();
331 
332     if( bUndo )
333     {
334         XubString aStr;
335         Point aDif(rRef2-rRef1);
336         if (aDif.X()==0) ImpTakeDescriptionStr(STR_EditMirrorHori,aStr);
337         else if (aDif.Y()==0) ImpTakeDescriptionStr(STR_EditMirrorVert,aStr);
338         else if (Abs(aDif.X())==Abs(aDif.Y())) ImpTakeDescriptionStr(STR_EditMirrorDiag,aStr);
339         else ImpTakeDescriptionStr(STR_EditMirrorFree,aStr);
340         if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy);
341         BegUndo(aStr);
342     }
343 
344     if (bCopy)
345         CopyMarkedObj();
346 
347     const sal_uInt32 nMarkAnz(GetMarkedObjectCount());
348 
349     if(nMarkAnz)
350     {
351         std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
352 
353         for(sal_uInt32 nm(0); nm < nMarkAnz; nm++)
354         {
355             SdrMark* pM = GetSdrMarkByIndex(nm);
356             SdrObject* pO = pM->GetMarkedSdrObj();
357 
358             if( bUndo )
359             {
360                 // extra undo actions for changed connector which now may hold it's layouted path (SJ)
361                 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
362                 AddUndoActions( vConnectorUndoActions );
363 
364                 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
365             }
366 
367             // set up a scene updater if object is a 3d object
368             if(dynamic_cast< E3dObject* >(pO))
369             {
370                 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO));
371             }
372 
373             pO->Mirror(rRef1,rRef2);
374         }
375 
376         // fire scene updaters
377         while(!aUpdaters.empty())
378         {
379             delete aUpdaters.back();
380             aUpdaters.pop_back();
381         }
382     }
383 
384     if( bUndo )
385         EndUndo();
386 }
387 
388 void SdrEditView::MirrorMarkedObjHorizontal(sal_Bool bCopy)
389 {
390     Point aCenter(GetMarkedObjRect().Center());
391     Point aPt2(aCenter);
392     aPt2.Y()++;
393     MirrorMarkedObj(aCenter,aPt2,bCopy);
394 }
395 
396 void SdrEditView::MirrorMarkedObjVertical(sal_Bool bCopy)
397 {
398     Point aCenter(GetMarkedObjRect().Center());
399     Point aPt2(aCenter);
400     aPt2.X()++;
401     MirrorMarkedObj(aCenter,aPt2,bCopy);
402 }
403 
404 long SdrEditView::GetMarkedObjShear() const
405 {
406     sal_Bool b1st=sal_True;
407     sal_Bool bOk=sal_True;
408     long nWink=0;
409     sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
410     for (sal_uIntPtr nm=0; nm<nMarkAnz && bOk; nm++) {
411         SdrMark* pM=GetSdrMarkByIndex(nm);
412         SdrObject* pO=pM->GetMarkedSdrObj();
413         long nWink2=pO->GetShearAngle();
414         if (b1st) nWink=nWink2;
415         else if (nWink2!=nWink) bOk=sal_False;
416         b1st=sal_False;
417     }
418     if (nWink>SDRMAXSHEAR) nWink=SDRMAXSHEAR;
419     if (nWink<-SDRMAXSHEAR) nWink=-SDRMAXSHEAR;
420     if (!bOk) nWink=0;
421     return nWink;
422 }
423 
424 void SdrEditView::ShearMarkedObj(const Point& rRef, long nWink, bool bVShear, bool bCopy)
425 {
426     const bool bUndo = IsUndoEnabled();
427 
428     if( bUndo )
429     {
430         XubString aStr;
431         ImpTakeDescriptionStr(STR_EditShear,aStr);
432         if (bCopy)
433             aStr+=ImpGetResStr(STR_EditWithCopy);
434         BegUndo(aStr);
435     }
436 
437     if (bCopy)
438         CopyMarkedObj();
439 
440     double nTan=tan(nWink*nPi180);
441     sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
442     for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
443     {
444         SdrMark* pM=GetSdrMarkByIndex(nm);
445         SdrObject* pO=pM->GetMarkedSdrObj();
446         if( bUndo )
447         {
448             std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
449             AddUndoActions( vConnectorUndoActions );
450             AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
451         }
452         pO->Shear(rRef,nWink,nTan,bVShear);
453     }
454 
455     if( bUndo )
456         EndUndo();
457 }
458 
459 void SdrEditView::ImpCrookObj(SdrObject* pO, const Point& rRef, const Point& rRad,
460     SdrCrookMode eMode, sal_Bool bVertical, sal_Bool bNoContortion, sal_Bool bRotate, const Rectangle& rMarkRect)
461 {
462     SdrPathObj* pPath=PTR_CAST(SdrPathObj,pO);
463     sal_Bool bDone = sal_False;
464 
465     if(pPath!=NULL && !bNoContortion)
466     {
467         XPolyPolygon aXPP(pPath->GetPathPoly());
468         switch (eMode) {
469             case SDRCROOK_ROTATE : CrookRotatePoly (aXPP,rRef,rRad,bVertical);           break;
470             case SDRCROOK_SLANT  : CrookSlantPoly  (aXPP,rRef,rRad,bVertical);           break;
471             case SDRCROOK_STRETCH: CrookStretchPoly(aXPP,rRef,rRad,bVertical,rMarkRect); break;
472         } // switch
473         pPath->SetPathPoly(aXPP.getB2DPolyPolygon());
474         bDone = sal_True;
475     }
476 
477     if(!bDone && !pPath && pO->IsPolyObj() && 0L != pO->GetPointCount())
478     {
479         // FuerPolyObj's, aber NICHT fuer SdrPathObj's, z.B. fuer's Bemassungsobjekt
480         sal_uInt32 nPtAnz(pO->GetPointCount());
481         XPolygon aXP((sal_uInt16)nPtAnz);
482         sal_uInt32 nPtNum;
483 
484         for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++)
485         {
486             Point aPt(pO->GetPoint(nPtNum));
487             aXP[(sal_uInt16)nPtNum]=aPt;
488         }
489 
490         switch (eMode)
491         {
492             case SDRCROOK_ROTATE : CrookRotatePoly (aXP,rRef,rRad,bVertical);           break;
493             case SDRCROOK_SLANT  : CrookSlantPoly  (aXP,rRef,rRad,bVertical);           break;
494             case SDRCROOK_STRETCH: CrookStretchPoly(aXP,rRef,rRad,bVertical,rMarkRect); break;
495         }
496 
497         for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++)
498         {
499             // hier koennte man vieleicht auch mal das Broadcasting optimieren
500             // ist aber z.Zt. bei den 2 Punkten des Bemassungsobjekts noch nicht so tragisch
501             pO->SetPoint(aXP[(sal_uInt16)nPtNum],nPtNum);
502         }
503 
504         bDone = sal_True;
505     }
506 
507     if(!bDone)
508     {
509         // Fuer alle anderen oder wenn bNoContortion
510         Point aCtr0(pO->GetSnapRect().Center());
511         Point aCtr1(aCtr0);
512         sal_Bool bRotOk(sal_False);
513         double nSin(0.0), nCos(1.0);
514         double nWink(0.0);
515 
516         if(0 != rRad.X() && 0 != rRad.Y())
517         {
518             bRotOk = bRotate;
519 
520             switch (eMode)
521             {
522                 case SDRCROOK_ROTATE : nWink=CrookRotateXPoint (aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical); bRotOk=bRotate; break;
523                 case SDRCROOK_SLANT  : nWink=CrookSlantXPoint  (aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical);           break;
524                 case SDRCROOK_STRETCH: nWink=CrookStretchXPoint(aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical,rMarkRect); break;
525             }
526         }
527 
528         aCtr1 -= aCtr0;
529 
530         if(bRotOk)
531             pO->Rotate(aCtr0, Round(nWink/nPi180), nSin, nCos);
532 
533         pO->Move(Size(aCtr1.X(),aCtr1.Y()));
534     }
535 }
536 
537 void SdrEditView::CrookMarkedObj(const Point& rRef, const Point& rRad, SdrCrookMode eMode,
538     bool bVertical, bool bNoContortion, bool bCopy)
539 {
540     Rectangle aMarkRect(GetMarkedObjRect());
541     const bool bUndo = IsUndoEnabled();
542 
543     bool bRotate=bNoContortion && eMode==SDRCROOK_ROTATE && IsRotateAllowed(sal_False);
544 
545     if( bUndo )
546     {
547         XubString aStr;
548         ImpTakeDescriptionStr(bNoContortion?STR_EditCrook:STR_EditCrookContortion,aStr);
549         if (bCopy)
550             aStr+=ImpGetResStr(STR_EditWithCopy);
551         BegUndo(aStr);
552     }
553 
554     if (bCopy)
555         CopyMarkedObj();
556 
557     sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
558     for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
559     {
560         SdrMark* pM=GetSdrMarkByIndex(nm);
561         SdrObject* pO=pM->GetMarkedSdrObj();
562         if( bUndo )
563             AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
564 
565         const SdrObjList* pOL=pO->GetSubList();
566         if (bNoContortion || pOL==NULL) {
567             ImpCrookObj(pO,rRef,rRad,eMode,bVertical,bNoContortion,bRotate,aMarkRect);
568         } else {
569             SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS);
570             while (aIter.IsMore()) {
571                 SdrObject* pO1=aIter.Next();
572                 ImpCrookObj(pO1,rRef,rRad,eMode,bVertical,bNoContortion,bRotate,aMarkRect);
573             }
574         }
575     }
576 
577     if( bUndo )
578         EndUndo();
579 }
580 
581 void SdrEditView::ImpDistortObj(SdrObject* pO, const Rectangle& rRef, const XPolygon& rDistortedRect, sal_Bool bNoContortion)
582 {
583     SdrPathObj* pPath = PTR_CAST(SdrPathObj, pO);
584 
585     if(!bNoContortion && pPath)
586     {
587         XPolyPolygon aXPP(pPath->GetPathPoly());
588         aXPP.Distort(rRef, rDistortedRect);
589         pPath->SetPathPoly(aXPP.getB2DPolyPolygon());
590     }
591     else if(pO->IsPolyObj())
592     {
593         // z.B. fuer's Bemassungsobjekt
594         sal_uInt32 nPtAnz(pO->GetPointCount());
595         XPolygon aXP((sal_uInt16)nPtAnz);
596         sal_uInt32 nPtNum;
597 
598         for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++)
599         {
600             Point aPt(pO->GetPoint(nPtNum));
601             aXP[(sal_uInt16)nPtNum]=aPt;
602         }
603 
604         aXP.Distort(rRef, rDistortedRect);
605 
606         for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++)
607         {
608             // hier koennte man vieleicht auch mal das Broadcasting optimieren
609             // ist aber z.Zt. bei den 2 Punkten des Bemassungsobjekts noch nicht so tragisch
610             pO->SetPoint(aXP[(sal_uInt16)nPtNum],nPtNum);
611         }
612     }
613 }
614 
615 void SdrEditView::DistortMarkedObj(const Rectangle& rRef, const XPolygon& rDistortedRect, bool bNoContortion, bool bCopy)
616 {
617     const bool bUndo = IsUndoEnabled();
618 
619     if( bUndo )
620     {
621         XubString aStr;
622         ImpTakeDescriptionStr(STR_EditDistort,aStr);
623         if (bCopy)
624             aStr+=ImpGetResStr(STR_EditWithCopy);
625         BegUndo(aStr);
626     }
627 
628     if (bCopy)
629         CopyMarkedObj();
630 
631     sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
632     for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
633     {
634         SdrMark* pM=GetSdrMarkByIndex(nm);
635         SdrObject* pO=pM->GetMarkedSdrObj();
636         if( bUndo )
637             AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
638 
639         Rectangle aRefRect(rRef);
640         XPolygon  aRefPoly(rDistortedRect);
641         const SdrObjList* pOL=pO->GetSubList();
642         if (bNoContortion || pOL==NULL) {
643             ImpDistortObj(pO,aRefRect,aRefPoly,bNoContortion);
644         } else {
645             SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS);
646             while (aIter.IsMore()) {
647                 SdrObject* pO1=aIter.Next();
648                 ImpDistortObj(pO1,aRefRect,aRefPoly,bNoContortion);
649             }
650         }
651     }
652     if( bUndo )
653         EndUndo();
654 }
655 
656 ////////////////////////////////////////////////////////////////////////////////////////////////////
657 
658 void SdrEditView::SetNotPersistAttrToMarked(const SfxItemSet& rAttr, sal_Bool /*bReplaceAll*/)
659 {
660     // bReplaceAll hat hier keinerlei Wirkung
661     Rectangle aAllSnapRect(GetMarkedObjRect());
662     const SfxPoolItem *pPoolItem=NULL;
663     if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1X,sal_True,&pPoolItem)==SFX_ITEM_SET) {
664         long n=((const SdrTransformRef1XItem*)pPoolItem)->GetValue();
665         SetRef1(Point(n,GetRef1().Y()));
666     }
667     if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1Y,sal_True,&pPoolItem)==SFX_ITEM_SET) {
668         long n=((const SdrTransformRef1YItem*)pPoolItem)->GetValue();
669         SetRef1(Point(GetRef1().X(),n));
670     }
671     if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2X,sal_True,&pPoolItem)==SFX_ITEM_SET) {
672         long n=((const SdrTransformRef2XItem*)pPoolItem)->GetValue();
673         SetRef2(Point(n,GetRef2().Y()));
674     }
675     if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2Y,sal_True,&pPoolItem)==SFX_ITEM_SET) {
676         long n=((const SdrTransformRef2YItem*)pPoolItem)->GetValue();
677         SetRef2(Point(GetRef2().X(),n));
678     }
679     long nAllPosX=0; sal_Bool bAllPosX=sal_False;
680     long nAllPosY=0; sal_Bool bAllPosY=sal_False;
681     long nAllWdt=0;  sal_Bool bAllWdt=sal_False;
682     long nAllHgt=0;  sal_Bool bAllHgt=sal_False;
683     sal_Bool bDoIt=sal_False;
684     if (rAttr.GetItemState(SDRATTR_ALLPOSITIONX,sal_True,&pPoolItem)==SFX_ITEM_SET) {
685         nAllPosX=((const SdrAllPositionXItem*)pPoolItem)->GetValue();
686         bAllPosX=sal_True; bDoIt=sal_True;
687     }
688     if (rAttr.GetItemState(SDRATTR_ALLPOSITIONY,sal_True,&pPoolItem)==SFX_ITEM_SET) {
689         nAllPosY=((const SdrAllPositionYItem*)pPoolItem)->GetValue();
690         bAllPosY=sal_True; bDoIt=sal_True;
691     }
692     if (rAttr.GetItemState(SDRATTR_ALLSIZEWIDTH,sal_True,&pPoolItem)==SFX_ITEM_SET) {
693         nAllWdt=((const SdrAllSizeWidthItem*)pPoolItem)->GetValue();
694         bAllWdt=sal_True; bDoIt=sal_True;
695     }
696     if (rAttr.GetItemState(SDRATTR_ALLSIZEHEIGHT,sal_True,&pPoolItem)==SFX_ITEM_SET) {
697         nAllHgt=((const SdrAllSizeHeightItem*)pPoolItem)->GetValue();
698         bAllHgt=sal_True; bDoIt=sal_True;
699     }
700     if (bDoIt) {
701         Rectangle aRect(aAllSnapRect); // !!! fuer PolyPt's und GluePt's aber bitte noch aendern !!!
702         if (bAllPosX) aRect.Move(nAllPosX-aRect.Left(),0);
703         if (bAllPosY) aRect.Move(0,nAllPosY-aRect.Top());
704         if (bAllWdt)  aRect.Right()=aAllSnapRect.Left()+nAllWdt;
705         if (bAllHgt)  aRect.Bottom()=aAllSnapRect.Top()+nAllHgt;
706         SetMarkedObjRect(aRect);
707     }
708     if (rAttr.GetItemState(SDRATTR_RESIZEXALL,sal_True,&pPoolItem)==SFX_ITEM_SET) {
709         Fraction aXFact=((const SdrResizeXAllItem*)pPoolItem)->GetValue();
710         ResizeMarkedObj(aAllSnapRect.TopLeft(),aXFact,Fraction(1,1));
711     }
712     if (rAttr.GetItemState(SDRATTR_RESIZEYALL,sal_True,&pPoolItem)==SFX_ITEM_SET) {
713         Fraction aYFact=((const SdrResizeYAllItem*)pPoolItem)->GetValue();
714         ResizeMarkedObj(aAllSnapRect.TopLeft(),Fraction(1,1),aYFact);
715     }
716     if (rAttr.GetItemState(SDRATTR_ROTATEALL,sal_True,&pPoolItem)==SFX_ITEM_SET) {
717         long nAngle=((const SdrRotateAllItem*)pPoolItem)->GetValue();
718         RotateMarkedObj(aAllSnapRect.Center(),nAngle);
719     }
720     if (rAttr.GetItemState(SDRATTR_HORZSHEARALL,sal_True,&pPoolItem)==SFX_ITEM_SET) {
721         long nAngle=((const SdrHorzShearAllItem*)pPoolItem)->GetValue();
722         ShearMarkedObj(aAllSnapRect.Center(),nAngle,sal_False);
723     }
724     if (rAttr.GetItemState(SDRATTR_VERTSHEARALL,sal_True,&pPoolItem)==SFX_ITEM_SET) {
725         long nAngle=((const SdrVertShearAllItem*)pPoolItem)->GetValue();
726         ShearMarkedObj(aAllSnapRect.Center(),nAngle,sal_True);
727     }
728 
729     const bool bUndo = IsUndoEnabled();
730 
731     // Todo: WhichRange nach Notwendigkeit ueberpruefen.
732     sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
733     for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
734     {
735         const SdrMark* pM=GetSdrMarkByIndex(nm);
736         SdrObject* pObj=pM->GetMarkedSdrObj();
737         //const SdrPageView* pPV=pM->GetPageView();
738         if( bUndo )
739             AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
740 
741         pObj->ApplyNotPersistAttr(rAttr);
742     }
743 }
744 
745 void SdrEditView::MergeNotPersistAttrFromMarked(SfxItemSet& rAttr, sal_Bool /*bOnlyHardAttr*/) const
746 {
747     // bOnlyHardAttr hat hier keinerlei Wirkung
748     // Hier muss ausserdem noch der Nullpunkt und
749     // die PvPos berueksichtigt werden.
750     Rectangle aAllSnapRect(GetMarkedObjRect()); // !!! fuer PolyPt's und GluePt's aber bitte noch aendern !!!
751     long nAllSnapPosX=aAllSnapRect.Left();
752     long nAllSnapPosY=aAllSnapRect.Top();
753     long nAllSnapWdt=aAllSnapRect.GetWidth()-1;
754     long nAllSnapHgt=aAllSnapRect.GetHeight()-1;
755     // koennte mal zu CheckPossibilities mit rein
756     sal_Bool bMovProtect=sal_False,bMovProtectDC=sal_False;
757     sal_Bool bSizProtect=sal_False,bSizProtectDC=sal_False;
758     sal_Bool bPrintable =sal_True ,bPrintableDC=sal_False;
759     sal_Bool bVisible = sal_True, bVisibleDC=sal_False;
760     SdrLayerID nLayerId=0; sal_Bool bLayerDC=sal_False;
761     XubString aObjName;     sal_Bool bObjNameDC=sal_False,bObjNameSet=sal_False;
762     long nSnapPosX=0;      sal_Bool bSnapPosXDC=sal_False;
763     long nSnapPosY=0;      sal_Bool bSnapPosYDC=sal_False;
764     long nSnapWdt=0;       sal_Bool bSnapWdtDC=sal_False;
765     long nSnapHgt=0;       sal_Bool bSnapHgtDC=sal_False;
766     long nLogicWdt=0;      sal_Bool bLogicWdtDC=sal_False,bLogicWdtDiff=sal_False;
767     long nLogicHgt=0;      sal_Bool bLogicHgtDC=sal_False,bLogicHgtDiff=sal_False;
768     long nRotAngle=0;      sal_Bool bRotAngleDC=sal_False;
769     long nShrAngle=0;      sal_Bool bShrAngleDC=sal_False;
770     Rectangle aSnapRect;
771     Rectangle aLogicRect;
772     sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
773     for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++) {
774         const SdrMark* pM=GetSdrMarkByIndex(nm);
775         const SdrObject* pObj=pM->GetMarkedSdrObj();
776         if (nm==0) {
777             nLayerId=pObj->GetLayer();
778             bMovProtect=pObj->IsMoveProtect();
779             bSizProtect=pObj->IsResizeProtect();
780             bPrintable =pObj->IsPrintable();
781             bVisible = pObj->IsVisible();
782             Rectangle aSnapRect2(pObj->GetSnapRect());
783             Rectangle aLogicRect2(pObj->GetLogicRect());
784             nSnapPosX=aSnapRect2.Left();
785             nSnapPosY=aSnapRect2.Top();
786             nSnapWdt=aSnapRect2.GetWidth()-1;
787             nSnapHgt=aSnapRect2.GetHeight()-1;
788             nLogicWdt=aLogicRect2.GetWidth()-1;
789             nLogicHgt=aLogicRect2.GetHeight()-1;
790             bLogicWdtDiff=nLogicWdt!=nSnapWdt;
791             bLogicHgtDiff=nLogicHgt!=nSnapHgt;
792             nRotAngle=pObj->GetRotateAngle();
793             nShrAngle=pObj->GetShearAngle();
794         } else {
795             if (!bLayerDC      && nLayerId   !=pObj->GetLayer())        bLayerDC=sal_True;
796             if (!bMovProtectDC && bMovProtect!=pObj->IsMoveProtect())   bMovProtectDC=sal_True;
797             if (!bSizProtectDC && bSizProtect!=pObj->IsResizeProtect()) bSizProtectDC=sal_True;
798             if (!bPrintableDC  && bPrintable !=pObj->IsPrintable())     bPrintableDC=sal_True;
799             if (!bVisibleDC    && bVisible !=pObj->IsVisible())         bVisibleDC=sal_True;
800             if (!bRotAngleDC   && nRotAngle  !=pObj->GetRotateAngle())  bRotAngleDC=sal_True;
801             if (!bShrAngleDC   && nShrAngle  !=pObj->GetShearAngle())   bShrAngleDC=sal_True;
802             if (!bSnapWdtDC || !bSnapHgtDC || !bSnapPosXDC || !bSnapPosYDC || !bLogicWdtDiff || !bLogicHgtDiff) {
803                 aSnapRect=pObj->GetSnapRect();
804                 if (nSnapPosX!=aSnapRect.Left()) bSnapPosXDC=sal_True;
805                 if (nSnapPosY!=aSnapRect.Top()) bSnapPosYDC=sal_True;
806                 if (nSnapWdt!=aSnapRect.GetWidth()-1) bSnapWdtDC=sal_True;
807                 if (nSnapHgt!=aSnapRect.GetHeight()-1) bSnapHgtDC=sal_True;
808             }
809             if (!bLogicWdtDC || !bLogicHgtDC || !bLogicWdtDiff || !bLogicHgtDiff) {
810                 aLogicRect=pObj->GetLogicRect();
811                 if (nLogicWdt!=aLogicRect.GetWidth()-1) bLogicWdtDC=sal_True;
812                 if (nLogicHgt!=aLogicRect.GetHeight()-1) bLogicHgtDC=sal_True;
813                 if (!bLogicWdtDiff && aSnapRect.GetWidth()!=aLogicRect.GetWidth()) bLogicWdtDiff=sal_True;
814                 if (!bLogicHgtDiff && aSnapRect.GetHeight()!=aLogicRect.GetHeight()) bLogicHgtDiff=sal_True;
815             }
816         }
817         if (!bObjNameDC ) {
818             if (!bObjNameSet) {
819                 aObjName=pObj->GetName();
820             } else {
821                 if (aObjName!=pObj->GetName()) bObjNameDC=sal_True;
822             }
823         }
824     }
825 
826     if (bSnapPosXDC || nAllSnapPosX!=nSnapPosX) rAttr.Put(SdrAllPositionXItem(nAllSnapPosX));
827     if (bSnapPosYDC || nAllSnapPosY!=nSnapPosY) rAttr.Put(SdrAllPositionYItem(nAllSnapPosY));
828     if (bSnapWdtDC  || nAllSnapWdt !=nSnapWdt ) rAttr.Put(SdrAllSizeWidthItem(nAllSnapWdt));
829     if (bSnapHgtDC  || nAllSnapHgt !=nSnapHgt ) rAttr.Put(SdrAllSizeHeightItem(nAllSnapHgt));
830 
831     // Items fuer reine Transformationen
832     rAttr.Put(SdrMoveXItem());
833     rAttr.Put(SdrMoveYItem());
834     rAttr.Put(SdrResizeXOneItem());
835     rAttr.Put(SdrResizeYOneItem());
836     rAttr.Put(SdrRotateOneItem());
837     rAttr.Put(SdrHorzShearOneItem());
838     rAttr.Put(SdrVertShearOneItem());
839 
840     if (nMarkAnz>1) {
841         rAttr.Put(SdrResizeXAllItem());
842         rAttr.Put(SdrResizeYAllItem());
843         rAttr.Put(SdrRotateAllItem());
844         rAttr.Put(SdrHorzShearAllItem());
845         rAttr.Put(SdrVertShearAllItem());
846     }
847 
848     if(eDragMode == SDRDRAG_ROTATE || eDragMode == SDRDRAG_MIRROR)
849     {
850         rAttr.Put(SdrTransformRef1XItem(GetRef1().X()));
851         rAttr.Put(SdrTransformRef1YItem(GetRef1().Y()));
852     }
853 
854     if(eDragMode == SDRDRAG_MIRROR)
855     {
856         rAttr.Put(SdrTransformRef2XItem(GetRef2().X()));
857         rAttr.Put(SdrTransformRef2YItem(GetRef2().Y()));
858     }
859 }
860 
861 SfxItemSet SdrEditView::GetAttrFromMarked(sal_Bool bOnlyHardAttr) const
862 {
863     SfxItemSet aSet(pMod->GetItemPool());
864     MergeAttrFromMarked(aSet,bOnlyHardAttr);
865     //the EE_FEATURE items should not be set with SetAttrToMarked (see error message there)
866     //so we do not set them here
867     // #i32448#
868     // Do not disable, but clear the items.
869     aSet.ClearItem(EE_FEATURE_TAB);
870     aSet.ClearItem(EE_FEATURE_LINEBR);
871     aSet.ClearItem(EE_FEATURE_NOTCONV);
872     aSet.ClearItem(EE_FEATURE_FIELD);
873     return aSet;
874 }
875 
876 void SdrEditView::MergeAttrFromMarked(SfxItemSet& rAttr, sal_Bool bOnlyHardAttr) const
877 {
878     sal_uInt32 nMarkAnz(GetMarkedObjectCount());
879 
880     for(sal_uInt32 a(0); a < nMarkAnz; a++)
881     {
882         // #80277# merging was done wrong in the prev version
883         //const SfxItemSet& rSet = GetMarkedObjectByIndex()->GetItemSet();
884         const SfxItemSet& rSet = GetMarkedObjectByIndex(a)->GetMergedItemSet();
885         SfxWhichIter aIter(rSet);
886         sal_uInt16 nWhich(aIter.FirstWhich());
887 
888         while(nWhich)
889         {
890             if(!bOnlyHardAttr)
891             {
892                 if(SFX_ITEM_DONTCARE == rSet.GetItemState(nWhich, sal_False))
893                     rAttr.InvalidateItem(nWhich);
894                 else
895                     rAttr.MergeValue(rSet.Get(nWhich), sal_True);
896             }
897             else if(SFX_ITEM_SET == rSet.GetItemState(nWhich, sal_False))
898             {
899                 const SfxPoolItem& rItem = rSet.Get(nWhich);
900                 rAttr.MergeValue(rItem, sal_True);
901             }
902 
903             nWhich = aIter.NextWhich();
904         }
905     }
906 }
907 
908 void SdrEditView::SetAttrToMarked(const SfxItemSet& rAttr, sal_Bool bReplaceAll)
909 {
910     if (AreObjectsMarked())
911     {
912 #ifdef DBG_UTIL
913         {
914             sal_Bool bHasEEFeatureItems=sal_False;
915             SfxItemIter aIter(rAttr);
916             const SfxPoolItem* pItem=aIter.FirstItem();
917             while (!bHasEEFeatureItems && pItem!=NULL) {
918                 if (!IsInvalidItem(pItem)) {
919                     sal_uInt16 nW=pItem->Which();
920                     if (nW>=EE_FEATURE_START && nW<=EE_FEATURE_END) bHasEEFeatureItems=sal_True;
921                 }
922                 pItem=aIter.NextItem();
923             }
924             if(bHasEEFeatureItems)
925             {
926                 String aMessage;
927                 aMessage.AppendAscii("SdrEditView::SetAttrToMarked(): Das setzen von EE_FEATURE-Items an der SdrView macht keinen Sinn! Es fuehrt nur zu Overhead und nicht mehr lesbaren Dokumenten.");
928                 InfoBox(NULL, aMessage).Execute();
929             }
930         }
931 #endif
932 
933         // #103836# if the user thets character attributes to the complete shape,
934         //          we want to remove all hard set character attributes with same
935         //          which ids from the text. We do that later but here we remember
936         //          all character attribute which id's that are set.
937         std::vector<sal_uInt16> aCharWhichIds;
938         {
939             SfxItemIter aIter(rAttr);
940             const SfxPoolItem* pItem=aIter.FirstItem();
941             while( pItem!=NULL )
942             {
943                 if (!IsInvalidItem(pItem))
944                 {
945                     sal_uInt16 nWhich = pItem->Which();
946                     if (nWhich>=EE_CHAR_START && nWhich<=EE_CHAR_END)
947                         aCharWhichIds.push_back( nWhich );
948                 }
949                 pItem=aIter.NextItem();
950             }
951         }
952 
953         // Joe, 2.7.98: Damit Undo nach Format.Standard auch die Textattribute korrekt restauriert
954         sal_Bool bHasEEItems=SearchOutlinerItems(rAttr,bReplaceAll);
955 
956         // AW 030100: save additional geom info when para or char attributes
957         // are changed and the geom form of the text object might be changed
958         sal_Bool bPossibleGeomChange(sal_False);
959         SfxWhichIter aIter(rAttr);
960         sal_uInt16 nWhich = aIter.FirstWhich();
961         while(!bPossibleGeomChange && nWhich)
962         {
963             SfxItemState eState = rAttr.GetItemState(nWhich);
964             if(eState == SFX_ITEM_SET)
965             {
966                 if((nWhich >= SDRATTR_TEXT_MINFRAMEHEIGHT && nWhich <= SDRATTR_TEXT_CONTOURFRAME)
967                     || nWhich == SDRATTR_3DOBJ_PERCENT_DIAGONAL
968                     || nWhich == SDRATTR_3DOBJ_BACKSCALE
969                     || nWhich == SDRATTR_3DOBJ_DEPTH
970                     || nWhich == SDRATTR_3DOBJ_END_ANGLE
971                     || nWhich == SDRATTR_3DSCENE_DISTANCE)
972                 {
973                     bPossibleGeomChange = sal_True;
974                 }
975             }
976             nWhich = aIter.NextWhich();
977         }
978 
979         const bool bUndo = IsUndoEnabled();
980         if( bUndo )
981         {
982             XubString aStr;
983             ImpTakeDescriptionStr(STR_EditSetAttributes,aStr);
984             BegUndo(aStr);
985         }
986 
987         const sal_uInt32 nMarkAnz(GetMarkedObjectCount());
988         std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
989 
990         // create ItemSet without SFX_ITEM_DONTCARE. Put()
991         // uses it's second parameter (bInvalidAsDefault) to
992         // remove all such items to set them to default.
993         SfxItemSet aAttr(*rAttr.GetPool(), rAttr.GetRanges());
994         aAttr.Put(rAttr, sal_True);
995 
996         // #i38135#
997         bool bResetAnimationTimer(false);
998 
999         for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
1000         {
1001             SdrMark* pM=GetSdrMarkByIndex(nm);
1002             SdrObject* pObj = pM->GetMarkedSdrObj();
1003 
1004             if( bUndo )
1005             {
1006                 std::vector< SdrUndoAction* > vConnectorUndoActions;
1007                 SdrEdgeObj* pEdgeObj = dynamic_cast< SdrEdgeObj* >( pObj );
1008                 if ( pEdgeObj )
1009                     bPossibleGeomChange = sal_True;
1010                 else if( bUndo )
1011                     vConnectorUndoActions = CreateConnectorUndo( *pObj );
1012 
1013                 AddUndoActions( vConnectorUndoActions );
1014             }
1015 
1016             // new geometry undo
1017             if(bPossibleGeomChange && bUndo)
1018             {
1019                 // save position and size of obect, too
1020                 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
1021             }
1022 
1023             if( bUndo )
1024             {
1025                 // #i8508#
1026                 // If this is a text object also rescue the OutlinerParaObject since
1027                 // applying attributes to the object may change text layout when
1028                 // multiple portions exist with multiple formats. If a OutlinerParaObject
1029                 // really exists and needs to be rescued is evaluated in the undo
1030                 // implementation itself.
1031                 const bool bRescueText = dynamic_cast< SdrTextObj* >(pObj) != 0;
1032 
1033                 // add attribute undo
1034                 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj,sal_False,bHasEEItems || bPossibleGeomChange || bRescueText));
1035             }
1036 
1037             // set up a scxene updater if object is a 3d object
1038             if(dynamic_cast< E3dObject* >(pObj))
1039             {
1040                 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pObj));
1041             }
1042 
1043             // set attributes at object
1044             pObj->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
1045 
1046             if(pObj->ISA(SdrTextObj))
1047             {
1048                 SdrTextObj* pTextObj = ((SdrTextObj*)pObj);
1049 
1050                 if(!aCharWhichIds.empty())
1051                 {
1052                     Rectangle aOldBoundRect = pTextObj->GetLastBoundRect();
1053 
1054                     // #110094#-14 pTextObj->SendRepaintBroadcast(pTextObj->GetBoundRect());
1055                     pTextObj->RemoveOutlinerCharacterAttribs( aCharWhichIds );
1056 
1057                     // object has changed, should be called form
1058                     // RemoveOutlinerCharacterAttribs. This will change when the text
1059                     // object implementation changes.
1060                     pTextObj->SetChanged();
1061 
1062                     pTextObj->BroadcastObjectChange();
1063                     pTextObj->SendUserCall(SDRUSERCALL_CHGATTR, aOldBoundRect);
1064                 }
1065             }
1066 
1067             // #i38495#
1068             if(!bResetAnimationTimer)
1069             {
1070                 if(pObj->GetViewContact().isAnimatedInAnyViewObjectContact())
1071                 {
1072                     bResetAnimationTimer = true;
1073                 }
1074             }
1075         }
1076 
1077         // fire scene updaters
1078         while(!aUpdaters.empty())
1079         {
1080             delete aUpdaters.back();
1081             aUpdaters.pop_back();
1082         }
1083 
1084         // #i38135#
1085         if(bResetAnimationTimer)
1086         {
1087             SetAnimationTimer(0L);
1088         }
1089 
1090         // besser vorher checken, was gemacht werden soll:
1091         // pObj->SetAttr() oder SetNotPersistAttr()
1092         // !!! fehlende Implementation !!!
1093         SetNotPersistAttrToMarked(rAttr,bReplaceAll);
1094 
1095         if( bUndo )
1096             EndUndo();
1097     }
1098 }
1099 
1100 SfxStyleSheet* SdrEditView::GetStyleSheetFromMarked() const
1101 {
1102     SfxStyleSheet* pRet=NULL;
1103     sal_Bool b1st=sal_True;
1104     sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
1105     for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++) {
1106         SdrMark* pM=GetSdrMarkByIndex(nm);
1107         SfxStyleSheet* pSS=pM->GetMarkedSdrObj()->GetStyleSheet();
1108         if (b1st) pRet=pSS;
1109         else if (pRet!=pSS) return NULL; // verschiedene StyleSheets
1110         b1st=sal_False;
1111     }
1112     return pRet;
1113 }
1114 
1115 void SdrEditView::SetStyleSheetToMarked(SfxStyleSheet* pStyleSheet, sal_Bool bDontRemoveHardAttr)
1116 {
1117     if (AreObjectsMarked())
1118     {
1119         const bool bUndo = IsUndoEnabled();
1120 
1121         if( bUndo )
1122         {
1123             XubString aStr;
1124             if (pStyleSheet!=NULL)
1125                 ImpTakeDescriptionStr(STR_EditSetStylesheet,aStr);
1126             else
1127                 ImpTakeDescriptionStr(STR_EditDelStylesheet,aStr);
1128             BegUndo(aStr);
1129         }
1130 
1131         sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
1132         for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
1133         {
1134             SdrMark* pM=GetSdrMarkByIndex(nm);
1135             if( bUndo )
1136             {
1137                 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pM->GetMarkedSdrObj()));
1138                 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pM->GetMarkedSdrObj(),true,true));
1139             }
1140             pM->GetMarkedSdrObj()->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1141         }
1142 
1143         if( bUndo )
1144             EndUndo();
1145     }
1146 }
1147 
1148 ////////////////////////////////////////////////////////////////////////////////////////////////////
1149 
1150 /* new interface src537 */
1151 sal_Bool SdrEditView::GetAttributes(SfxItemSet& rTargetSet, sal_Bool bOnlyHardAttr) const
1152 {
1153     if(GetMarkedObjectCount())
1154     {
1155         rTargetSet.Put(GetAttrFromMarked(bOnlyHardAttr), sal_False);
1156         return sal_True;
1157     }
1158     else
1159     {
1160         return SdrMarkView::GetAttributes(rTargetSet, bOnlyHardAttr);
1161     }
1162 }
1163 
1164 sal_Bool SdrEditView::SetAttributes(const SfxItemSet& rSet, sal_Bool bReplaceAll)
1165 {
1166     if (GetMarkedObjectCount()!=0) {
1167         SetAttrToMarked(rSet,bReplaceAll);
1168         return sal_True;
1169     } else {
1170         return SdrMarkView::SetAttributes(rSet,bReplaceAll);
1171     }
1172 }
1173 
1174 SfxStyleSheet* SdrEditView::GetStyleSheet() const // SfxStyleSheet* SdrEditView::GetStyleSheet(sal_Bool& rOk) const
1175 {
1176     if (GetMarkedObjectCount()!=0) {
1177         //rOk=sal_True;
1178         return GetStyleSheetFromMarked();
1179     } else {
1180         return SdrMarkView::GetStyleSheet(); // SdrMarkView::GetStyleSheet(rOk);
1181     }
1182 }
1183 
1184 sal_Bool SdrEditView::SetStyleSheet(SfxStyleSheet* pStyleSheet, sal_Bool bDontRemoveHardAttr)
1185 {
1186     if (GetMarkedObjectCount()!=0) {
1187         SetStyleSheetToMarked(pStyleSheet,bDontRemoveHardAttr);
1188         return sal_True;
1189     } else {
1190         return SdrMarkView::SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1191     }
1192 }
1193 
1194 ////////////////////////////////////////////////////////////////////////////////////////////////////
1195 
1196 SfxItemSet SdrEditView::GetGeoAttrFromMarked() const
1197 {
1198     SfxItemSet aRetSet(pMod->GetItemPool(),   // SID_ATTR_TRANSFORM_... aus s:svxids.hrc
1199                        SID_ATTR_TRANSFORM_POS_X,SID_ATTR_TRANSFORM_ANGLE,
1200                        SID_ATTR_TRANSFORM_PROTECT_POS,SID_ATTR_TRANSFORM_AUTOHEIGHT,
1201                        SDRATTR_ECKENRADIUS,SDRATTR_ECKENRADIUS,
1202                        0);
1203     if (AreObjectsMarked()) {
1204         SfxItemSet aMarkAttr(GetAttrFromMarked(sal_False)); // wg. AutoGrowHeight und Eckenradius
1205         Rectangle aRect(GetMarkedObjRect());
1206 
1207         if(GetSdrPageView())
1208         {
1209             GetSdrPageView()->LogicToPagePos(aRect);
1210         }
1211 
1212         // Position
1213         aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_X,aRect.Left()));
1214         aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_Y,aRect.Top()));
1215 
1216         // Groesse
1217         long nResizeRefX=aRect.Left();
1218         long nResizeRefY=aRect.Top();
1219         if (eDragMode==SDRDRAG_ROTATE) { // Drehachse auch als Referenz fuer Resize
1220             nResizeRefX=aRef1.X();
1221             nResizeRefY=aRef1.Y();
1222         }
1223         aRetSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_WIDTH,aRect.Right()-aRect.Left()));
1224         aRetSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_HEIGHT,aRect.Bottom()-aRect.Top()));
1225         aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_RESIZE_REF_X,nResizeRefX));
1226         aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_RESIZE_REF_Y,nResizeRefY));
1227 
1228         Point aRotateAxe(aRef1);
1229 
1230         if(GetSdrPageView())
1231         {
1232             GetSdrPageView()->LogicToPagePos(aRotateAxe);
1233         }
1234 
1235         // Drehung
1236         long nRotateRefX=aRect.Center().X();
1237         long nRotateRefY=aRect.Center().Y();
1238         if (eDragMode==SDRDRAG_ROTATE) {
1239             nRotateRefX=aRotateAxe.X();
1240             nRotateRefY=aRotateAxe.Y();
1241         }
1242         aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ANGLE,GetMarkedObjRotate()));
1243         aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_X,nRotateRefX));
1244         aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_Y,nRotateRefY));
1245 
1246         // Shear
1247         long nShearRefX=aRect.Left();
1248         long nShearRefY=aRect.Bottom();
1249         if (eDragMode==SDRDRAG_ROTATE) { // Drehachse auch als Referenz fuer Shear
1250             nShearRefX=aRotateAxe.X();
1251             nShearRefY=aRotateAxe.Y();
1252         }
1253         aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR,GetMarkedObjShear()));
1254         aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_X,nShearRefX));
1255         aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_Y,nShearRefY));
1256 
1257         // Pruefen der einzelnen Objekte, ob Objekte geschuetzt sind
1258         const SdrMarkList& rMarkList=GetMarkedObjectList();
1259         sal_uIntPtr nMarkCount=rMarkList.GetMarkCount();
1260         SdrObject* pObj=rMarkList.GetMark(0)->GetMarkedSdrObj();
1261         sal_Bool bPosProt=pObj->IsMoveProtect();
1262         sal_Bool bSizProt=pObj->IsResizeProtect();
1263         sal_Bool bPosProtDontCare=sal_False;
1264         sal_Bool bSizProtDontCare=sal_False;
1265         for (sal_uIntPtr i=1; i<nMarkCount && (!bPosProtDontCare || !bSizProtDontCare); i++) {
1266             pObj=rMarkList.GetMark(i)->GetMarkedSdrObj();
1267             if (bPosProt!=pObj->IsMoveProtect()) bPosProtDontCare=sal_True;
1268             if (bSizProt!=pObj->IsResizeProtect()) bSizProtDontCare=sal_True;
1269         }
1270 
1271         // InvalidateItem setzt das Item auf DONT_CARE
1272         if (bPosProtDontCare) {
1273             aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_PROTECT_POS);
1274         } else {
1275             aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_PROTECT_POS,bPosProt));
1276         }
1277         if (bSizProtDontCare) {
1278             aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_PROTECT_SIZE);
1279         } else {
1280             aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_PROTECT_SIZE,bSizProt));
1281         }
1282 
1283         SfxItemState eState=aMarkAttr.GetItemState(SDRATTR_TEXT_AUTOGROWWIDTH);
1284         sal_Bool bAutoGrow=((SdrTextAutoGrowWidthItem&)(aMarkAttr.Get(SDRATTR_TEXT_AUTOGROWWIDTH))).GetValue();
1285         if (eState==SFX_ITEM_DONTCARE) {
1286             aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_AUTOWIDTH);
1287         } else if (eState==SFX_ITEM_SET) {
1288             aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_AUTOWIDTH,bAutoGrow));
1289         }
1290 
1291         eState=aMarkAttr.GetItemState(SDRATTR_TEXT_AUTOGROWHEIGHT);
1292         bAutoGrow=((SdrTextAutoGrowHeightItem&)(aMarkAttr.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue();
1293         if (eState==SFX_ITEM_DONTCARE) {
1294             aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_AUTOHEIGHT);
1295         } else if (eState==SFX_ITEM_SET) {
1296             aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_AUTOHEIGHT,bAutoGrow));
1297         }
1298 
1299         eState=aMarkAttr.GetItemState(SDRATTR_ECKENRADIUS);
1300         long nRadius=((SdrEckenradiusItem&)(aMarkAttr.Get(SDRATTR_ECKENRADIUS))).GetValue();
1301         if (eState==SFX_ITEM_DONTCARE) {
1302             aRetSet.InvalidateItem(SDRATTR_ECKENRADIUS);
1303         } else if (eState==SFX_ITEM_SET) {
1304             aRetSet.Put(SdrEckenradiusItem(nRadius));
1305         }
1306 
1307     }
1308     return aRetSet;
1309 }
1310 
1311 Point ImpGetPoint(Rectangle aRect, RECT_POINT eRP)
1312 {
1313     switch(eRP) {
1314         case RP_LT: return aRect.TopLeft();
1315         case RP_MT: return aRect.TopCenter();
1316         case RP_RT: return aRect.TopRight();
1317         case RP_LM: return aRect.LeftCenter();
1318         case RP_MM: return aRect.Center();
1319         case RP_RM: return aRect.RightCenter();
1320         case RP_LB: return aRect.BottomLeft();
1321         case RP_MB: return aRect.BottomCenter();
1322         case RP_RB: return aRect.BottomRight();
1323     }
1324     return Point(); // Sollte nicht vorkommen !
1325 }
1326 
1327 void SdrEditView::SetGeoAttrToMarked(const SfxItemSet& rAttr)
1328 {
1329     Rectangle aRect(GetMarkedObjRect());
1330 
1331     if(GetSdrPageView())
1332     {
1333         GetSdrPageView()->LogicToPagePos(aRect);
1334     }
1335 
1336     long nOldRotateAngle=GetMarkedObjRotate();
1337     long nOldShearAngle=GetMarkedObjShear();
1338     const SdrMarkList& rMarkList=GetMarkedObjectList();
1339     sal_uIntPtr nMarkCount=rMarkList.GetMarkCount();
1340     SdrObject* pObj=NULL;
1341 
1342     RECT_POINT eSizePoint=RP_MM;
1343     long nPosDX=0;
1344     long nPosDY=0;
1345     long nSizX=0;
1346     long nSizY=0;
1347     long nRotateAngle=0;
1348 
1349     // #86909#
1350     sal_Bool bModeIsRotate(eDragMode == SDRDRAG_ROTATE);
1351     long nRotateX(0);
1352     long nRotateY(0);
1353     long nOldRotateX(0);
1354     long nOldRotateY(0);
1355     if(bModeIsRotate)
1356     {
1357         Point aRotateAxe(aRef1);
1358 
1359         if(GetSdrPageView())
1360         {
1361             GetSdrPageView()->LogicToPagePos(aRotateAxe);
1362         }
1363 
1364         nRotateX = nOldRotateX = aRotateAxe.X();
1365         nRotateY = nOldRotateY = aRotateAxe.Y();
1366     }
1367 
1368     long nNewShearAngle=0;
1369     long nShearAngle=0;
1370     long nShearX=0;
1371     long nShearY=0;
1372     sal_Bool bShearVert=sal_False;
1373 
1374     sal_Bool bChgPos=sal_False;
1375     sal_Bool bChgSiz=sal_False;
1376     sal_Bool bChgHgt=sal_False;
1377     sal_Bool bRotate=sal_False;
1378     sal_Bool bShear =sal_False;
1379 
1380     sal_Bool bSetAttr=sal_False;
1381     SfxItemSet aSetAttr(pMod->GetItemPool());
1382 
1383     const SfxPoolItem* pPoolItem=NULL;
1384 
1385     // Position
1386     if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_POS_X,sal_True,&pPoolItem)) {
1387         nPosDX=((const SfxInt32Item*)pPoolItem)->GetValue()-aRect.Left();
1388         bChgPos=sal_True;
1389     }
1390     if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_POS_Y,sal_True,&pPoolItem)){
1391         nPosDY=((const SfxInt32Item*)pPoolItem)->GetValue()-aRect.Top();
1392         bChgPos=sal_True;
1393     }
1394     // Groesse
1395     if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_WIDTH,sal_True,&pPoolItem)) {
1396         nSizX=((const SfxUInt32Item*)pPoolItem)->GetValue();
1397         bChgSiz=sal_True;
1398     }
1399     if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_HEIGHT,sal_True,&pPoolItem)) {
1400         nSizY=((const SfxUInt32Item*)pPoolItem)->GetValue();
1401         bChgSiz=sal_True;
1402         bChgHgt=sal_True;
1403     }
1404     if (bChgSiz) {
1405         eSizePoint=(RECT_POINT)((const SfxAllEnumItem&)rAttr.Get(SID_ATTR_TRANSFORM_SIZE_POINT)).GetValue();
1406     }
1407 
1408     // Rotation
1409     if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ANGLE,sal_True,&pPoolItem)) {
1410         nRotateAngle=((const SfxInt32Item*)pPoolItem)->GetValue()-nOldRotateAngle;
1411         bRotate = (nRotateAngle != 0);
1412     }
1413 
1414     // #86909# pos rot point x
1415     if(bRotate || SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ROT_X, sal_True ,&pPoolItem))
1416         nRotateX = ((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_ROT_X)).GetValue();
1417 
1418     // #86909# pos rot point y
1419     if(bRotate || SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ROT_Y, sal_True ,&pPoolItem))
1420         nRotateY = ((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_ROT_Y)).GetValue();
1421 
1422     // Shear
1423     if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_SHEAR,sal_True,&pPoolItem)) {
1424         nNewShearAngle=((const SfxInt32Item*)pPoolItem)->GetValue();
1425         if (nNewShearAngle>SDRMAXSHEAR) nNewShearAngle=SDRMAXSHEAR;
1426         if (nNewShearAngle<-SDRMAXSHEAR) nNewShearAngle=-SDRMAXSHEAR;
1427         if (nNewShearAngle!=nOldShearAngle) {
1428             bShearVert=((const SfxBoolItem&)rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_VERTICAL)).GetValue();
1429             if (bShearVert) {
1430                 nShearAngle=nNewShearAngle;
1431             } else {
1432                 if (nNewShearAngle!=0 && nOldShearAngle!=0) {
1433                     // Bugfix #25714#.
1434                     double nOld=tan((double)nOldShearAngle*nPi180);
1435                     double nNew=tan((double)nNewShearAngle*nPi180);
1436                     nNew-=nOld;
1437                     nNew=atan(nNew)/nPi180;
1438                     nShearAngle=Round(nNew);
1439                 } else {
1440                     nShearAngle=nNewShearAngle-nOldShearAngle;
1441                 }
1442             }
1443             bShear=nShearAngle!=0;
1444             if (bShear) {
1445                 nShearX=((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_X)).GetValue();
1446                 nShearY=((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_Y)).GetValue();
1447             }
1448         }
1449     }
1450 
1451     // AutoGrow
1452     if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_AUTOWIDTH,sal_True,&pPoolItem)) {
1453         sal_Bool bAutoGrow=((const SfxBoolItem*)pPoolItem)->GetValue();
1454         aSetAttr.Put(SdrTextAutoGrowWidthItem(bAutoGrow));
1455         bSetAttr=sal_True;
1456     }
1457 
1458     if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_AUTOHEIGHT,sal_True,&pPoolItem)) {
1459         sal_Bool bAutoGrow=((const SfxBoolItem*)pPoolItem)->GetValue();
1460         aSetAttr.Put(SdrTextAutoGrowHeightItem(bAutoGrow));
1461         bSetAttr=sal_True;
1462     }
1463 
1464     // Eckenradius
1465     if (bEdgeRadiusAllowed && SFX_ITEM_SET==rAttr.GetItemState(SDRATTR_ECKENRADIUS,sal_True,&pPoolItem)) {
1466         long nRadius=((SdrEckenradiusItem*)pPoolItem)->GetValue();
1467         aSetAttr.Put(SdrEckenradiusItem(nRadius));
1468         bSetAttr=sal_True;
1469     }
1470 
1471     ForcePossibilities();
1472 
1473     BegUndo(ImpGetResStr(STR_EditTransform),GetDescriptionOfMarkedObjects());
1474 
1475     if (bSetAttr) {
1476         SetAttrToMarked(aSetAttr,sal_False);
1477     }
1478 
1479     // Groesse und Hoehe aendern
1480     if (bChgSiz && (bResizeFreeAllowed || bResizePropAllowed)) {
1481         Fraction aWdt(nSizX,aRect.Right()-aRect.Left());
1482         Fraction aHgt(nSizY,aRect.Bottom()-aRect.Top());
1483         Point aRef(ImpGetPoint(aRect,eSizePoint));
1484 
1485         if(GetSdrPageView())
1486         {
1487             GetSdrPageView()->PagePosToLogic(aRef);
1488         }
1489 
1490         ResizeMarkedObj(aRef,aWdt,aHgt);
1491     }
1492 
1493     // Rotieren
1494     if (bRotate && (bRotateFreeAllowed || bRotate90Allowed)) {
1495         Point aRef(nRotateX,nRotateY);
1496 
1497         if(GetSdrPageView())
1498         {
1499             GetSdrPageView()->PagePosToLogic(aRef);
1500         }
1501 
1502         RotateMarkedObj(aRef,nRotateAngle);
1503     }
1504 
1505     // #86909# set rotation point position
1506     if(bModeIsRotate && (nRotateX != nOldRotateX || nRotateY != nOldRotateY))
1507     {
1508         Point aNewRef1(nRotateX, nRotateY);
1509 
1510         if(GetSdrPageView())
1511         {
1512             GetSdrPageView()->PagePosToLogic(aNewRef1);
1513         }
1514 
1515         SetRef1(aNewRef1);
1516     }
1517 
1518     // Shear
1519     if (bShear && bShearAllowed) {
1520         Point aRef(nShearX,nShearY);
1521 
1522         if(GetSdrPageView())
1523         {
1524             GetSdrPageView()->PagePosToLogic(aRef);
1525         }
1526 
1527         ShearMarkedObj(aRef,nShearAngle,bShearVert);
1528 
1529         // #i74358#
1530         // ShearMarkedObj creates a linear combination of the existing transformation and
1531         // the new shear to apply. If the object is already transformed (e.g. rotated) the
1532         // linear combination will not decompose to the same start values again, but to a
1533         // new combination. Thus it makes no sense to check if the wanted shear is reached
1534         // or not. Taking out.
1535 #if 0
1536         long nTempAngle=GetMarkedObjShear();
1537         if (nTempAngle!=0 && nTempAngle!=nNewShearAngle && !bShearVert) {
1538             // noch eine 2. Iteration zur Kompensation der Rundungsfehler
1539             double nOld=tan((double)nTempAngle*nPi180);
1540             double nNew=tan((double)nNewShearAngle*nPi180);
1541             nNew-=nOld;
1542             nNew=atan(nNew)/nPi180;
1543             nTempAngle=Round(nNew);
1544             if (nTempAngle!=0) {
1545                 ShearMarkedObj(aRef,nTempAngle,bShearVert);
1546             }
1547         }
1548 #endif
1549     }
1550 
1551     // Position aendern
1552     if (bChgPos && bMoveAllowed) {
1553         MoveMarkedObj(Size(nPosDX,nPosDY));
1554     }
1555 
1556     // protect position
1557     if(SFX_ITEM_SET == rAttr.GetItemState(SID_ATTR_TRANSFORM_PROTECT_POS, sal_True, &pPoolItem))
1558     {
1559         const sal_Bool bProtPos(((const SfxBoolItem*)pPoolItem)->GetValue());
1560         bool bChanged(false);
1561 
1562         for(sal_uInt32 i(0); i < nMarkCount; i++)
1563         {
1564             pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
1565 
1566             if(pObj->IsMoveProtect() != bProtPos)
1567             {
1568                 bChanged = true;
1569                 pObj->SetMoveProtect(bProtPos);
1570 
1571                 if(bProtPos)
1572                 {
1573                     pObj->SetResizeProtect(true);
1574                 }
1575             }
1576         }
1577 
1578         if(bChanged)
1579         {
1580             bMoveProtect = bProtPos;
1581 
1582             if(bProtPos)
1583             {
1584                 bResizeProtect = true;
1585             }
1586 
1587             // #i77187# there is no simple method to get the toolbars updated
1588             // in the application. The App is listening to selection change and i
1589             // will use it here (even if not true). It's acceptable since changing
1590             // this model data is pretty rare and only possible using the F4 dialog
1591             MarkListHasChanged();
1592         }
1593     }
1594 
1595     if(!bMoveProtect)
1596     {
1597         // protect size
1598         if(SFX_ITEM_SET == rAttr.GetItemState(SID_ATTR_TRANSFORM_PROTECT_SIZE, sal_True, &pPoolItem))
1599         {
1600             const sal_Bool bProtSize(((const SfxBoolItem*)pPoolItem)->GetValue());
1601             bool bChanged(false);
1602 
1603             for(sal_uInt32 i(0); i < nMarkCount; i++)
1604             {
1605                 pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
1606 
1607                 if(pObj->IsResizeProtect() != bProtSize)
1608                 {
1609                     bChanged = true;
1610                     pObj->SetResizeProtect(bProtSize);
1611                 }
1612             }
1613 
1614             if(bChanged)
1615             {
1616                 bResizeProtect = bProtSize;
1617 
1618                 // #i77187# see above
1619                 MarkListHasChanged();
1620             }
1621         }
1622     }
1623 
1624     EndUndo();
1625 }
1626 
1627 ////////////////////////////////////////////////////////////////////////////////////////////////////
1628 
1629 sal_Bool SdrEditView::IsAlignPossible() const
1630 {  // Mindestens 2 markierte Objekte, davon mind. 1 beweglich
1631     ForcePossibilities();
1632     sal_uIntPtr nAnz=GetMarkedObjectCount();
1633     if (nAnz==0) return sal_False;         // Nix markiert!
1634     if (nAnz==1) return bMoveAllowed;  // einzelnes Obj an der Seite ausrichten
1635     return bOneOrMoreMovable;          // ansonsten ist MarkCount>=2
1636 }
1637 
1638 void SdrEditView::AlignMarkedObjects(SdrHorAlign eHor, SdrVertAlign eVert, sal_Bool bBoundRects)
1639 {
1640     if (eHor==SDRHALIGN_NONE && eVert==SDRVALIGN_NONE)
1641         return;
1642 
1643     SortMarkedObjects();
1644     if (GetMarkedObjectCount()<1)
1645         return;
1646 
1647     const bool bUndo = IsUndoEnabled();
1648     if( bUndo )
1649     {
1650         XubString aStr(GetDescriptionOfMarkedObjects());
1651         if (eHor==SDRHALIGN_NONE)
1652         {
1653             switch (eVert)
1654             {
1655                 case SDRVALIGN_TOP   : ImpTakeDescriptionStr(STR_EditAlignVTop   ,aStr); break;
1656                 case SDRVALIGN_BOTTOM: ImpTakeDescriptionStr(STR_EditAlignVBottom,aStr); break;
1657                 case SDRVALIGN_CENTER: ImpTakeDescriptionStr(STR_EditAlignVCenter,aStr); break;
1658                 default: break;
1659             }
1660         }
1661         else if (eVert==SDRVALIGN_NONE)
1662         {
1663             switch (eHor)
1664             {
1665                 case SDRHALIGN_LEFT  : ImpTakeDescriptionStr(STR_EditAlignHLeft  ,aStr); break;
1666                 case SDRHALIGN_RIGHT : ImpTakeDescriptionStr(STR_EditAlignHRight ,aStr); break;
1667                 case SDRHALIGN_CENTER: ImpTakeDescriptionStr(STR_EditAlignHCenter,aStr); break;
1668                 default: break;
1669             }
1670         }
1671         else if (eHor==SDRHALIGN_CENTER && eVert==SDRVALIGN_CENTER)
1672         {
1673             ImpTakeDescriptionStr(STR_EditAlignCenter,aStr);
1674         }
1675         else
1676         {
1677             ImpTakeDescriptionStr(STR_EditAlign,aStr);
1678         }
1679         BegUndo(aStr);
1680     }
1681 
1682     Rectangle aBound;
1683     sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
1684     sal_uIntPtr nm;
1685     sal_Bool bHasFixed=sal_False;
1686     for (nm=0; nm<nMarkAnz; nm++)
1687     {
1688         SdrMark* pM=GetSdrMarkByIndex(nm);
1689         SdrObject* pObj=pM->GetMarkedSdrObj();
1690         SdrObjTransformInfoRec aInfo;
1691         pObj->TakeObjInfo(aInfo);
1692         if (!aInfo.bMoveAllowed || pObj->IsMoveProtect())
1693         {
1694             Rectangle aObjRect(bBoundRects?pObj->GetCurrentBoundRect():pObj->GetSnapRect());
1695             aBound.Union(aObjRect);
1696             bHasFixed=sal_True;
1697         }
1698     }
1699     if (!bHasFixed)
1700     {
1701         if (nMarkAnz==1)
1702         {   // einzelnes Obj an der Seite ausrichten
1703             const SdrObject* pObj=GetMarkedObjectByIndex(0L);
1704             const SdrPage* pPage=pObj->GetPage();
1705             const SdrPageGridFrameList* pGFL=pPage->GetGridFrameList(GetSdrPageViewOfMarkedByIndex(0),&(pObj->GetSnapRect()));
1706             const SdrPageGridFrame* pFrame=NULL;
1707             if (pGFL!=NULL && pGFL->GetCount()!=0)
1708             { // Writer
1709                 pFrame=&((*pGFL)[0]);
1710             }
1711 
1712             if (pFrame!=NULL)
1713             { // Writer
1714                 aBound=pFrame->GetUserArea();
1715             }
1716             else
1717             {
1718                 aBound=Rectangle(pPage->GetLftBorder(),pPage->GetUppBorder(),
1719                                  pPage->GetWdt()-pPage->GetRgtBorder(),
1720                                  pPage->GetHgt()-pPage->GetLwrBorder());
1721             }
1722         }
1723         else
1724         {
1725             if (bBoundRects)
1726                 aBound=GetMarkedObjBoundRect();
1727             else
1728                 aBound=GetMarkedObjRect();
1729         }
1730     }
1731     Point aCenter(aBound.Center());
1732     for (nm=0; nm<nMarkAnz; nm++)
1733     {
1734         SdrMark* pM=GetSdrMarkByIndex(nm);
1735         SdrObject* pObj=pM->GetMarkedSdrObj();
1736         SdrObjTransformInfoRec aInfo;
1737         pObj->TakeObjInfo(aInfo);
1738         if (aInfo.bMoveAllowed && !pObj->IsMoveProtect())
1739         {
1740             // SdrPageView* pPV=pM->GetPageView();
1741             long nXMov=0;
1742             long nYMov=0;
1743             Rectangle aObjRect(bBoundRects?pObj->GetCurrentBoundRect():pObj->GetSnapRect());
1744             switch (eVert)
1745             {
1746                 case SDRVALIGN_TOP   : nYMov=aBound.Top()   -aObjRect.Top()       ; break;
1747                 case SDRVALIGN_BOTTOM: nYMov=aBound.Bottom()-aObjRect.Bottom()    ; break;
1748                 case SDRVALIGN_CENTER: nYMov=aCenter.Y()    -aObjRect.Center().Y(); break;
1749                 default: break;
1750             }
1751             switch (eHor)
1752             {
1753                 case SDRHALIGN_LEFT  : nXMov=aBound.Left()  -aObjRect.Left()      ; break;
1754                 case SDRHALIGN_RIGHT : nXMov=aBound.Right() -aObjRect.Right()     ; break;
1755                 case SDRHALIGN_CENTER: nXMov=aCenter.X()    -aObjRect.Center().X(); break;
1756                 default: break;
1757             }
1758             if (nXMov!=0 || nYMov!=0)
1759             {
1760                 // #104104# SdrEdgeObj needs an extra SdrUndoGeoObj since the
1761                 // connections may need to be saved
1762                 if( bUndo )
1763                 {
1764                     if( dynamic_cast<SdrEdgeObj*>(pObj) )
1765                     {
1766                         AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
1767                     }
1768 
1769                     AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pObj,Size(nXMov,nYMov)));
1770                 }
1771 
1772                 pObj->Move(Size(nXMov,nYMov));
1773             }
1774         }
1775     }
1776 
1777     if( bUndo )
1778         EndUndo();
1779 }
1780 
1781