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