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