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