bump product version to 4.1.6.2
[LibreOffice.git] / svx / source / svdraw / svdedtv1.cxx
blob85ea67dafe7b10527421ee0c27a451fe6e85d658
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <svx/svdedtv.hxx>
22 #include <math.h>
24 #include <tools/bigint.hxx>
25 #include <svl/itemiter.hxx>
26 #include <vcl/msgbox.hxx>
27 #include <svx/rectenum.hxx>
28 #include <svx/svxids.hrc> // for SID_ATTR_TRANSFORM_...
29 #include <svx/svdattr.hxx> // for Get/SetGeoAttr
30 #include "svx/svditer.hxx"
31 #include <svx/svdtrans.hxx>
32 #include <svx/svdundo.hxx>
33 #include <svx/svdpage.hxx>
34 #include <svx/svdpagv.hxx>
35 #include <svx/svdlayer.hxx> // for MergeNotPersistAttr
36 #include <svx/svdattrx.hxx> // for MergeNotPersistAttr
37 #include <svx/svdetc.hxx> // for SearchOutlinerItems
38 #include <svx/svdopath.hxx> // for Crook
39 #include "svx/svdstr.hrc" // names taken from the resource
40 #include "svx/svdglob.hxx" // StringCache
41 #include <editeng/editdata.hxx>
42 #include <editeng/eeitem.hxx>
43 #include <svl/aeitem.hxx>
44 #include <svl/whiter.hxx>
45 #include <svx/sdr/contact/objectcontact.hxx>
46 #include <svx/sdr/contact/viewcontact.hxx>
47 #include <svx/e3dsceneupdater.hxx>
48 #include <svx/obj3d.hxx>
49 #include <basegfx/matrix/b2dhommatrix.hxx>
50 #include <svx/AffineMatrixItem.hxx>
51 #include <basegfx/matrix/b2dhommatrixtools.hxx>
52 #include <svx/xlnwtit.hxx>
53 #include <svx/xlnstwit.hxx>
54 #include <svx/xlnedwit.hxx>
56 ////////////////////////////////////////////////////////////////////////////////////////////////////
57 ////////////////////////////////////////////////////////////////////////////////////////////////////
58 // EditView
59 ////////////////////////////////////////////////////////////////////////////////////////////////////
60 ////////////////////////////////////////////////////////////////////////////////////////////////////
62 void SdrEditView::SetMarkedObjRect(const Rectangle& rRect, sal_Bool bCopy)
64 DBG_ASSERT(!rRect.IsEmpty(),"SetMarkedObjRect() with an empty Rect does not make sense.");
65 if (rRect.IsEmpty()) return;
66 sal_uIntPtr nAnz=GetMarkedObjectCount();
67 if (nAnz==0) return;
68 Rectangle aR0(GetMarkedObjRect());
69 DBG_ASSERT(!aR0.IsEmpty(),"SetMarkedObjRect(): GetMarkedObjRect() is empty.");
70 if (aR0.IsEmpty()) return;
71 long x0=aR0.Left();
72 long y0=aR0.Top();
73 long w0=aR0.Right()-x0;
74 long h0=aR0.Bottom()-y0;
75 long x1=rRect.Left();
76 long y1=rRect.Top();
77 long w1=rRect.Right()-x1;
78 long h1=rRect.Bottom()-y1;
79 XubString aStr;
80 ImpTakeDescriptionStr(STR_EditPosSize,aStr);
81 if (bCopy)
82 aStr+=ImpGetResStr(STR_EditWithCopy);
84 const bool bUndo = IsUndoEnabled();
85 if( bUndo )
86 BegUndo(aStr);
88 if (bCopy)
89 CopyMarkedObj();
91 for (sal_uIntPtr nm=0; nm<nAnz; nm++)
93 SdrMark* pM=GetSdrMarkByIndex(nm);
94 SdrObject* pO=pM->GetMarkedSdrObj();
95 if( bUndo )
96 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
98 Rectangle aR1(pO->GetSnapRect());
99 if (!aR1.IsEmpty())
101 if (aR1==aR0)
103 aR1=rRect;
105 else
106 { // transform aR1 to aR0 after rRect
107 aR1.Move(-x0,-y0);
108 BigInt l(aR1.Left());
109 BigInt r(aR1.Right());
110 BigInt t(aR1.Top());
111 BigInt b(aR1.Bottom());
112 if (w0!=0) {
113 l*=w1; l/=w0;
114 r*=w1; r/=w0;
115 } else {
116 l=0; r=w1;
118 if (h0!=0) {
119 t*=h1; t/=h0;
120 b*=h1; b/=h0;
121 } else {
122 t=0; b=h1;
124 aR1.Left ()=long(l);
125 aR1.Right ()=long(r);
126 aR1.Top ()=long(t);
127 aR1.Bottom()=long(b);
128 aR1.Move(x1,y1);
130 pO->SetSnapRect(aR1);
131 } else {
132 OSL_FAIL("SetMarkedObjRect(): pObj->GetSnapRect() returns empty Rect");
135 if( bUndo )
136 EndUndo();
139 std::vector< SdrUndoAction* > SdrEditView::CreateConnectorUndo( SdrObject& rO )
141 std::vector< SdrUndoAction* > vUndoActions;
143 if ( rO.GetBroadcaster() )
145 const SdrPage* pPage = rO.GetPage();
146 if ( pPage )
148 SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS );
149 while( aIter.IsMore() )
151 SdrObject* pPartObj = aIter.Next();
152 if ( pPartObj->ISA( SdrEdgeObj ) )
154 if ( ( pPartObj->GetConnectedNode( sal_False ) == &rO ) ||
155 ( pPartObj->GetConnectedNode( sal_True ) == &rO ) )
157 vUndoActions.push_back( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject( *pPartObj ) );
163 return vUndoActions;
166 void SdrEditView::AddUndoActions( std::vector< SdrUndoAction* >& rUndoActions )
168 std::vector< SdrUndoAction* >::iterator aUndoActionIter( rUndoActions.begin() );
169 while( aUndoActionIter != rUndoActions.end() )
170 AddUndo( *aUndoActionIter++ );
173 void SdrEditView::MoveMarkedObj(const Size& rSiz, bool bCopy)
175 const bool bUndo = IsUndoEnabled();
177 if( bUndo )
179 XubString aStr(ImpGetResStr(STR_EditMove));
180 if (bCopy)
181 aStr+=ImpGetResStr(STR_EditWithCopy);
182 // meeds its own UndoGroup because of its parameters
183 BegUndo(aStr,GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVE);
186 if (bCopy)
187 CopyMarkedObj();
189 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
190 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
192 SdrMark* pM=GetSdrMarkByIndex(nm);
193 SdrObject* pO=pM->GetMarkedSdrObj();
194 if( bUndo )
196 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
197 AddUndoActions( vConnectorUndoActions );
198 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pO,rSiz));
200 pO->Move(rSiz);
203 if( bUndo )
204 EndUndo();
207 void SdrEditView::ResizeMarkedObj(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bCopy)
209 const bool bUndo = IsUndoEnabled();
210 if( bUndo )
212 XubString aStr;
213 ImpTakeDescriptionStr(STR_EditResize,aStr);
214 if (bCopy)
215 aStr+=ImpGetResStr(STR_EditWithCopy);
216 BegUndo(aStr);
219 if (bCopy)
220 CopyMarkedObj();
222 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
223 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
225 SdrMark* pM=GetSdrMarkByIndex(nm);
226 SdrObject* pO=pM->GetMarkedSdrObj();
227 if( bUndo )
229 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
230 AddUndoActions( vConnectorUndoActions );
231 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
233 pO->Resize(rRef,xFact,yFact);
236 if( bUndo )
237 EndUndo();
239 void SdrEditView::ResizeMultMarkedObj(const Point& rRef,
240 const Fraction& xFact,
241 const Fraction& yFact,
242 const bool bCopy,
243 const bool bWdh,
244 const bool bHgt)
246 const bool bUndo = IsUndoEnabled();
247 if( bUndo )
249 XubString aStr;
250 ImpTakeDescriptionStr(STR_EditResize,aStr);
251 if (bCopy)
252 aStr+=ImpGetResStr(STR_EditWithCopy);
253 BegUndo(aStr);
256 if (bCopy)
257 CopyMarkedObj();
259 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
260 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
262 SdrMark* pM=GetSdrMarkByIndex(nm);
263 SdrObject* pO=pM->GetMarkedSdrObj();
264 if( bUndo )
266 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
267 AddUndoActions( vConnectorUndoActions );
268 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
271 Fraction aFrac(1,1);
272 if (bWdh && bHgt)
273 pO->Resize(rRef, xFact, yFact);
274 else if (bWdh)
275 pO->Resize(rRef, xFact, aFrac);
276 else if (bHgt)
277 pO->Resize(rRef, aFrac, yFact);
279 if( bUndo )
280 EndUndo();
283 long SdrEditView::GetMarkedObjRotate() const
285 long nRetval(0);
287 if(GetMarkedObjectCount())
289 SdrMark* pM = GetSdrMarkByIndex(0);
290 SdrObject* pO = pM->GetMarkedSdrObj();
292 nRetval = pO->GetRotateAngle();
295 return nRetval;
296 //sal_Bool b1st=sal_True;
297 //sal_Bool bOk=sal_True;
298 //long nWink=0;
299 //sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
300 //for (sal_uIntPtr nm=0; nm<nMarkAnz && bOk; nm++) {
301 // SdrMark* pM=GetSdrMarkByIndex(nm);
302 // SdrObject* pO=pM->GetMarkedSdrObj();
303 // long nWink2=pO->GetRotateAngle();
304 // if (b1st) nWink=nWink2;
305 // else if (nWink2!=nWink) bOk=sal_False;
306 // b1st=sal_False;
308 //if (!bOk) nWink=0;
309 //return nWink;
312 void SdrEditView::RotateMarkedObj(const Point& rRef, long nWink, bool bCopy)
314 const bool bUndo = IsUndoEnabled();
315 if( bUndo )
317 XubString aStr;
318 ImpTakeDescriptionStr(STR_EditRotate,aStr);
319 if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy);
320 BegUndo(aStr);
323 if (bCopy)
324 CopyMarkedObj();
326 double nSin=sin(nWink*nPi180);
327 double nCos=cos(nWink*nPi180);
328 const sal_uInt32 nMarkAnz(GetMarkedObjectCount());
330 if(nMarkAnz)
332 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
334 for(sal_uInt32 nm(0); nm < nMarkAnz; nm++)
336 SdrMark* pM = GetSdrMarkByIndex(nm);
337 SdrObject* pO = pM->GetMarkedSdrObj();
339 if( bUndo )
341 // extra undo actions for changed connector which now may hold its laid out path (SJ)
342 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
343 AddUndoActions( vConnectorUndoActions );
345 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
348 // set up a scene updater if object is a 3d object
349 if(dynamic_cast< E3dObject* >(pO))
351 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO));
354 pO->Rotate(rRef,nWink,nSin,nCos);
357 // fire scene updaters
358 while(!aUpdaters.empty())
360 delete aUpdaters.back();
361 aUpdaters.pop_back();
365 if( bUndo )
366 EndUndo();
369 void SdrEditView::MirrorMarkedObj(const Point& rRef1, const Point& rRef2, bool bCopy)
371 const bool bUndo = IsUndoEnabled();
373 if( bUndo )
375 XubString aStr;
376 Point aDif(rRef2-rRef1);
377 if (aDif.X()==0) ImpTakeDescriptionStr(STR_EditMirrorHori,aStr);
378 else if (aDif.Y()==0) ImpTakeDescriptionStr(STR_EditMirrorVert,aStr);
379 else if (std::abs(aDif.X()) == std::abs(aDif.Y())) ImpTakeDescriptionStr(STR_EditMirrorDiag,aStr);
380 else ImpTakeDescriptionStr(STR_EditMirrorFree,aStr);
381 if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy);
382 BegUndo(aStr);
385 if (bCopy)
386 CopyMarkedObj();
388 const sal_uInt32 nMarkAnz(GetMarkedObjectCount());
390 if(nMarkAnz)
392 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
394 for(sal_uInt32 nm(0); nm < nMarkAnz; nm++)
396 SdrMark* pM = GetSdrMarkByIndex(nm);
397 SdrObject* pO = pM->GetMarkedSdrObj();
399 if( bUndo )
401 // extra undo actions for changed connector which now may hold its laid out path (SJ)
402 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
403 AddUndoActions( vConnectorUndoActions );
405 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
408 // set up a scene updater if object is a 3d object
409 if(dynamic_cast< E3dObject* >(pO))
411 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO));
414 pO->Mirror(rRef1,rRef2);
417 // fire scene updaters
418 while(!aUpdaters.empty())
420 delete aUpdaters.back();
421 aUpdaters.pop_back();
425 if( bUndo )
426 EndUndo();
429 void SdrEditView::MirrorMarkedObjHorizontal(sal_Bool bCopy)
431 Point aCenter(GetMarkedObjRect().Center());
432 Point aPt2(aCenter);
433 aPt2.Y()++;
434 MirrorMarkedObj(aCenter,aPt2,bCopy);
437 void SdrEditView::MirrorMarkedObjVertical(sal_Bool bCopy)
439 Point aCenter(GetMarkedObjRect().Center());
440 Point aPt2(aCenter);
441 aPt2.X()++;
442 MirrorMarkedObj(aCenter,aPt2,bCopy);
445 long SdrEditView::GetMarkedObjShear() const
447 bool b1st=true;
448 bool bOk=true;
449 long nWink=0;
450 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
451 for (sal_uIntPtr nm=0; nm<nMarkAnz && bOk; nm++) {
452 SdrMark* pM=GetSdrMarkByIndex(nm);
453 SdrObject* pO=pM->GetMarkedSdrObj();
454 long nWink2=pO->GetShearAngle();
455 if (b1st) nWink=nWink2;
456 else if (nWink2!=nWink) bOk=false;
457 b1st=false;
459 if (nWink>SDRMAXSHEAR) nWink=SDRMAXSHEAR;
460 if (nWink<-SDRMAXSHEAR) nWink=-SDRMAXSHEAR;
461 if (!bOk) nWink=0;
462 return nWink;
465 void SdrEditView::ShearMarkedObj(const Point& rRef, long nWink, bool bVShear, bool bCopy)
467 const bool bUndo = IsUndoEnabled();
469 if( bUndo )
471 XubString aStr;
472 ImpTakeDescriptionStr(STR_EditShear,aStr);
473 if (bCopy)
474 aStr+=ImpGetResStr(STR_EditWithCopy);
475 BegUndo(aStr);
478 if (bCopy)
479 CopyMarkedObj();
481 double nTan=tan(nWink*nPi180);
482 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
483 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
485 SdrMark* pM=GetSdrMarkByIndex(nm);
486 SdrObject* pO=pM->GetMarkedSdrObj();
487 if( bUndo )
489 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
490 AddUndoActions( vConnectorUndoActions );
491 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
493 pO->Shear(rRef,nWink,nTan,bVShear);
496 if( bUndo )
497 EndUndo();
500 void SdrEditView::ImpCrookObj(SdrObject* pO, const Point& rRef, const Point& rRad,
501 SdrCrookMode eMode, sal_Bool bVertical, sal_Bool bNoContortion, sal_Bool bRotate, const Rectangle& rMarkRect)
503 SdrPathObj* pPath=PTR_CAST(SdrPathObj,pO);
504 bool bDone = false;
506 if(pPath!=NULL && !bNoContortion)
508 XPolyPolygon aXPP(pPath->GetPathPoly());
509 switch (eMode) {
510 case SDRCROOK_ROTATE : CrookRotatePoly (aXPP,rRef,rRad,bVertical); break;
511 case SDRCROOK_SLANT : CrookSlantPoly (aXPP,rRef,rRad,bVertical); break;
512 case SDRCROOK_STRETCH: CrookStretchPoly(aXPP,rRef,rRad,bVertical,rMarkRect); break;
513 } // switch
514 pPath->SetPathPoly(aXPP.getB2DPolyPolygon());
515 bDone = true;
518 if(!bDone && !pPath && pO->IsPolyObj() && 0L != pO->GetPointCount())
520 // for PolyObj's, but NOT for SdrPathObj's, e.g. the measurement object
521 sal_uInt32 nPtAnz(pO->GetPointCount());
522 XPolygon aXP((sal_uInt16)nPtAnz);
523 sal_uInt32 nPtNum;
525 for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++)
527 Point aPt(pO->GetPoint(nPtNum));
528 aXP[(sal_uInt16)nPtNum]=aPt;
531 switch (eMode)
533 case SDRCROOK_ROTATE : CrookRotatePoly (aXP,rRef,rRad,bVertical); break;
534 case SDRCROOK_SLANT : CrookSlantPoly (aXP,rRef,rRad,bVertical); break;
535 case SDRCROOK_STRETCH: CrookStretchPoly(aXP,rRef,rRad,bVertical,rMarkRect); break;
538 for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++)
540 // broadcasting could be optimized here, but for the
541 // current two points of the measurement object, it's fine
542 pO->SetPoint(aXP[(sal_uInt16)nPtNum],nPtNum);
545 bDone = true;
548 if(!bDone)
550 // for all others or if bNoContortion
551 Point aCtr0(pO->GetSnapRect().Center());
552 Point aCtr1(aCtr0);
553 sal_Bool bRotOk(sal_False);
554 double nSin(0.0), nCos(1.0);
555 double nWink(0.0);
557 if(0 != rRad.X() && 0 != rRad.Y())
559 bRotOk = bRotate;
561 switch (eMode)
563 case SDRCROOK_ROTATE : nWink=CrookRotateXPoint (aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical); bRotOk=bRotate; break;
564 case SDRCROOK_SLANT : nWink=CrookSlantXPoint (aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical); break;
565 case SDRCROOK_STRETCH: nWink=CrookStretchXPoint(aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical,rMarkRect); break;
569 aCtr1 -= aCtr0;
571 if(bRotOk)
572 pO->Rotate(aCtr0, Round(nWink/nPi180), nSin, nCos);
574 pO->Move(Size(aCtr1.X(),aCtr1.Y()));
578 void SdrEditView::CrookMarkedObj(const Point& rRef, const Point& rRad, SdrCrookMode eMode,
579 bool bVertical, bool bNoContortion, bool bCopy)
581 Rectangle aMarkRect(GetMarkedObjRect());
582 const bool bUndo = IsUndoEnabled();
584 bool bRotate=bNoContortion && eMode==SDRCROOK_ROTATE && IsRotateAllowed(sal_False);
586 if( bUndo )
588 XubString aStr;
589 ImpTakeDescriptionStr(bNoContortion?STR_EditCrook:STR_EditCrookContortion,aStr);
590 if (bCopy)
591 aStr+=ImpGetResStr(STR_EditWithCopy);
592 BegUndo(aStr);
595 if (bCopy)
596 CopyMarkedObj();
598 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
599 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
601 SdrMark* pM=GetSdrMarkByIndex(nm);
602 SdrObject* pO=pM->GetMarkedSdrObj();
603 if( bUndo )
604 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
606 const SdrObjList* pOL=pO->GetSubList();
607 if (bNoContortion || pOL==NULL) {
608 ImpCrookObj(pO,rRef,rRad,eMode,bVertical,bNoContortion,bRotate,aMarkRect);
609 } else {
610 SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS);
611 while (aIter.IsMore()) {
612 SdrObject* pO1=aIter.Next();
613 ImpCrookObj(pO1,rRef,rRad,eMode,bVertical,bNoContortion,bRotate,aMarkRect);
618 if( bUndo )
619 EndUndo();
622 void SdrEditView::ImpDistortObj(SdrObject* pO, const Rectangle& rRef, const XPolygon& rDistortedRect, sal_Bool bNoContortion)
624 SdrPathObj* pPath = PTR_CAST(SdrPathObj, pO);
626 if(!bNoContortion && pPath)
628 XPolyPolygon aXPP(pPath->GetPathPoly());
629 aXPP.Distort(rRef, rDistortedRect);
630 pPath->SetPathPoly(aXPP.getB2DPolyPolygon());
632 else if(pO->IsPolyObj())
634 // e. g. for the measurement object
635 sal_uInt32 nPtAnz(pO->GetPointCount());
636 XPolygon aXP((sal_uInt16)nPtAnz);
637 sal_uInt32 nPtNum;
639 for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++)
641 Point aPt(pO->GetPoint(nPtNum));
642 aXP[(sal_uInt16)nPtNum]=aPt;
645 aXP.Distort(rRef, rDistortedRect);
647 for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++)
649 // broadcasting could be optimized here, but for the
650 // current two points of the measurement object it's fine
651 pO->SetPoint(aXP[(sal_uInt16)nPtNum],nPtNum);
656 void SdrEditView::DistortMarkedObj(const Rectangle& rRef, const XPolygon& rDistortedRect, bool bNoContortion, bool bCopy)
658 const bool bUndo = IsUndoEnabled();
660 if( bUndo )
662 XubString aStr;
663 ImpTakeDescriptionStr(STR_EditDistort,aStr);
664 if (bCopy)
665 aStr+=ImpGetResStr(STR_EditWithCopy);
666 BegUndo(aStr);
669 if (bCopy)
670 CopyMarkedObj();
672 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
673 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
675 SdrMark* pM=GetSdrMarkByIndex(nm);
676 SdrObject* pO=pM->GetMarkedSdrObj();
677 if( bUndo )
678 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
680 Rectangle aRefRect(rRef);
681 XPolygon aRefPoly(rDistortedRect);
682 const SdrObjList* pOL=pO->GetSubList();
683 if (bNoContortion || pOL==NULL) {
684 ImpDistortObj(pO,aRefRect,aRefPoly,bNoContortion);
685 } else {
686 SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS);
687 while (aIter.IsMore()) {
688 SdrObject* pO1=aIter.Next();
689 ImpDistortObj(pO1,aRefRect,aRefPoly,bNoContortion);
693 if( bUndo )
694 EndUndo();
697 ////////////////////////////////////////////////////////////////////////////////////////////////////
699 void SdrEditView::SetNotPersistAttrToMarked(const SfxItemSet& rAttr, sal_Bool /*bReplaceAll*/)
701 // bReplaceAll has no effect here
702 Rectangle aAllSnapRect(GetMarkedObjRect());
703 const SfxPoolItem *pPoolItem=NULL;
704 if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1X,sal_True,&pPoolItem)==SFX_ITEM_SET) {
705 long n=((const SdrTransformRef1XItem*)pPoolItem)->GetValue();
706 SetRef1(Point(n,GetRef1().Y()));
708 if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1Y,sal_True,&pPoolItem)==SFX_ITEM_SET) {
709 long n=((const SdrTransformRef1YItem*)pPoolItem)->GetValue();
710 SetRef1(Point(GetRef1().X(),n));
712 if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2X,sal_True,&pPoolItem)==SFX_ITEM_SET) {
713 long n=((const SdrTransformRef2XItem*)pPoolItem)->GetValue();
714 SetRef2(Point(n,GetRef2().Y()));
716 if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2Y,sal_True,&pPoolItem)==SFX_ITEM_SET) {
717 long n=((const SdrTransformRef2YItem*)pPoolItem)->GetValue();
718 SetRef2(Point(GetRef2().X(),n));
720 long nAllPosX=0; sal_Bool bAllPosX=false;
721 long nAllPosY=0; sal_Bool bAllPosY=false;
722 long nAllWdt=0; sal_Bool bAllWdt=false;
723 long nAllHgt=0; sal_Bool bAllHgt=false;
724 bool bDoIt=false;
725 if (rAttr.GetItemState(SDRATTR_ALLPOSITIONX,sal_True,&pPoolItem)==SFX_ITEM_SET) {
726 nAllPosX=((const SdrAllPositionXItem*)pPoolItem)->GetValue();
727 bAllPosX=true; bDoIt=true;
729 if (rAttr.GetItemState(SDRATTR_ALLPOSITIONY,sal_True,&pPoolItem)==SFX_ITEM_SET) {
730 nAllPosY=((const SdrAllPositionYItem*)pPoolItem)->GetValue();
731 bAllPosY=true; bDoIt=true;
733 if (rAttr.GetItemState(SDRATTR_ALLSIZEWIDTH,sal_True,&pPoolItem)==SFX_ITEM_SET) {
734 nAllWdt=((const SdrAllSizeWidthItem*)pPoolItem)->GetValue();
735 bAllWdt=true; bDoIt=true;
737 if (rAttr.GetItemState(SDRATTR_ALLSIZEHEIGHT,sal_True,&pPoolItem)==SFX_ITEM_SET) {
738 nAllHgt=((const SdrAllSizeHeightItem*)pPoolItem)->GetValue();
739 bAllHgt=true; bDoIt=true;
741 if (bDoIt) {
742 Rectangle aRect(aAllSnapRect); // TODO: change this for PolyPt's and GluePt's!!!
743 if (bAllPosX) aRect.Move(nAllPosX-aRect.Left(),0);
744 if (bAllPosY) aRect.Move(0,nAllPosY-aRect.Top());
745 if (bAllWdt) aRect.Right()=aAllSnapRect.Left()+nAllWdt;
746 if (bAllHgt) aRect.Bottom()=aAllSnapRect.Top()+nAllHgt;
747 SetMarkedObjRect(aRect);
749 if (rAttr.GetItemState(SDRATTR_RESIZEXALL,sal_True,&pPoolItem)==SFX_ITEM_SET) {
750 Fraction aXFact=((const SdrResizeXAllItem*)pPoolItem)->GetValue();
751 ResizeMarkedObj(aAllSnapRect.TopLeft(),aXFact,Fraction(1,1));
753 if (rAttr.GetItemState(SDRATTR_RESIZEYALL,sal_True,&pPoolItem)==SFX_ITEM_SET) {
754 Fraction aYFact=((const SdrResizeYAllItem*)pPoolItem)->GetValue();
755 ResizeMarkedObj(aAllSnapRect.TopLeft(),Fraction(1,1),aYFact);
757 if (rAttr.GetItemState(SDRATTR_ROTATEALL,sal_True,&pPoolItem)==SFX_ITEM_SET) {
758 long nAngle=((const SdrRotateAllItem*)pPoolItem)->GetValue();
759 RotateMarkedObj(aAllSnapRect.Center(),nAngle);
761 if (rAttr.GetItemState(SDRATTR_HORZSHEARALL,sal_True,&pPoolItem)==SFX_ITEM_SET) {
762 long nAngle=((const SdrHorzShearAllItem*)pPoolItem)->GetValue();
763 ShearMarkedObj(aAllSnapRect.Center(),nAngle,sal_False);
765 if (rAttr.GetItemState(SDRATTR_VERTSHEARALL,sal_True,&pPoolItem)==SFX_ITEM_SET) {
766 long nAngle=((const SdrVertShearAllItem*)pPoolItem)->GetValue();
767 ShearMarkedObj(aAllSnapRect.Center(),nAngle,sal_True);
770 const bool bUndo = IsUndoEnabled();
772 // TODO: check if WhichRange is necessary.
773 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
774 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
776 const SdrMark* pM=GetSdrMarkByIndex(nm);
777 SdrObject* pObj=pM->GetMarkedSdrObj();
778 if( bUndo )
779 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
781 pObj->ApplyNotPersistAttr(rAttr);
785 void SdrEditView::MergeNotPersistAttrFromMarked(SfxItemSet& rAttr, sal_Bool /*bOnlyHardAttr*/) const
787 // bOnlyHardAttr has no effect here.
788 // TODO: Take into account the origin and PvPos.
789 Rectangle aAllSnapRect(GetMarkedObjRect()); // TODO: change this for PolyPt's and GluePt's!!!
790 long nAllSnapPosX=aAllSnapRect.Left();
791 long nAllSnapPosY=aAllSnapRect.Top();
792 long nAllSnapWdt=aAllSnapRect.GetWidth()-1;
793 long nAllSnapHgt=aAllSnapRect.GetHeight()-1;
794 // TODO: could go into CheckPossibilities
795 bool bMovProtect = false, bMovProtectDC = false;
796 bool bSizProtect = false, bSizProtectDC = false;
797 bool bPrintable = true, bPrintableDC = false;
798 bool bVisible = true, bVisibleDC = false;
799 SdrLayerID nLayerId=0; bool bLayerDC=false;
800 OUString aObjName;
801 sal_Bool bObjNameDC=false,bObjNameSet=false;
802 long nSnapPosX=0; bool bSnapPosXDC=false;
803 long nSnapPosY=0; bool bSnapPosYDC=false;
804 long nSnapWdt=0; bool bSnapWdtDC=false;
805 long nSnapHgt=0; bool bSnapHgtDC=false;
806 long nLogicWdt=0; bool bLogicWdtDC=false,bLogicWdtDiff=false;
807 long nLogicHgt=0; bool bLogicHgtDC=false,bLogicHgtDiff=false;
808 long nRotAngle=0; bool bRotAngleDC=false;
809 long nShrAngle=0; bool bShrAngleDC=false;
810 Rectangle aSnapRect;
811 Rectangle aLogicRect;
812 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
813 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++) {
814 const SdrMark* pM=GetSdrMarkByIndex(nm);
815 const SdrObject* pObj=pM->GetMarkedSdrObj();
816 if (nm==0) {
817 nLayerId=pObj->GetLayer();
818 bMovProtect=pObj->IsMoveProtect();
819 bSizProtect=pObj->IsResizeProtect();
820 bPrintable =pObj->IsPrintable();
821 bVisible = pObj->IsVisible();
822 Rectangle aSnapRect2(pObj->GetSnapRect());
823 Rectangle aLogicRect2(pObj->GetLogicRect());
824 nSnapPosX=aSnapRect2.Left();
825 nSnapPosY=aSnapRect2.Top();
826 nSnapWdt=aSnapRect2.GetWidth()-1;
827 nSnapHgt=aSnapRect2.GetHeight()-1;
828 nLogicWdt=aLogicRect2.GetWidth()-1;
829 nLogicHgt=aLogicRect2.GetHeight()-1;
830 bLogicWdtDiff=nLogicWdt!=nSnapWdt;
831 bLogicHgtDiff=nLogicHgt!=nSnapHgt;
832 nRotAngle=pObj->GetRotateAngle();
833 nShrAngle=pObj->GetShearAngle();
834 } else {
835 if (!bLayerDC && nLayerId !=pObj->GetLayer()) bLayerDC = true;
836 if (!bMovProtectDC && bMovProtect!=pObj->IsMoveProtect()) bMovProtectDC = true;
837 if (!bSizProtectDC && bSizProtect!=pObj->IsResizeProtect()) bSizProtectDC = true;
838 if (!bPrintableDC && bPrintable !=pObj->IsPrintable()) bPrintableDC = true;
839 if (!bVisibleDC && bVisible !=pObj->IsVisible()) bVisibleDC=true;
840 if (!bRotAngleDC && nRotAngle !=pObj->GetRotateAngle()) bRotAngleDC=true;
841 if (!bShrAngleDC && nShrAngle !=pObj->GetShearAngle()) bShrAngleDC=true;
842 if (!bSnapWdtDC || !bSnapHgtDC || !bSnapPosXDC || !bSnapPosYDC || !bLogicWdtDiff || !bLogicHgtDiff) {
843 aSnapRect=pObj->GetSnapRect();
844 if (nSnapPosX!=aSnapRect.Left()) bSnapPosXDC=true;
845 if (nSnapPosY!=aSnapRect.Top()) bSnapPosYDC=true;
846 if (nSnapWdt!=aSnapRect.GetWidth()-1) bSnapWdtDC=true;
847 if (nSnapHgt!=aSnapRect.GetHeight()-1) bSnapHgtDC=true;
849 if (!bLogicWdtDC || !bLogicHgtDC || !bLogicWdtDiff || !bLogicHgtDiff) {
850 aLogicRect=pObj->GetLogicRect();
851 if (nLogicWdt!=aLogicRect.GetWidth()-1) bLogicWdtDC=true;
852 if (nLogicHgt!=aLogicRect.GetHeight()-1) bLogicHgtDC=true;
853 if (!bLogicWdtDiff && aSnapRect.GetWidth()!=aLogicRect.GetWidth()) bLogicWdtDiff=true;
854 if (!bLogicHgtDiff && aSnapRect.GetHeight()!=aLogicRect.GetHeight()) bLogicHgtDiff=true;
857 if (!bObjNameDC ) {
858 if (!bObjNameSet) {
859 aObjName=pObj->GetName();
860 } else {
861 if (!aObjName.equals(pObj->GetName()))
862 bObjNameDC = true;
867 if (bSnapPosXDC || nAllSnapPosX!=nSnapPosX) rAttr.Put(SdrAllPositionXItem(nAllSnapPosX));
868 if (bSnapPosYDC || nAllSnapPosY!=nSnapPosY) rAttr.Put(SdrAllPositionYItem(nAllSnapPosY));
869 if (bSnapWdtDC || nAllSnapWdt !=nSnapWdt ) rAttr.Put(SdrAllSizeWidthItem(nAllSnapWdt));
870 if (bSnapHgtDC || nAllSnapHgt !=nSnapHgt ) rAttr.Put(SdrAllSizeHeightItem(nAllSnapHgt));
872 // items for pure transformations
873 rAttr.Put(SdrMoveXItem());
874 rAttr.Put(SdrMoveYItem());
875 rAttr.Put(SdrResizeXOneItem());
876 rAttr.Put(SdrResizeYOneItem());
877 rAttr.Put(SdrRotateOneItem());
878 rAttr.Put(SdrHorzShearOneItem());
879 rAttr.Put(SdrVertShearOneItem());
881 if (nMarkAnz>1) {
882 rAttr.Put(SdrResizeXAllItem());
883 rAttr.Put(SdrResizeYAllItem());
884 rAttr.Put(SdrRotateAllItem());
885 rAttr.Put(SdrHorzShearAllItem());
886 rAttr.Put(SdrVertShearAllItem());
889 if(eDragMode == SDRDRAG_ROTATE || eDragMode == SDRDRAG_MIRROR)
891 rAttr.Put(SdrTransformRef1XItem(GetRef1().X()));
892 rAttr.Put(SdrTransformRef1YItem(GetRef1().Y()));
895 if(eDragMode == SDRDRAG_MIRROR)
897 rAttr.Put(SdrTransformRef2XItem(GetRef2().X()));
898 rAttr.Put(SdrTransformRef2YItem(GetRef2().Y()));
902 SfxItemSet SdrEditView::GetAttrFromMarked(sal_Bool bOnlyHardAttr) const
904 SfxItemSet aSet(pMod->GetItemPool());
905 MergeAttrFromMarked(aSet,bOnlyHardAttr);
906 //the EE_FEATURE items should not be set with SetAttrToMarked (see error message there)
907 //so we do not set them here
908 // #i32448#
909 // Do not disable, but clear the items.
910 aSet.ClearItem(EE_FEATURE_TAB);
911 aSet.ClearItem(EE_FEATURE_LINEBR);
912 aSet.ClearItem(EE_FEATURE_NOTCONV);
913 aSet.ClearItem(EE_FEATURE_FIELD);
914 return aSet;
917 void SdrEditView::MergeAttrFromMarked(SfxItemSet& rAttr, sal_Bool bOnlyHardAttr) const
919 sal_uInt32 nMarkAnz(GetMarkedObjectCount());
921 for(sal_uInt32 a(0); a < nMarkAnz; a++)
923 // #80277# merging was done wrong in the prev version
924 const SfxItemSet& rSet = GetMarkedObjectByIndex(a)->GetMergedItemSet();
925 SfxWhichIter aIter(rSet);
926 sal_uInt16 nWhich(aIter.FirstWhich());
928 while(nWhich)
930 if(!bOnlyHardAttr)
932 if(SFX_ITEM_DONTCARE == rSet.GetItemState(nWhich, sal_False))
933 rAttr.InvalidateItem(nWhich);
934 else
935 rAttr.MergeValue(rSet.Get(nWhich), sal_True);
937 else if(SFX_ITEM_SET == rSet.GetItemState(nWhich, sal_False))
939 const SfxPoolItem& rItem = rSet.Get(nWhich);
940 rAttr.MergeValue(rItem, sal_True);
943 nWhich = aIter.NextWhich();
948 void SdrEditView::SetAttrToMarked(const SfxItemSet& rAttr, sal_Bool bReplaceAll)
950 if (AreObjectsMarked())
952 #ifdef DBG_UTIL
954 bool bHasEEFeatureItems=false;
955 SfxItemIter aIter(rAttr);
956 const SfxPoolItem* pItem=aIter.FirstItem();
957 while (!bHasEEFeatureItems && pItem!=NULL) {
958 if (!IsInvalidItem(pItem)) {
959 sal_uInt16 nW=pItem->Which();
960 if (nW>=EE_FEATURE_START && nW<=EE_FEATURE_END) bHasEEFeatureItems=true;
962 pItem=aIter.NextItem();
964 if(bHasEEFeatureItems)
966 String aMessage;
967 aMessage.AppendAscii("SdrEditView::SetAttrToMarked(): Setting EE_FEATURE items at the SdrView does not make sense! It only leads to overhead and unreadable documents.");
968 InfoBox(NULL, aMessage).Execute();
971 #endif
973 // #103836# if the user thets character attributes to the complete shape,
974 // we want to remove all hard set character attributes with same
975 // which ids from the text. We do that later but here we remember
976 // all character attribute which id's that are set.
977 std::vector<sal_uInt16> aCharWhichIds;
979 SfxItemIter aIter(rAttr);
980 const SfxPoolItem* pItem=aIter.FirstItem();
981 while( pItem!=NULL )
983 if (!IsInvalidItem(pItem))
985 sal_uInt16 nWhich = pItem->Which();
986 if (nWhich>=EE_CHAR_START && nWhich<=EE_CHAR_END)
987 aCharWhichIds.push_back( nWhich );
989 pItem=aIter.NextItem();
993 // To make Undo reconstruct text attributes correctly after Format.Standard
994 sal_Bool bHasEEItems=SearchOutlinerItems(rAttr,bReplaceAll);
996 // save additional geometry information when paragraph or character attributes
997 // are changed and the geometrical shape of the text object might be changed
998 bool bPossibleGeomChange(false);
999 SfxWhichIter aIter(rAttr);
1000 sal_uInt16 nWhich = aIter.FirstWhich();
1001 while(!bPossibleGeomChange && nWhich)
1003 SfxItemState eState = rAttr.GetItemState(nWhich);
1004 if(eState == SFX_ITEM_SET)
1006 if((nWhich >= SDRATTR_TEXT_MINFRAMEHEIGHT && nWhich <= SDRATTR_TEXT_CONTOURFRAME)
1007 || nWhich == SDRATTR_3DOBJ_PERCENT_DIAGONAL
1008 || nWhich == SDRATTR_3DOBJ_BACKSCALE
1009 || nWhich == SDRATTR_3DOBJ_DEPTH
1010 || nWhich == SDRATTR_3DOBJ_END_ANGLE
1011 || nWhich == SDRATTR_3DSCENE_DISTANCE)
1013 bPossibleGeomChange = true;
1016 nWhich = aIter.NextWhich();
1019 const bool bUndo = IsUndoEnabled();
1020 if( bUndo )
1022 XubString aStr;
1023 ImpTakeDescriptionStr(STR_EditSetAttributes,aStr);
1024 BegUndo(aStr);
1027 const sal_uInt32 nMarkAnz(GetMarkedObjectCount());
1028 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
1030 // create ItemSet without SFX_ITEM_DONTCARE. Put()
1031 // uses its second parameter (bInvalidAsDefault) to
1032 // remove all such items to set them to default.
1033 SfxItemSet aAttr(*rAttr.GetPool(), rAttr.GetRanges());
1034 aAttr.Put(rAttr, sal_True);
1036 // #i38135#
1037 bool bResetAnimationTimer(false);
1039 // check if LineWidth is part of the change
1040 const bool bLineWidthChange(SFX_ITEM_SET == aAttr.GetItemState(XATTR_LINEWIDTH));
1041 sal_Int32 nNewLineWidth(0);
1042 sal_Int32 nOldLineWidth(0);
1044 if(bLineWidthChange)
1046 nNewLineWidth = ((const XLineWidthItem&)aAttr.Get(XATTR_LINEWIDTH)).GetValue();
1049 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
1051 SdrMark* pM=GetSdrMarkByIndex(nm);
1052 SdrObject* pObj = pM->GetMarkedSdrObj();
1054 if( bUndo )
1056 std::vector< SdrUndoAction* > vConnectorUndoActions;
1057 SdrEdgeObj* pEdgeObj = dynamic_cast< SdrEdgeObj* >( pObj );
1058 if ( pEdgeObj )
1059 bPossibleGeomChange = true;
1060 else if( bUndo )
1061 vConnectorUndoActions = CreateConnectorUndo( *pObj );
1063 AddUndoActions( vConnectorUndoActions );
1066 // new geometry undo
1067 if(bPossibleGeomChange && bUndo)
1069 // save position and size of object, too
1070 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
1073 if( bUndo )
1075 // #i8508#
1076 // If this is a text object also rescue the OutlinerParaObject since
1077 // applying attributes to the object may change text layout when
1078 // multiple portions exist with multiple formats. If a OutlinerParaObject
1079 // really exists and needs to be rescued is evaluated in the undo
1080 // implementation itself.
1081 const bool bRescueText = dynamic_cast< SdrTextObj* >(pObj) != 0;
1083 // add attribute undo
1084 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj,sal_False,bHasEEItems || bPossibleGeomChange || bRescueText));
1087 // set up a scene updater if object is a 3d object
1088 if(dynamic_cast< E3dObject* >(pObj))
1090 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pObj));
1093 if(bLineWidthChange)
1095 nOldLineWidth = ((const XLineWidthItem&)pObj->GetMergedItem(XATTR_LINEWIDTH)).GetValue();
1098 // set attributes at object
1099 pObj->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
1101 if(bLineWidthChange)
1103 const SfxItemSet& rSet = pObj->GetMergedItemSet();
1105 if(nOldLineWidth != nNewLineWidth)
1107 if(SFX_ITEM_DONTCARE != rSet.GetItemState(XATTR_LINESTARTWIDTH))
1109 const sal_Int32 nValAct(((const XLineStartWidthItem&)rSet.Get(XATTR_LINESTARTWIDTH)).GetValue());
1110 const sal_Int32 nValNewStart(std::max((sal_Int32)0, nValAct + (((nNewLineWidth - nOldLineWidth) * 15) / 10)));
1112 pObj->SetMergedItem(XLineStartWidthItem(nValNewStart));
1115 if(SFX_ITEM_DONTCARE != rSet.GetItemState(XATTR_LINEENDWIDTH))
1117 const sal_Int32 nValAct(((const XLineEndWidthItem&)rSet.Get(XATTR_LINEENDWIDTH)).GetValue());
1118 const sal_Int32 nValNewEnd(std::max((sal_Int32)0, nValAct + (((nNewLineWidth - nOldLineWidth) * 15) / 10)));
1120 pObj->SetMergedItem(XLineEndWidthItem(nValNewEnd));
1125 if(pObj->ISA(SdrTextObj))
1127 SdrTextObj* pTextObj = ((SdrTextObj*)pObj);
1129 if(!aCharWhichIds.empty())
1131 Rectangle aOldBoundRect = pTextObj->GetLastBoundRect();
1133 // #110094#-14 pTextObj->SendRepaintBroadcast(pTextObj->GetBoundRect());
1134 pTextObj->RemoveOutlinerCharacterAttribs( aCharWhichIds );
1136 // object has changed, should be called from
1137 // RemoveOutlinerCharacterAttribs. This will change when the text
1138 // object implementation changes.
1139 pTextObj->SetChanged();
1141 pTextObj->BroadcastObjectChange();
1142 pTextObj->SendUserCall(SDRUSERCALL_CHGATTR, aOldBoundRect);
1146 // #i38495#
1147 if(!bResetAnimationTimer)
1149 if(pObj->GetViewContact().isAnimatedInAnyViewObjectContact())
1151 bResetAnimationTimer = true;
1156 // fire scene updaters
1157 while(!aUpdaters.empty())
1159 delete aUpdaters.back();
1160 aUpdaters.pop_back();
1163 // #i38135#
1164 if(bResetAnimationTimer)
1166 SetAnimationTimer(0L);
1169 // better check before what to do:
1170 // pObj->SetAttr() or SetNotPersistAttr()
1171 // TODO: missing implementation!
1172 SetNotPersistAttrToMarked(rAttr,bReplaceAll);
1174 if( bUndo )
1175 EndUndo();
1179 SfxStyleSheet* SdrEditView::GetStyleSheetFromMarked() const
1181 SfxStyleSheet* pRet=NULL;
1182 bool b1st=true;
1183 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
1184 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++) {
1185 SdrMark* pM=GetSdrMarkByIndex(nm);
1186 SfxStyleSheet* pSS=pM->GetMarkedSdrObj()->GetStyleSheet();
1187 if (b1st) pRet=pSS;
1188 else if (pRet!=pSS) return NULL; // different stylesheets
1189 b1st=false;
1191 return pRet;
1194 void SdrEditView::SetStyleSheetToMarked(SfxStyleSheet* pStyleSheet, sal_Bool bDontRemoveHardAttr)
1196 if (AreObjectsMarked())
1198 const bool bUndo = IsUndoEnabled();
1200 if( bUndo )
1202 XubString aStr;
1203 if (pStyleSheet!=NULL)
1204 ImpTakeDescriptionStr(STR_EditSetStylesheet,aStr);
1205 else
1206 ImpTakeDescriptionStr(STR_EditDelStylesheet,aStr);
1207 BegUndo(aStr);
1210 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
1211 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
1213 SdrMark* pM=GetSdrMarkByIndex(nm);
1214 if( bUndo )
1216 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pM->GetMarkedSdrObj()));
1217 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pM->GetMarkedSdrObj(),true,true));
1219 pM->GetMarkedSdrObj()->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1222 if( bUndo )
1223 EndUndo();
1227 ////////////////////////////////////////////////////////////////////////////////////////////////////
1229 sal_Bool SdrEditView::GetAttributes(SfxItemSet& rTargetSet, sal_Bool bOnlyHardAttr) const
1231 if(GetMarkedObjectCount())
1233 rTargetSet.Put(GetAttrFromMarked(bOnlyHardAttr), sal_False);
1234 return sal_True;
1236 else
1238 return SdrMarkView::GetAttributes(rTargetSet, bOnlyHardAttr);
1242 sal_Bool SdrEditView::SetAttributes(const SfxItemSet& rSet, sal_Bool bReplaceAll)
1244 if (GetMarkedObjectCount()!=0) {
1245 SetAttrToMarked(rSet,bReplaceAll);
1246 return sal_True;
1247 } else {
1248 return SdrMarkView::SetAttributes(rSet,bReplaceAll);
1252 SfxStyleSheet* SdrEditView::GetStyleSheet() const
1254 if (GetMarkedObjectCount()!=0) {
1255 return GetStyleSheetFromMarked();
1256 } else {
1257 return SdrMarkView::GetStyleSheet();
1261 sal_Bool SdrEditView::SetStyleSheet(SfxStyleSheet* pStyleSheet, sal_Bool bDontRemoveHardAttr)
1263 if (GetMarkedObjectCount()!=0) {
1264 SetStyleSheetToMarked(pStyleSheet,bDontRemoveHardAttr);
1265 return sal_True;
1266 } else {
1267 return SdrMarkView::SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1271 ////////////////////////////////////////////////////////////////////////////////////////////////////
1273 SfxItemSet SdrEditView::GetGeoAttrFromMarked() const
1275 SfxItemSet aRetSet(pMod->GetItemPool(), // SID_ATTR_TRANSFORM_... from s:svxids.hrc
1276 SID_ATTR_TRANSFORM_POS_X, SID_ATTR_TRANSFORM_ANGLE,
1277 SID_ATTR_TRANSFORM_PROTECT_POS, SID_ATTR_TRANSFORM_AUTOHEIGHT,
1278 SDRATTR_ECKENRADIUS, SDRATTR_ECKENRADIUS,
1281 if (AreObjectsMarked())
1283 SfxItemSet aMarkAttr(GetAttrFromMarked(sal_False)); // because of AutoGrowHeight and corner radius
1284 Rectangle aRect(GetMarkedObjRect());
1285 // restore position to that before calc hack
1286 aRect -= GetGridOffset();
1288 if(GetSdrPageView())
1290 GetSdrPageView()->LogicToPagePos(aRect);
1293 // position
1294 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_X,aRect.Left()));
1295 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_Y,aRect.Top()));
1297 // size
1298 long nResizeRefX=aRect.Left();
1299 long nResizeRefY=aRect.Top();
1300 if (eDragMode==SDRDRAG_ROTATE) { // use rotation axis as a reference for resizing, too
1301 nResizeRefX=aRef1.X();
1302 nResizeRefY=aRef1.Y();
1304 aRetSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_WIDTH,aRect.Right()-aRect.Left()));
1305 aRetSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_HEIGHT,aRect.Bottom()-aRect.Top()));
1306 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_RESIZE_REF_X,nResizeRefX));
1307 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_RESIZE_REF_Y,nResizeRefY));
1309 Point aRotateAxe(aRef1);
1311 if(GetSdrPageView())
1313 GetSdrPageView()->LogicToPagePos(aRotateAxe);
1316 // rotation
1317 long nRotateRefX=aRect.Center().X();
1318 long nRotateRefY=aRect.Center().Y();
1319 if (eDragMode==SDRDRAG_ROTATE) {
1320 nRotateRefX=aRotateAxe.X();
1321 nRotateRefY=aRotateAxe.Y();
1323 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ANGLE,GetMarkedObjRotate()));
1324 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_X,nRotateRefX));
1325 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_Y,nRotateRefY));
1327 // shearing
1328 long nShearRefX=aRect.Left();
1329 long nShearRefY=aRect.Bottom();
1330 if (eDragMode==SDRDRAG_ROTATE) { // use rotation axis as a reference for shearing, too
1331 nShearRefX=aRotateAxe.X();
1332 nShearRefY=aRotateAxe.Y();
1334 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR,GetMarkedObjShear()));
1335 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_X,nShearRefX));
1336 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_Y,nShearRefY));
1338 // check every object whether it is protected
1339 const SdrMarkList& rMarkList=GetMarkedObjectList();
1340 sal_uIntPtr nMarkCount=rMarkList.GetMarkCount();
1341 SdrObject* pObj=rMarkList.GetMark(0)->GetMarkedSdrObj();
1342 bool bPosProt=pObj->IsMoveProtect();
1343 bool bSizProt=pObj->IsResizeProtect();
1344 bool bPosProtDontCare=false;
1345 bool bSizProtDontCare=false;
1346 for (sal_uIntPtr i=1; i<nMarkCount && (!bPosProtDontCare || !bSizProtDontCare); i++)
1348 pObj=rMarkList.GetMark(i)->GetMarkedSdrObj();
1349 if (bPosProt!=pObj->IsMoveProtect()) bPosProtDontCare=true;
1350 if (bSizProt!=pObj->IsResizeProtect()) bSizProtDontCare=true;
1353 // InvalidateItem sets item to DONT_CARE
1354 if (bPosProtDontCare) {
1355 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_PROTECT_POS);
1356 } else {
1357 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_PROTECT_POS,bPosProt));
1359 if (bSizProtDontCare) {
1360 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_PROTECT_SIZE);
1361 } else {
1362 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_PROTECT_SIZE,bSizProt));
1365 SfxItemState eState=aMarkAttr.GetItemState(SDRATTR_TEXT_AUTOGROWWIDTH);
1366 sal_Bool bAutoGrow=((SdrTextAutoGrowWidthItem&)(aMarkAttr.Get(SDRATTR_TEXT_AUTOGROWWIDTH))).GetValue();
1367 if (eState==SFX_ITEM_DONTCARE) {
1368 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_AUTOWIDTH);
1369 } else if (eState==SFX_ITEM_SET) {
1370 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_AUTOWIDTH,bAutoGrow));
1373 eState=aMarkAttr.GetItemState(SDRATTR_TEXT_AUTOGROWHEIGHT);
1374 bAutoGrow=((SdrTextAutoGrowHeightItem&)(aMarkAttr.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue();
1375 if (eState==SFX_ITEM_DONTCARE) {
1376 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_AUTOHEIGHT);
1377 } else if (eState==SFX_ITEM_SET) {
1378 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_AUTOHEIGHT,bAutoGrow));
1381 eState=aMarkAttr.GetItemState(SDRATTR_ECKENRADIUS);
1382 long nRadius=((SdrEckenradiusItem&)(aMarkAttr.Get(SDRATTR_ECKENRADIUS))).GetValue();
1383 if (eState==SFX_ITEM_DONTCARE) {
1384 aRetSet.InvalidateItem(SDRATTR_ECKENRADIUS);
1385 } else if (eState==SFX_ITEM_SET) {
1386 aRetSet.Put(SdrEckenradiusItem(nRadius));
1389 basegfx::B2DHomMatrix aTransformation;
1391 if(nMarkCount > 1)
1393 // multiple objects, range is collected in aRect
1394 aTransformation = basegfx::tools::createScaleTranslateB2DHomMatrix(
1395 aRect.Left(), aRect.Top(),
1396 aRect.getWidth(), aRect.getHeight());
1398 else if(pObj)
1400 // single object, get homogen transformation
1401 basegfx::B2DPolyPolygon aPolyPolygon;
1403 pObj->TRGetBaseGeometry(aTransformation, aPolyPolygon);
1406 if(aTransformation.isIdentity())
1408 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_MATRIX);
1410 else
1412 com::sun::star::geometry::AffineMatrix2D aAffineMatrix2D;
1413 Point aPageOffset(0, 0);
1415 if(GetSdrPageView())
1417 aPageOffset = GetSdrPageView()->GetPageOrigin();
1420 aAffineMatrix2D.m00 = aTransformation.get(0, 0);
1421 aAffineMatrix2D.m01 = aTransformation.get(0, 1);
1422 aAffineMatrix2D.m02 = aTransformation.get(0, 2) - aPageOffset.X();
1423 aAffineMatrix2D.m10 = aTransformation.get(1, 0);
1424 aAffineMatrix2D.m11 = aTransformation.get(1, 1);
1425 aAffineMatrix2D.m12 = aTransformation.get(1, 2) - aPageOffset.Y();
1427 aRetSet.Put(AffineMatrixItem(&aAffineMatrix2D));
1431 return aRetSet;
1434 Point ImpGetPoint(Rectangle aRect, RECT_POINT eRP)
1436 switch(eRP) {
1437 case RP_LT: return aRect.TopLeft();
1438 case RP_MT: return aRect.TopCenter();
1439 case RP_RT: return aRect.TopRight();
1440 case RP_LM: return aRect.LeftCenter();
1441 case RP_MM: return aRect.Center();
1442 case RP_RM: return aRect.RightCenter();
1443 case RP_LB: return aRect.BottomLeft();
1444 case RP_MB: return aRect.BottomCenter();
1445 case RP_RB: return aRect.BottomRight();
1447 return Point(); // Should not happen!
1450 void SdrEditView::SetGeoAttrToMarked(const SfxItemSet& rAttr)
1452 Rectangle aRect(GetMarkedObjRect());
1454 if(GetSdrPageView())
1456 GetSdrPageView()->LogicToPagePos(aRect);
1459 long nOldRotateAngle=GetMarkedObjRotate();
1460 long nOldShearAngle=GetMarkedObjShear();
1461 const SdrMarkList& rMarkList=GetMarkedObjectList();
1462 sal_uIntPtr nMarkCount=rMarkList.GetMarkCount();
1463 SdrObject* pObj=NULL;
1465 RECT_POINT eSizePoint=RP_MM;
1466 long nPosDX=0;
1467 long nPosDY=0;
1468 long nSizX=0;
1469 long nSizY=0;
1470 long nRotateAngle=0;
1472 bool bModeIsRotate(eDragMode == SDRDRAG_ROTATE);
1473 long nRotateX(0);
1474 long nRotateY(0);
1475 long nOldRotateX(0);
1476 long nOldRotateY(0);
1477 if(bModeIsRotate)
1479 Point aRotateAxe(aRef1);
1481 if(GetSdrPageView())
1483 GetSdrPageView()->LogicToPagePos(aRotateAxe);
1486 nRotateX = nOldRotateX = aRotateAxe.X();
1487 nRotateY = nOldRotateY = aRotateAxe.Y();
1490 long nShearAngle=0;
1491 long nShearX=0;
1492 long nShearY=0;
1493 sal_Bool bShearVert=sal_False;
1495 bool bChgPos=false;
1496 bool bChgSiz=false;
1497 bool bChgWdh=false;
1498 bool bChgHgt=false;
1499 bool bRotate=false;
1500 bool bShear =false;
1502 bool bSetAttr=false;
1503 SfxItemSet aSetAttr(pMod->GetItemPool());
1505 const SfxPoolItem* pPoolItem=NULL;
1507 // position
1508 if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_POS_X,sal_True,&pPoolItem)) {
1509 nPosDX=((const SfxInt32Item*)pPoolItem)->GetValue()-aRect.Left();
1510 bChgPos=true;
1512 if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_POS_Y,sal_True,&pPoolItem)){
1513 nPosDY=((const SfxInt32Item*)pPoolItem)->GetValue()-aRect.Top();
1514 bChgPos=true;
1516 // size
1517 if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_WIDTH,sal_True,&pPoolItem)) {
1518 nSizX=((const SfxUInt32Item*)pPoolItem)->GetValue();
1519 bChgSiz=true;
1520 bChgWdh=true;
1522 if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_HEIGHT,sal_True,&pPoolItem)) {
1523 nSizY=((const SfxUInt32Item*)pPoolItem)->GetValue();
1524 bChgSiz=true;
1525 bChgHgt=true;
1527 if (bChgSiz) {
1528 eSizePoint=(RECT_POINT)((const SfxAllEnumItem&)rAttr.Get(SID_ATTR_TRANSFORM_SIZE_POINT)).GetValue();
1531 // rotation
1532 if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ANGLE,sal_True,&pPoolItem)) {
1533 nRotateAngle=((const SfxInt32Item*)pPoolItem)->GetValue()-nOldRotateAngle;
1534 bRotate = (nRotateAngle != 0);
1537 // position rotation point x
1538 if(bRotate || SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ROT_X, sal_True ,&pPoolItem))
1539 nRotateX = ((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_ROT_X)).GetValue();
1541 // position rotation point y
1542 if(bRotate || SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ROT_Y, sal_True ,&pPoolItem))
1543 nRotateY = ((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_ROT_Y)).GetValue();
1545 // shearing
1546 if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_SHEAR,sal_True,&pPoolItem)) {
1547 long nNewShearAngle=((const SfxInt32Item*)pPoolItem)->GetValue();
1548 if (nNewShearAngle>SDRMAXSHEAR) nNewShearAngle=SDRMAXSHEAR;
1549 if (nNewShearAngle<-SDRMAXSHEAR) nNewShearAngle=-SDRMAXSHEAR;
1550 if (nNewShearAngle!=nOldShearAngle) {
1551 bShearVert=((const SfxBoolItem&)rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_VERTICAL)).GetValue();
1552 if (bShearVert) {
1553 nShearAngle=nNewShearAngle;
1554 } else {
1555 if (nNewShearAngle!=0 && nOldShearAngle!=0) {
1556 // bug fix
1557 double nOld=tan((double)nOldShearAngle*nPi180);
1558 double nNew=tan((double)nNewShearAngle*nPi180);
1559 nNew-=nOld;
1560 nNew=atan(nNew)/nPi180;
1561 nShearAngle=Round(nNew);
1562 } else {
1563 nShearAngle=nNewShearAngle-nOldShearAngle;
1566 bShear=nShearAngle!=0;
1567 if (bShear) {
1568 nShearX=((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_X)).GetValue();
1569 nShearY=((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_Y)).GetValue();
1574 // AutoGrow
1575 if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_AUTOWIDTH,sal_True,&pPoolItem)) {
1576 sal_Bool bAutoGrow=((const SfxBoolItem*)pPoolItem)->GetValue();
1577 aSetAttr.Put(SdrTextAutoGrowWidthItem(bAutoGrow));
1578 bSetAttr=true;
1581 if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_AUTOHEIGHT,sal_True,&pPoolItem)) {
1582 sal_Bool bAutoGrow=((const SfxBoolItem*)pPoolItem)->GetValue();
1583 aSetAttr.Put(SdrTextAutoGrowHeightItem(bAutoGrow));
1584 bSetAttr=true;
1587 // corner radius
1588 if (bEdgeRadiusAllowed && SFX_ITEM_SET==rAttr.GetItemState(SDRATTR_ECKENRADIUS,sal_True,&pPoolItem)) {
1589 long nRadius=((SdrEckenradiusItem*)pPoolItem)->GetValue();
1590 aSetAttr.Put(SdrEckenradiusItem(nRadius));
1591 bSetAttr=true;
1594 ForcePossibilities();
1596 BegUndo(ImpGetResStr(STR_EditTransform),GetDescriptionOfMarkedObjects());
1598 if (bSetAttr) {
1599 SetAttrToMarked(aSetAttr,sal_False);
1602 // change size and height
1603 if (bChgSiz && (bResizeFreeAllowed || bResizePropAllowed)) {
1604 Fraction aWdt(nSizX,aRect.Right()-aRect.Left());
1605 Fraction aHgt(nSizY,aRect.Bottom()-aRect.Top());
1606 Point aRef(ImpGetPoint(aRect,eSizePoint));
1608 if(GetSdrPageView())
1610 GetSdrPageView()->PagePosToLogic(aRef);
1613 ResizeMultMarkedObj(aRef, aWdt, aHgt, false, bChgWdh, bChgHgt);
1616 // rotate
1617 if (bRotate && (bRotateFreeAllowed || bRotate90Allowed)) {
1618 Point aRef(nRotateX,nRotateY);
1620 if(GetSdrPageView())
1622 GetSdrPageView()->PagePosToLogic(aRef);
1625 RotateMarkedObj(aRef,nRotateAngle);
1628 // set rotation point position
1629 if(bModeIsRotate && (nRotateX != nOldRotateX || nRotateY != nOldRotateY))
1631 Point aNewRef1(nRotateX, nRotateY);
1633 if(GetSdrPageView())
1635 GetSdrPageView()->PagePosToLogic(aNewRef1);
1638 SetRef1(aNewRef1);
1641 // shear
1642 if (bShear && bShearAllowed) {
1643 Point aRef(nShearX,nShearY);
1645 if(GetSdrPageView())
1647 GetSdrPageView()->PagePosToLogic(aRef);
1650 ShearMarkedObj(aRef,nShearAngle,bShearVert);
1652 // #i74358#
1653 // ShearMarkedObj creates a linear combination of the existing transformation and
1654 // the new shear to apply. If the object is already transformed (e.g. rotated) the
1655 // linear combination will not decompose to the same start values again, but to a
1656 // new combination. Thus it makes no sense to check if the wanted shear is reached
1657 // or not. Taking out.
1660 // change position
1661 if (bChgPos && bMoveAllowed) {
1662 MoveMarkedObj(Size(nPosDX,nPosDY));
1665 // protect position
1666 if(SFX_ITEM_SET == rAttr.GetItemState(SID_ATTR_TRANSFORM_PROTECT_POS, sal_True, &pPoolItem))
1668 const bool bProtPos(((const SfxBoolItem*)pPoolItem)->GetValue());
1669 bool bChanged(false);
1671 for(sal_uInt32 i(0); i < nMarkCount; i++)
1673 pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
1675 if(pObj->IsMoveProtect() != bProtPos)
1677 bChanged = true;
1678 pObj->SetMoveProtect(bProtPos);
1680 if(bProtPos)
1682 pObj->SetResizeProtect(true);
1687 if(bChanged)
1689 bMoveProtect = bProtPos;
1691 if(bProtPos)
1693 bResizeProtect = true;
1696 // #i77187# there is no simple method to get the toolbars updated
1697 // in the application. The App is listening to selection change and i
1698 // will use it here (even if not true). It's acceptable since changing
1699 // this model data is pretty rare and only possible using the F4 dialog
1700 MarkListHasChanged();
1704 if(!bMoveProtect)
1706 // protect size
1707 if(SFX_ITEM_SET == rAttr.GetItemState(SID_ATTR_TRANSFORM_PROTECT_SIZE, sal_True, &pPoolItem))
1709 const bool bProtSize(((const SfxBoolItem*)pPoolItem)->GetValue());
1710 bool bChanged(false);
1712 for(sal_uInt32 i(0); i < nMarkCount; i++)
1714 pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
1716 if(pObj->IsResizeProtect() != bProtSize)
1718 bChanged = true;
1719 pObj->SetResizeProtect(bProtSize);
1723 if(bChanged)
1725 bResizeProtect = bProtSize;
1727 // #i77187# see above
1728 MarkListHasChanged();
1733 EndUndo();
1736 ////////////////////////////////////////////////////////////////////////////////////////////////////
1738 sal_Bool SdrEditView::IsAlignPossible() const
1739 { // at least two selected objects, at least one of them movable
1740 ForcePossibilities();
1741 sal_uIntPtr nAnz=GetMarkedObjectCount();
1742 if (nAnz==0) return sal_False; // nothing selected!
1743 if (nAnz==1) return bMoveAllowed; // align single object to page
1744 return bOneOrMoreMovable; // otherwise: MarkCount>=2
1747 void SdrEditView::AlignMarkedObjects(SdrHorAlign eHor, SdrVertAlign eVert, sal_Bool bBoundRects)
1749 if (eHor==SDRHALIGN_NONE && eVert==SDRVALIGN_NONE)
1750 return;
1752 SortMarkedObjects();
1753 if (GetMarkedObjectCount()<1)
1754 return;
1756 const bool bUndo = IsUndoEnabled();
1757 if( bUndo )
1759 XubString aStr(GetDescriptionOfMarkedObjects());
1760 if (eHor==SDRHALIGN_NONE)
1762 switch (eVert)
1764 case SDRVALIGN_TOP : ImpTakeDescriptionStr(STR_EditAlignVTop ,aStr); break;
1765 case SDRVALIGN_BOTTOM: ImpTakeDescriptionStr(STR_EditAlignVBottom,aStr); break;
1766 case SDRVALIGN_CENTER: ImpTakeDescriptionStr(STR_EditAlignVCenter,aStr); break;
1767 default: break;
1770 else if (eVert==SDRVALIGN_NONE)
1772 switch (eHor)
1774 case SDRHALIGN_LEFT : ImpTakeDescriptionStr(STR_EditAlignHLeft ,aStr); break;
1775 case SDRHALIGN_RIGHT : ImpTakeDescriptionStr(STR_EditAlignHRight ,aStr); break;
1776 case SDRHALIGN_CENTER: ImpTakeDescriptionStr(STR_EditAlignHCenter,aStr); break;
1777 default: break;
1780 else if (eHor==SDRHALIGN_CENTER && eVert==SDRVALIGN_CENTER)
1782 ImpTakeDescriptionStr(STR_EditAlignCenter,aStr);
1784 else
1786 ImpTakeDescriptionStr(STR_EditAlign,aStr);
1788 BegUndo(aStr);
1791 Rectangle aBound;
1792 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
1793 sal_uIntPtr nm;
1794 bool bHasFixed=false;
1795 for (nm=0; nm<nMarkAnz; nm++)
1797 SdrMark* pM=GetSdrMarkByIndex(nm);
1798 SdrObject* pObj=pM->GetMarkedSdrObj();
1799 SdrObjTransformInfoRec aInfo;
1800 pObj->TakeObjInfo(aInfo);
1801 if (!aInfo.bMoveAllowed || pObj->IsMoveProtect())
1803 Rectangle aObjRect(bBoundRects?pObj->GetCurrentBoundRect():pObj->GetSnapRect());
1804 aBound.Union(aObjRect);
1805 bHasFixed=true;
1808 if (!bHasFixed)
1810 if (nMarkAnz==1)
1811 { // align single object to page
1812 const SdrObject* pObj=GetMarkedObjectByIndex(0L);
1813 const SdrPage* pPage=pObj->GetPage();
1814 const SdrPageGridFrameList* pGFL=pPage->GetGridFrameList(GetSdrPageViewOfMarkedByIndex(0),&(pObj->GetSnapRect()));
1815 const SdrPageGridFrame* pFrame=NULL;
1816 if (pGFL!=NULL && pGFL->GetCount()!=0)
1817 { // Writer
1818 pFrame=&((*pGFL)[0]);
1821 if (pFrame!=NULL)
1822 { // Writer
1823 aBound=pFrame->GetUserArea();
1825 else
1827 aBound=Rectangle(pPage->GetLftBorder(),pPage->GetUppBorder(),
1828 pPage->GetWdt()-pPage->GetRgtBorder(),
1829 pPage->GetHgt()-pPage->GetLwrBorder());
1832 else
1834 if (bBoundRects)
1835 aBound=GetMarkedObjBoundRect();
1836 else
1837 aBound=GetMarkedObjRect();
1840 Point aCenter(aBound.Center());
1841 for (nm=0; nm<nMarkAnz; nm++)
1843 SdrMark* pM=GetSdrMarkByIndex(nm);
1844 SdrObject* pObj=pM->GetMarkedSdrObj();
1845 SdrObjTransformInfoRec aInfo;
1846 pObj->TakeObjInfo(aInfo);
1847 if (aInfo.bMoveAllowed && !pObj->IsMoveProtect())
1849 long nXMov=0;
1850 long nYMov=0;
1851 Rectangle aObjRect(bBoundRects?pObj->GetCurrentBoundRect():pObj->GetSnapRect());
1852 switch (eVert)
1854 case SDRVALIGN_TOP : nYMov=aBound.Top() -aObjRect.Top() ; break;
1855 case SDRVALIGN_BOTTOM: nYMov=aBound.Bottom()-aObjRect.Bottom() ; break;
1856 case SDRVALIGN_CENTER: nYMov=aCenter.Y() -aObjRect.Center().Y(); break;
1857 default: break;
1859 switch (eHor)
1861 case SDRHALIGN_LEFT : nXMov=aBound.Left() -aObjRect.Left() ; break;
1862 case SDRHALIGN_RIGHT : nXMov=aBound.Right() -aObjRect.Right() ; break;
1863 case SDRHALIGN_CENTER: nXMov=aCenter.X() -aObjRect.Center().X(); break;
1864 default: break;
1866 if (nXMov!=0 || nYMov!=0)
1868 // SdrEdgeObj needs an extra SdrUndoGeoObj since the
1869 // connections may need to be saved
1870 if( bUndo )
1872 if( dynamic_cast<SdrEdgeObj*>(pObj) )
1874 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
1877 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pObj,Size(nXMov,nYMov)));
1880 pObj->Move(Size(nXMov,nYMov));
1885 if( bUndo )
1886 EndUndo();
1889 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */