Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / svx / source / svdraw / svdedtv1.cxx
blob7945d2cb69be7dc5fe3e99f14ee016396152b05c
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 .
20 #include <basegfx/matrix/b2dhommatrix.hxx>
21 #include <basegfx/matrix/b2dhommatrixtools.hxx>
22 #include <editeng/editdata.hxx>
23 #include <editeng/eeitem.hxx>
24 #include <math.h>
25 #include <svl/aeitem.hxx>
26 #include <svl/itemiter.hxx>
27 #include <svl/whiter.hxx>
28 #include <tools/bigint.hxx>
29 #include <vcl/msgbox.hxx>
31 #include "svdglob.hxx"
32 #include "svx/svditer.hxx"
33 #include "svx/svdstr.hrc"
35 #include <svx/AffineMatrixItem.hxx>
36 #include <svx/e3dsceneupdater.hxx>
37 #include <svx/obj3d.hxx>
38 #include <svx/rectenum.hxx>
39 #include <svx/sdr/contact/objectcontact.hxx>
40 #include <svx/sdr/contact/viewcontact.hxx>
41 #include <svx/svdattr.hxx>
42 #include <svx/svdedtv.hxx>
43 #include <svx/svdetc.hxx>
44 #include <svx/svdlayer.hxx>
45 #include <svx/svdopath.hxx>
46 #include <svx/svdpage.hxx>
47 #include <svx/svdpagv.hxx>
48 #include <svx/svdtrans.hxx>
49 #include <svx/svdundo.hxx>
50 #include <svx/svxids.hrc>
51 #include <sxallitm.hxx>
52 #include <sxmovitm.hxx>
53 #include <sxreaitm.hxx>
54 #include <sxreoitm.hxx>
55 #include <sxroaitm.hxx>
56 #include <sxrooitm.hxx>
57 #include <sxsalitm.hxx>
58 #include <sxsoitm.hxx>
59 #include <sxtraitm.hxx>
60 #include <svx/xlnedwit.hxx>
61 #include <svx/xlnstwit.hxx>
62 #include <svx/xlnwtit.hxx>
66 // EditView
70 void SdrEditView::SetMarkedObjRect(const Rectangle& rRect, bool bCopy)
72 DBG_ASSERT(!rRect.IsEmpty(),"SetMarkedObjRect() with an empty Rect does not make sense.");
73 if (rRect.IsEmpty()) return;
74 sal_uIntPtr nAnz=GetMarkedObjectCount();
75 if (nAnz==0) return;
76 Rectangle aR0(GetMarkedObjRect());
77 DBG_ASSERT(!aR0.IsEmpty(),"SetMarkedObjRect(): GetMarkedObjRect() is empty.");
78 if (aR0.IsEmpty()) return;
79 long x0=aR0.Left();
80 long y0=aR0.Top();
81 long w0=aR0.Right()-x0;
82 long h0=aR0.Bottom()-y0;
83 long x1=rRect.Left();
84 long y1=rRect.Top();
85 long w1=rRect.Right()-x1;
86 long h1=rRect.Bottom()-y1;
87 OUString aStr;
88 ImpTakeDescriptionStr(STR_EditPosSize,aStr);
89 if (bCopy)
90 aStr+=ImpGetResStr(STR_EditWithCopy);
92 const bool bUndo = IsUndoEnabled();
93 if( bUndo )
94 BegUndo(aStr);
96 if (bCopy)
97 CopyMarkedObj();
99 for (sal_uIntPtr nm=0; nm<nAnz; nm++)
101 SdrMark* pM=GetSdrMarkByIndex(nm);
102 SdrObject* pO=pM->GetMarkedSdrObj();
103 if( bUndo )
104 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
106 Rectangle aR1(pO->GetSnapRect());
107 if (!aR1.IsEmpty())
109 if (aR1==aR0)
111 aR1=rRect;
113 else
114 { // transform aR1 to aR0 after rRect
115 aR1.Move(-x0,-y0);
116 BigInt l(aR1.Left());
117 BigInt r(aR1.Right());
118 BigInt t(aR1.Top());
119 BigInt b(aR1.Bottom());
120 if (w0!=0) {
121 l*=w1; l/=w0;
122 r*=w1; r/=w0;
123 } else {
124 l=0; r=w1;
126 if (h0!=0) {
127 t*=h1; t/=h0;
128 b*=h1; b/=h0;
129 } else {
130 t=0; b=h1;
132 aR1.Left ()=long(l);
133 aR1.Right ()=long(r);
134 aR1.Top ()=long(t);
135 aR1.Bottom()=long(b);
136 aR1.Move(x1,y1);
138 pO->SetSnapRect(aR1);
139 } else {
140 OSL_FAIL("SetMarkedObjRect(): pObj->GetSnapRect() returns empty Rect");
143 if( bUndo )
144 EndUndo();
147 std::vector< SdrUndoAction* > SdrEditView::CreateConnectorUndo( SdrObject& rO )
149 std::vector< SdrUndoAction* > vUndoActions;
151 if ( rO.GetBroadcaster() )
153 const SdrPage* pPage = rO.GetPage();
154 if ( pPage )
156 SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS );
157 while( aIter.IsMore() )
159 SdrObject* pPartObj = aIter.Next();
160 if ( pPartObj->ISA( SdrEdgeObj ) )
162 if ( ( pPartObj->GetConnectedNode( false ) == &rO ) ||
163 ( pPartObj->GetConnectedNode( true ) == &rO ) )
165 vUndoActions.push_back( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject( *pPartObj ) );
171 return vUndoActions;
174 void SdrEditView::AddUndoActions( std::vector< SdrUndoAction* >& rUndoActions )
176 std::vector< SdrUndoAction* >::iterator aUndoActionIter( rUndoActions.begin() );
177 while( aUndoActionIter != rUndoActions.end() )
178 AddUndo( *aUndoActionIter++ );
181 void SdrEditView::MoveMarkedObj(const Size& rSiz, bool bCopy)
183 const bool bUndo = IsUndoEnabled();
185 if( bUndo )
187 OUString aStr(ImpGetResStr(STR_EditMove));
188 if (bCopy)
189 aStr += ImpGetResStr(STR_EditWithCopy);
190 // meeds its own UndoGroup because of its parameters
191 BegUndo(aStr,GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVE);
194 if (bCopy)
195 CopyMarkedObj();
197 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
198 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
200 SdrMark* pM=GetSdrMarkByIndex(nm);
201 SdrObject* pO=pM->GetMarkedSdrObj();
202 if( bUndo )
204 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
205 AddUndoActions( vConnectorUndoActions );
206 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pO,rSiz));
208 pO->Move(rSiz);
211 if( bUndo )
212 EndUndo();
215 void SdrEditView::ResizeMarkedObj(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bCopy)
217 const bool bUndo = IsUndoEnabled();
218 if( bUndo )
220 OUString aStr;
221 ImpTakeDescriptionStr(STR_EditResize,aStr);
222 if (bCopy)
223 aStr+=ImpGetResStr(STR_EditWithCopy);
224 BegUndo(aStr);
227 if (bCopy)
228 CopyMarkedObj();
230 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
231 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
233 SdrMark* pM=GetSdrMarkByIndex(nm);
234 SdrObject* pO=pM->GetMarkedSdrObj();
235 if( bUndo )
237 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
238 AddUndoActions( vConnectorUndoActions );
239 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
241 pO->Resize(rRef,xFact,yFact);
244 if( bUndo )
245 EndUndo();
247 void SdrEditView::ResizeMultMarkedObj(const Point& rRef,
248 const Fraction& xFact,
249 const Fraction& yFact,
250 const bool bCopy,
251 const bool bWdh,
252 const bool bHgt)
254 const bool bUndo = IsUndoEnabled();
255 if( bUndo )
257 OUString aStr;
258 ImpTakeDescriptionStr(STR_EditResize,aStr);
259 if (bCopy)
260 aStr+=ImpGetResStr(STR_EditWithCopy);
261 BegUndo(aStr);
264 if (bCopy)
265 CopyMarkedObj();
267 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
268 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
270 SdrMark* pM=GetSdrMarkByIndex(nm);
271 SdrObject* pO=pM->GetMarkedSdrObj();
272 if( bUndo )
274 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
275 AddUndoActions( vConnectorUndoActions );
276 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
279 Fraction aFrac(1,1);
280 if (bWdh && bHgt)
281 pO->Resize(rRef, xFact, yFact);
282 else if (bWdh)
283 pO->Resize(rRef, xFact, aFrac);
284 else if (bHgt)
285 pO->Resize(rRef, aFrac, yFact);
287 if( bUndo )
288 EndUndo();
291 long SdrEditView::GetMarkedObjRotate() const
293 long nRetval(0);
295 if(GetMarkedObjectCount())
297 SdrMark* pM = GetSdrMarkByIndex(0);
298 SdrObject* pO = pM->GetMarkedSdrObj();
300 nRetval = pO->GetRotateAngle();
303 return nRetval;
304 //sal_Bool b1st=true;
305 //sal_Bool bOk=true;
306 //long nWink=0;
307 //sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
308 //for (sal_uIntPtr nm=0; nm<nMarkAnz && bOk; nm++) {
309 // SdrMark* pM=GetSdrMarkByIndex(nm);
310 // SdrObject* pO=pM->GetMarkedSdrObj();
311 // long nWink2=pO->GetRotateAngle();
312 // if (b1st) nWink=nWink2;
313 // else if (nWink2!=nWink) bOk=false;
314 // b1st=false;
316 //if (!bOk) nWink=0;
317 //return nWink;
320 void SdrEditView::RotateMarkedObj(const Point& rRef, long nWink, bool bCopy)
322 const bool bUndo = IsUndoEnabled();
323 if( bUndo )
325 OUString aStr;
326 ImpTakeDescriptionStr(STR_EditRotate,aStr);
327 if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy);
328 BegUndo(aStr);
331 if (bCopy)
332 CopyMarkedObj();
334 double nSin=sin(nWink*nPi180);
335 double nCos=cos(nWink*nPi180);
336 const sal_uInt32 nMarkAnz(GetMarkedObjectCount());
338 if(nMarkAnz)
340 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
342 for(sal_uInt32 nm(0); nm < nMarkAnz; nm++)
344 SdrMark* pM = GetSdrMarkByIndex(nm);
345 SdrObject* pO = pM->GetMarkedSdrObj();
347 if( bUndo )
349 // extra undo actions for changed connector which now may hold its laid out path (SJ)
350 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
351 AddUndoActions( vConnectorUndoActions );
353 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
356 // set up a scene updater if object is a 3d object
357 if(dynamic_cast< E3dObject* >(pO))
359 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO));
362 pO->Rotate(rRef,nWink,nSin,nCos);
365 // fire scene updaters
366 while(!aUpdaters.empty())
368 delete aUpdaters.back();
369 aUpdaters.pop_back();
373 if( bUndo )
374 EndUndo();
377 void SdrEditView::MirrorMarkedObj(const Point& rRef1, const Point& rRef2, bool bCopy)
379 const bool bUndo = IsUndoEnabled();
381 if( bUndo )
383 OUString aStr;
384 Point aDif(rRef2-rRef1);
385 if (aDif.X()==0) ImpTakeDescriptionStr(STR_EditMirrorHori,aStr);
386 else if (aDif.Y()==0) ImpTakeDescriptionStr(STR_EditMirrorVert,aStr);
387 else if (std::abs(aDif.X()) == std::abs(aDif.Y())) ImpTakeDescriptionStr(STR_EditMirrorDiag,aStr);
388 else ImpTakeDescriptionStr(STR_EditMirrorFree,aStr);
389 if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy);
390 BegUndo(aStr);
393 if (bCopy)
394 CopyMarkedObj();
396 const sal_uInt32 nMarkAnz(GetMarkedObjectCount());
398 if(nMarkAnz)
400 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
402 for(sal_uInt32 nm(0); nm < nMarkAnz; nm++)
404 SdrMark* pM = GetSdrMarkByIndex(nm);
405 SdrObject* pO = pM->GetMarkedSdrObj();
407 if( bUndo )
409 // extra undo actions for changed connector which now may hold its laid out path (SJ)
410 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
411 AddUndoActions( vConnectorUndoActions );
413 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
416 // set up a scene updater if object is a 3d object
417 if(dynamic_cast< E3dObject* >(pO))
419 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO));
422 pO->Mirror(rRef1,rRef2);
425 // fire scene updaters
426 while(!aUpdaters.empty())
428 delete aUpdaters.back();
429 aUpdaters.pop_back();
433 if( bUndo )
434 EndUndo();
437 void SdrEditView::MirrorMarkedObjHorizontal(bool bCopy)
439 Point aCenter(GetMarkedObjRect().Center());
440 Point aPt2(aCenter);
441 aPt2.Y()++;
442 MirrorMarkedObj(aCenter,aPt2,bCopy);
445 void SdrEditView::MirrorMarkedObjVertical(bool bCopy)
447 Point aCenter(GetMarkedObjRect().Center());
448 Point aPt2(aCenter);
449 aPt2.X()++;
450 MirrorMarkedObj(aCenter,aPt2,bCopy);
453 long SdrEditView::GetMarkedObjShear() const
455 bool b1st=true;
456 bool bOk=true;
457 long nWink=0;
458 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
459 for (sal_uIntPtr nm=0; nm<nMarkAnz && bOk; nm++) {
460 SdrMark* pM=GetSdrMarkByIndex(nm);
461 SdrObject* pO=pM->GetMarkedSdrObj();
462 long nWink2=pO->GetShearAngle();
463 if (b1st) nWink=nWink2;
464 else if (nWink2!=nWink) bOk=false;
465 b1st=false;
467 if (nWink>SDRMAXSHEAR) nWink=SDRMAXSHEAR;
468 if (nWink<-SDRMAXSHEAR) nWink=-SDRMAXSHEAR;
469 if (!bOk) nWink=0;
470 return nWink;
473 void SdrEditView::ShearMarkedObj(const Point& rRef, long nWink, bool bVShear, bool bCopy)
475 const bool bUndo = IsUndoEnabled();
477 if( bUndo )
479 OUString aStr;
480 ImpTakeDescriptionStr(STR_EditShear,aStr);
481 if (bCopy)
482 aStr+=ImpGetResStr(STR_EditWithCopy);
483 BegUndo(aStr);
486 if (bCopy)
487 CopyMarkedObj();
489 double nTan=tan(nWink*nPi180);
490 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
491 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
493 SdrMark* pM=GetSdrMarkByIndex(nm);
494 SdrObject* pO=pM->GetMarkedSdrObj();
495 if( bUndo )
497 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
498 AddUndoActions( vConnectorUndoActions );
499 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
501 pO->Shear(rRef,nWink,nTan,bVShear);
504 if( bUndo )
505 EndUndo();
508 void SdrEditView::ImpCrookObj(SdrObject* pO, const Point& rRef, const Point& rRad,
509 SdrCrookMode eMode, bool bVertical, bool bNoContortion, bool bRotate, const Rectangle& rMarkRect)
511 SdrPathObj* pPath=PTR_CAST(SdrPathObj,pO);
512 bool bDone = false;
514 if(pPath!=NULL && !bNoContortion)
516 XPolyPolygon aXPP(pPath->GetPathPoly());
517 switch (eMode) {
518 case SDRCROOK_ROTATE : CrookRotatePoly (aXPP,rRef,rRad,bVertical); break;
519 case SDRCROOK_SLANT : CrookSlantPoly (aXPP,rRef,rRad,bVertical); break;
520 case SDRCROOK_STRETCH: CrookStretchPoly(aXPP,rRef,rRad,bVertical,rMarkRect); break;
521 } // switch
522 pPath->SetPathPoly(aXPP.getB2DPolyPolygon());
523 bDone = true;
526 if(!bDone && !pPath && pO->IsPolyObj() && 0L != pO->GetPointCount())
528 // for PolyObj's, but NOT for SdrPathObj's, e.g. the measurement object
529 sal_uInt32 nPtAnz(pO->GetPointCount());
530 XPolygon aXP((sal_uInt16)nPtAnz);
531 sal_uInt32 nPtNum;
533 for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++)
535 Point aPt(pO->GetPoint(nPtNum));
536 aXP[(sal_uInt16)nPtNum]=aPt;
539 switch (eMode)
541 case SDRCROOK_ROTATE : CrookRotatePoly (aXP,rRef,rRad,bVertical); break;
542 case SDRCROOK_SLANT : CrookSlantPoly (aXP,rRef,rRad,bVertical); break;
543 case SDRCROOK_STRETCH: CrookStretchPoly(aXP,rRef,rRad,bVertical,rMarkRect); break;
546 for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++)
548 // broadcasting could be optimized here, but for the
549 // current two points of the measurement object, it's fine
550 pO->SetPoint(aXP[(sal_uInt16)nPtNum],nPtNum);
553 bDone = true;
556 if(!bDone)
558 // for all others or if bNoContortion
559 Point aCtr0(pO->GetSnapRect().Center());
560 Point aCtr1(aCtr0);
561 bool bRotOk(false);
562 double nSin(0.0), nCos(1.0);
563 double nWink(0.0);
565 if(0 != rRad.X() && 0 != rRad.Y())
567 bRotOk = bRotate;
569 switch (eMode)
571 case SDRCROOK_ROTATE : nWink=CrookRotateXPoint (aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical); bRotOk=bRotate; break;
572 case SDRCROOK_SLANT : nWink=CrookSlantXPoint (aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical); break;
573 case SDRCROOK_STRETCH: nWink=CrookStretchXPoint(aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical,rMarkRect); break;
577 aCtr1 -= aCtr0;
579 if(bRotOk)
580 pO->Rotate(aCtr0, Round(nWink/nPi180), nSin, nCos);
582 pO->Move(Size(aCtr1.X(),aCtr1.Y()));
586 void SdrEditView::CrookMarkedObj(const Point& rRef, const Point& rRad, SdrCrookMode eMode,
587 bool bVertical, bool bNoContortion, bool bCopy)
589 Rectangle aMarkRect(GetMarkedObjRect());
590 const bool bUndo = IsUndoEnabled();
592 bool bRotate=bNoContortion && eMode==SDRCROOK_ROTATE && IsRotateAllowed(false);
594 if( bUndo )
596 OUString aStr;
597 ImpTakeDescriptionStr(bNoContortion?STR_EditCrook:STR_EditCrookContortion,aStr);
598 if (bCopy)
599 aStr+=ImpGetResStr(STR_EditWithCopy);
600 BegUndo(aStr);
603 if (bCopy)
604 CopyMarkedObj();
606 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
607 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
609 SdrMark* pM=GetSdrMarkByIndex(nm);
610 SdrObject* pO=pM->GetMarkedSdrObj();
611 if( bUndo )
612 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
614 const SdrObjList* pOL=pO->GetSubList();
615 if (bNoContortion || pOL==NULL) {
616 ImpCrookObj(pO,rRef,rRad,eMode,bVertical,bNoContortion,bRotate,aMarkRect);
617 } else {
618 SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS);
619 while (aIter.IsMore()) {
620 SdrObject* pO1=aIter.Next();
621 ImpCrookObj(pO1,rRef,rRad,eMode,bVertical,bNoContortion,bRotate,aMarkRect);
626 if( bUndo )
627 EndUndo();
630 void SdrEditView::ImpDistortObj(SdrObject* pO, const Rectangle& rRef, const XPolygon& rDistortedRect, bool bNoContortion)
632 SdrPathObj* pPath = PTR_CAST(SdrPathObj, pO);
634 if(!bNoContortion && pPath)
636 XPolyPolygon aXPP(pPath->GetPathPoly());
637 aXPP.Distort(rRef, rDistortedRect);
638 pPath->SetPathPoly(aXPP.getB2DPolyPolygon());
640 else if(pO->IsPolyObj())
642 // e. g. for the measurement object
643 sal_uInt32 nPtAnz(pO->GetPointCount());
644 XPolygon aXP((sal_uInt16)nPtAnz);
645 sal_uInt32 nPtNum;
647 for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++)
649 Point aPt(pO->GetPoint(nPtNum));
650 aXP[(sal_uInt16)nPtNum]=aPt;
653 aXP.Distort(rRef, rDistortedRect);
655 for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++)
657 // broadcasting could be optimized here, but for the
658 // current two points of the measurement object it's fine
659 pO->SetPoint(aXP[(sal_uInt16)nPtNum],nPtNum);
664 void SdrEditView::DistortMarkedObj(const Rectangle& rRef, const XPolygon& rDistortedRect, bool bNoContortion, bool bCopy)
666 const bool bUndo = IsUndoEnabled();
668 if( bUndo )
670 OUString aStr;
671 ImpTakeDescriptionStr(STR_EditDistort,aStr);
672 if (bCopy)
673 aStr+=ImpGetResStr(STR_EditWithCopy);
674 BegUndo(aStr);
677 if (bCopy)
678 CopyMarkedObj();
680 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
681 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
683 SdrMark* pM=GetSdrMarkByIndex(nm);
684 SdrObject* pO=pM->GetMarkedSdrObj();
685 if( bUndo )
686 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
688 Rectangle aRefRect(rRef);
689 XPolygon aRefPoly(rDistortedRect);
690 const SdrObjList* pOL=pO->GetSubList();
691 if (bNoContortion || pOL==NULL) {
692 ImpDistortObj(pO,aRefRect,aRefPoly,bNoContortion);
693 } else {
694 SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS);
695 while (aIter.IsMore()) {
696 SdrObject* pO1=aIter.Next();
697 ImpDistortObj(pO1,aRefRect,aRefPoly,bNoContortion);
701 if( bUndo )
702 EndUndo();
707 void SdrEditView::SetNotPersistAttrToMarked(const SfxItemSet& rAttr, bool /*bReplaceAll*/)
709 // bReplaceAll has no effect here
710 Rectangle aAllSnapRect(GetMarkedObjRect());
711 const SfxPoolItem *pPoolItem=NULL;
712 if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1X,true,&pPoolItem)==SFX_ITEM_SET) {
713 long n=((const SdrTransformRef1XItem*)pPoolItem)->GetValue();
714 SetRef1(Point(n,GetRef1().Y()));
716 if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1Y,true,&pPoolItem)==SFX_ITEM_SET) {
717 long n=((const SdrTransformRef1YItem*)pPoolItem)->GetValue();
718 SetRef1(Point(GetRef1().X(),n));
720 if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2X,true,&pPoolItem)==SFX_ITEM_SET) {
721 long n=((const SdrTransformRef2XItem*)pPoolItem)->GetValue();
722 SetRef2(Point(n,GetRef2().Y()));
724 if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2Y,true,&pPoolItem)==SFX_ITEM_SET) {
725 long n=((const SdrTransformRef2YItem*)pPoolItem)->GetValue();
726 SetRef2(Point(GetRef2().X(),n));
728 long nAllPosX=0; bool bAllPosX=false;
729 long nAllPosY=0; bool bAllPosY=false;
730 long nAllWdt=0; bool bAllWdt=false;
731 long nAllHgt=0; bool bAllHgt=false;
732 bool bDoIt=false;
733 if (rAttr.GetItemState(SDRATTR_ALLPOSITIONX,true,&pPoolItem)==SFX_ITEM_SET) {
734 nAllPosX=((const SdrAllPositionXItem*)pPoolItem)->GetValue();
735 bAllPosX=true; bDoIt=true;
737 if (rAttr.GetItemState(SDRATTR_ALLPOSITIONY,true,&pPoolItem)==SFX_ITEM_SET) {
738 nAllPosY=((const SdrAllPositionYItem*)pPoolItem)->GetValue();
739 bAllPosY=true; bDoIt=true;
741 if (rAttr.GetItemState(SDRATTR_ALLSIZEWIDTH,true,&pPoolItem)==SFX_ITEM_SET) {
742 nAllWdt=((const SdrAllSizeWidthItem*)pPoolItem)->GetValue();
743 bAllWdt=true; bDoIt=true;
745 if (rAttr.GetItemState(SDRATTR_ALLSIZEHEIGHT,true,&pPoolItem)==SFX_ITEM_SET) {
746 nAllHgt=((const SdrAllSizeHeightItem*)pPoolItem)->GetValue();
747 bAllHgt=true; bDoIt=true;
749 if (bDoIt) {
750 Rectangle aRect(aAllSnapRect); // TODO: change this for PolyPt's and GluePt's!!!
751 if (bAllPosX) aRect.Move(nAllPosX-aRect.Left(),0);
752 if (bAllPosY) aRect.Move(0,nAllPosY-aRect.Top());
753 if (bAllWdt) aRect.Right()=aAllSnapRect.Left()+nAllWdt;
754 if (bAllHgt) aRect.Bottom()=aAllSnapRect.Top()+nAllHgt;
755 SetMarkedObjRect(aRect);
757 if (rAttr.GetItemState(SDRATTR_RESIZEXALL,true,&pPoolItem)==SFX_ITEM_SET) {
758 Fraction aXFact=((const SdrResizeXAllItem*)pPoolItem)->GetValue();
759 ResizeMarkedObj(aAllSnapRect.TopLeft(),aXFact,Fraction(1,1));
761 if (rAttr.GetItemState(SDRATTR_RESIZEYALL,true,&pPoolItem)==SFX_ITEM_SET) {
762 Fraction aYFact=((const SdrResizeYAllItem*)pPoolItem)->GetValue();
763 ResizeMarkedObj(aAllSnapRect.TopLeft(),Fraction(1,1),aYFact);
765 if (rAttr.GetItemState(SDRATTR_ROTATEALL,true,&pPoolItem)==SFX_ITEM_SET) {
766 long nAngle=((const SdrRotateAllItem*)pPoolItem)->GetValue();
767 RotateMarkedObj(aAllSnapRect.Center(),nAngle);
769 if (rAttr.GetItemState(SDRATTR_HORZSHEARALL,true,&pPoolItem)==SFX_ITEM_SET) {
770 long nAngle=((const SdrHorzShearAllItem*)pPoolItem)->GetValue();
771 ShearMarkedObj(aAllSnapRect.Center(),nAngle,false);
773 if (rAttr.GetItemState(SDRATTR_VERTSHEARALL,true,&pPoolItem)==SFX_ITEM_SET) {
774 long nAngle=((const SdrVertShearAllItem*)pPoolItem)->GetValue();
775 ShearMarkedObj(aAllSnapRect.Center(),nAngle,true);
778 const bool bUndo = IsUndoEnabled();
780 // TODO: check if WhichRange is necessary.
781 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
782 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
784 const SdrMark* pM=GetSdrMarkByIndex(nm);
785 SdrObject* pObj=pM->GetMarkedSdrObj();
786 if( bUndo )
787 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
789 pObj->ApplyNotPersistAttr(rAttr);
793 void SdrEditView::MergeNotPersistAttrFromMarked(SfxItemSet& rAttr, bool /*bOnlyHardAttr*/) const
795 // bOnlyHardAttr has no effect here.
796 // TODO: Take into account the origin and PvPos.
797 Rectangle aAllSnapRect(GetMarkedObjRect()); // TODO: change this for PolyPt's and GluePt's!!!
798 long nAllSnapPosX=aAllSnapRect.Left();
799 long nAllSnapPosY=aAllSnapRect.Top();
800 long nAllSnapWdt=aAllSnapRect.GetWidth()-1;
801 long nAllSnapHgt=aAllSnapRect.GetHeight()-1;
802 // TODO: could go into CheckPossibilities
803 bool bMovProtect = false, bMovProtectDC = false;
804 bool bSizProtect = false, bSizProtectDC = false;
805 bool bPrintable = true, bPrintableDC = false;
806 bool bVisible = true, bVisibleDC = false;
807 SdrLayerID nLayerId=0; bool bLayerDC=false;
808 OUString aObjName;
809 bool bObjNameDC=false,bObjNameSet=false;
810 long nSnapPosX=0; bool bSnapPosXDC=false;
811 long nSnapPosY=0; bool bSnapPosYDC=false;
812 long nSnapWdt=0; bool bSnapWdtDC=false;
813 long nSnapHgt=0; bool bSnapHgtDC=false;
814 long nLogicWdt=0; bool bLogicWdtDC=false,bLogicWdtDiff=false;
815 long nLogicHgt=0; bool bLogicHgtDC=false,bLogicHgtDiff=false;
816 long nRotAngle=0; bool bRotAngleDC=false;
817 long nShrAngle=0; bool bShrAngleDC=false;
818 Rectangle aSnapRect;
819 Rectangle aLogicRect;
820 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
821 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++) {
822 const SdrMark* pM=GetSdrMarkByIndex(nm);
823 const SdrObject* pObj=pM->GetMarkedSdrObj();
824 if (nm==0) {
825 nLayerId=pObj->GetLayer();
826 bMovProtect=pObj->IsMoveProtect();
827 bSizProtect=pObj->IsResizeProtect();
828 bPrintable =pObj->IsPrintable();
829 bVisible = pObj->IsVisible();
830 Rectangle aSnapRect2(pObj->GetSnapRect());
831 Rectangle aLogicRect2(pObj->GetLogicRect());
832 nSnapPosX=aSnapRect2.Left();
833 nSnapPosY=aSnapRect2.Top();
834 nSnapWdt=aSnapRect2.GetWidth()-1;
835 nSnapHgt=aSnapRect2.GetHeight()-1;
836 nLogicWdt=aLogicRect2.GetWidth()-1;
837 nLogicHgt=aLogicRect2.GetHeight()-1;
838 bLogicWdtDiff=nLogicWdt!=nSnapWdt;
839 bLogicHgtDiff=nLogicHgt!=nSnapHgt;
840 nRotAngle=pObj->GetRotateAngle();
841 nShrAngle=pObj->GetShearAngle();
842 } else {
843 if (!bLayerDC && nLayerId !=pObj->GetLayer()) bLayerDC = true;
844 if (!bMovProtectDC && bMovProtect!=pObj->IsMoveProtect()) bMovProtectDC = true;
845 if (!bSizProtectDC && bSizProtect!=pObj->IsResizeProtect()) bSizProtectDC = true;
846 if (!bPrintableDC && bPrintable !=pObj->IsPrintable()) bPrintableDC = true;
847 if (!bVisibleDC && bVisible !=pObj->IsVisible()) bVisibleDC=true;
848 if (!bRotAngleDC && nRotAngle !=pObj->GetRotateAngle()) bRotAngleDC=true;
849 if (!bShrAngleDC && nShrAngle !=pObj->GetShearAngle()) bShrAngleDC=true;
850 if (!bSnapWdtDC || !bSnapHgtDC || !bSnapPosXDC || !bSnapPosYDC || !bLogicWdtDiff || !bLogicHgtDiff) {
851 aSnapRect=pObj->GetSnapRect();
852 if (nSnapPosX!=aSnapRect.Left()) bSnapPosXDC=true;
853 if (nSnapPosY!=aSnapRect.Top()) bSnapPosYDC=true;
854 if (nSnapWdt!=aSnapRect.GetWidth()-1) bSnapWdtDC=true;
855 if (nSnapHgt!=aSnapRect.GetHeight()-1) bSnapHgtDC=true;
857 if (!bLogicWdtDC || !bLogicHgtDC || !bLogicWdtDiff || !bLogicHgtDiff) {
858 aLogicRect=pObj->GetLogicRect();
859 if (nLogicWdt!=aLogicRect.GetWidth()-1) bLogicWdtDC=true;
860 if (nLogicHgt!=aLogicRect.GetHeight()-1) bLogicHgtDC=true;
861 if (!bLogicWdtDiff && aSnapRect.GetWidth()!=aLogicRect.GetWidth()) bLogicWdtDiff=true;
862 if (!bLogicHgtDiff && aSnapRect.GetHeight()!=aLogicRect.GetHeight()) bLogicHgtDiff=true;
865 if (!bObjNameDC ) {
866 if (!bObjNameSet) {
867 aObjName=pObj->GetName();
868 } else {
869 if (!aObjName.equals(pObj->GetName()))
870 bObjNameDC = true;
875 if (bSnapPosXDC || nAllSnapPosX!=nSnapPosX) rAttr.Put(SdrAllPositionXItem(nAllSnapPosX));
876 if (bSnapPosYDC || nAllSnapPosY!=nSnapPosY) rAttr.Put(SdrAllPositionYItem(nAllSnapPosY));
877 if (bSnapWdtDC || nAllSnapWdt !=nSnapWdt ) rAttr.Put(SdrAllSizeWidthItem(nAllSnapWdt));
878 if (bSnapHgtDC || nAllSnapHgt !=nSnapHgt ) rAttr.Put(SdrAllSizeHeightItem(nAllSnapHgt));
880 // items for pure transformations
881 rAttr.Put(SdrMoveXItem());
882 rAttr.Put(SdrMoveYItem());
883 rAttr.Put(SdrResizeXOneItem());
884 rAttr.Put(SdrResizeYOneItem());
885 rAttr.Put(SdrRotateOneItem());
886 rAttr.Put(SdrHorzShearOneItem());
887 rAttr.Put(SdrVertShearOneItem());
889 if (nMarkAnz>1) {
890 rAttr.Put(SdrResizeXAllItem());
891 rAttr.Put(SdrResizeYAllItem());
892 rAttr.Put(SdrRotateAllItem());
893 rAttr.Put(SdrHorzShearAllItem());
894 rAttr.Put(SdrVertShearAllItem());
897 if(eDragMode == SDRDRAG_ROTATE || eDragMode == SDRDRAG_MIRROR)
899 rAttr.Put(SdrTransformRef1XItem(GetRef1().X()));
900 rAttr.Put(SdrTransformRef1YItem(GetRef1().Y()));
903 if(eDragMode == SDRDRAG_MIRROR)
905 rAttr.Put(SdrTransformRef2XItem(GetRef2().X()));
906 rAttr.Put(SdrTransformRef2YItem(GetRef2().Y()));
910 SfxItemSet SdrEditView::GetAttrFromMarked(bool bOnlyHardAttr) const
912 SfxItemSet aSet(pMod->GetItemPool());
913 MergeAttrFromMarked(aSet,bOnlyHardAttr);
914 //the EE_FEATURE items should not be set with SetAttrToMarked (see error message there)
915 //so we do not set them here
916 // #i32448#
917 // Do not disable, but clear the items.
918 aSet.ClearItem(EE_FEATURE_TAB);
919 aSet.ClearItem(EE_FEATURE_LINEBR);
920 aSet.ClearItem(EE_FEATURE_NOTCONV);
921 aSet.ClearItem(EE_FEATURE_FIELD);
922 return aSet;
925 void SdrEditView::MergeAttrFromMarked(SfxItemSet& rAttr, bool bOnlyHardAttr) const
927 sal_uInt32 nMarkAnz(GetMarkedObjectCount());
929 for(sal_uInt32 a(0); a < nMarkAnz; a++)
931 // #80277# merging was done wrong in the prev version
932 const SfxItemSet& rSet = GetMarkedObjectByIndex(a)->GetMergedItemSet();
933 SfxWhichIter aIter(rSet);
934 sal_uInt16 nWhich(aIter.FirstWhich());
936 while(nWhich)
938 if(!bOnlyHardAttr)
940 if(SFX_ITEM_DONTCARE == rSet.GetItemState(nWhich, false))
941 rAttr.InvalidateItem(nWhich);
942 else
943 rAttr.MergeValue(rSet.Get(nWhich), true);
945 else if(SFX_ITEM_SET == rSet.GetItemState(nWhich, false))
947 const SfxPoolItem& rItem = rSet.Get(nWhich);
948 rAttr.MergeValue(rItem, true);
951 nWhich = aIter.NextWhich();
956 void SdrEditView::SetAttrToMarked(const SfxItemSet& rAttr, bool bReplaceAll)
958 if (AreObjectsMarked())
960 #ifdef DBG_UTIL
962 bool bHasEEFeatureItems=false;
963 SfxItemIter aIter(rAttr);
964 const SfxPoolItem* pItem=aIter.FirstItem();
965 while (!bHasEEFeatureItems && pItem!=NULL) {
966 if (!IsInvalidItem(pItem)) {
967 sal_uInt16 nW=pItem->Which();
968 if (nW>=EE_FEATURE_START && nW<=EE_FEATURE_END) bHasEEFeatureItems=true;
970 pItem=aIter.NextItem();
972 if(bHasEEFeatureItems)
974 OUString aMessage("SdrEditView::SetAttrToMarked(): Setting EE_FEATURE items at the SdrView does not make sense! It only leads to overhead and unreadable documents.");
975 InfoBox(NULL, aMessage).Execute();
978 #endif
980 // #103836# if the user thets character attributes to the complete shape,
981 // we want to remove all hard set character attributes with same
982 // which ids from the text. We do that later but here we remember
983 // all character attribute which id's that are set.
984 std::vector<sal_uInt16> aCharWhichIds;
986 SfxItemIter aIter(rAttr);
987 const SfxPoolItem* pItem=aIter.FirstItem();
988 while( pItem!=NULL )
990 if (!IsInvalidItem(pItem))
992 sal_uInt16 nWhich = pItem->Which();
993 if (nWhich>=EE_CHAR_START && nWhich<=EE_CHAR_END)
994 aCharWhichIds.push_back( nWhich );
996 pItem=aIter.NextItem();
1000 // To make Undo reconstruct text attributes correctly after Format.Standard
1001 bool bHasEEItems=SearchOutlinerItems(rAttr,bReplaceAll);
1003 // save additional geometry information when paragraph or character attributes
1004 // are changed and the geometrical shape of the text object might be changed
1005 bool bPossibleGeomChange(false);
1006 SfxWhichIter aIter(rAttr);
1007 sal_uInt16 nWhich = aIter.FirstWhich();
1008 while(!bPossibleGeomChange && nWhich)
1010 SfxItemState eState = rAttr.GetItemState(nWhich);
1011 if(eState == SFX_ITEM_SET)
1013 if((nWhich >= SDRATTR_TEXT_MINFRAMEHEIGHT && nWhich <= SDRATTR_TEXT_CONTOURFRAME)
1014 || nWhich == SDRATTR_3DOBJ_PERCENT_DIAGONAL
1015 || nWhich == SDRATTR_3DOBJ_BACKSCALE
1016 || nWhich == SDRATTR_3DOBJ_DEPTH
1017 || nWhich == SDRATTR_3DOBJ_END_ANGLE
1018 || nWhich == SDRATTR_3DSCENE_DISTANCE)
1020 bPossibleGeomChange = true;
1023 nWhich = aIter.NextWhich();
1026 const bool bUndo = IsUndoEnabled();
1027 if( bUndo )
1029 OUString aStr;
1030 ImpTakeDescriptionStr(STR_EditSetAttributes,aStr);
1031 BegUndo(aStr);
1034 const sal_uInt32 nMarkAnz(GetMarkedObjectCount());
1035 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
1037 // create ItemSet without SFX_ITEM_DONTCARE. Put()
1038 // uses its second parameter (bInvalidAsDefault) to
1039 // remove all such items to set them to default.
1040 SfxItemSet aAttr(*rAttr.GetPool(), rAttr.GetRanges());
1041 aAttr.Put(rAttr, true);
1043 // #i38135#
1044 bool bResetAnimationTimer(false);
1046 // check if LineWidth is part of the change
1047 const bool bLineWidthChange(SFX_ITEM_SET == aAttr.GetItemState(XATTR_LINEWIDTH));
1048 sal_Int32 nNewLineWidth(0);
1049 sal_Int32 nOldLineWidth(0);
1051 if(bLineWidthChange)
1053 nNewLineWidth = ((const XLineWidthItem&)aAttr.Get(XATTR_LINEWIDTH)).GetValue();
1056 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
1058 SdrMark* pM=GetSdrMarkByIndex(nm);
1059 SdrObject* pObj = pM->GetMarkedSdrObj();
1061 if( bUndo )
1063 std::vector< SdrUndoAction* > vConnectorUndoActions;
1064 SdrEdgeObj* pEdgeObj = dynamic_cast< SdrEdgeObj* >( pObj );
1065 if ( pEdgeObj )
1066 bPossibleGeomChange = true;
1067 else if( bUndo )
1068 vConnectorUndoActions = CreateConnectorUndo( *pObj );
1070 AddUndoActions( vConnectorUndoActions );
1073 // new geometry undo
1074 if(bPossibleGeomChange && bUndo)
1076 // save position and size of object, too
1077 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
1080 if( bUndo )
1082 // #i8508#
1083 // If this is a text object also rescue the OutlinerParaObject since
1084 // applying attributes to the object may change text layout when
1085 // multiple portions exist with multiple formats. If a OutlinerParaObject
1086 // really exists and needs to be rescued is evaluated in the undo
1087 // implementation itself.
1088 const bool bRescueText = dynamic_cast< SdrTextObj* >(pObj) != 0;
1090 // add attribute undo
1091 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj,false,bHasEEItems || bPossibleGeomChange || bRescueText));
1094 // set up a scene updater if object is a 3d object
1095 if(dynamic_cast< E3dObject* >(pObj))
1097 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pObj));
1100 if(bLineWidthChange)
1102 nOldLineWidth = ((const XLineWidthItem&)pObj->GetMergedItem(XATTR_LINEWIDTH)).GetValue();
1105 // set attributes at object
1106 pObj->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
1108 if(bLineWidthChange)
1110 const SfxItemSet& rSet = pObj->GetMergedItemSet();
1112 if(nOldLineWidth != nNewLineWidth)
1114 if(SFX_ITEM_DONTCARE != rSet.GetItemState(XATTR_LINESTARTWIDTH))
1116 const sal_Int32 nValAct(((const XLineStartWidthItem&)rSet.Get(XATTR_LINESTARTWIDTH)).GetValue());
1117 const sal_Int32 nValNewStart(std::max((sal_Int32)0, nValAct + (((nNewLineWidth - nOldLineWidth) * 15) / 10)));
1119 pObj->SetMergedItem(XLineStartWidthItem(nValNewStart));
1122 if(SFX_ITEM_DONTCARE != rSet.GetItemState(XATTR_LINEENDWIDTH))
1124 const sal_Int32 nValAct(((const XLineEndWidthItem&)rSet.Get(XATTR_LINEENDWIDTH)).GetValue());
1125 const sal_Int32 nValNewEnd(std::max((sal_Int32)0, nValAct + (((nNewLineWidth - nOldLineWidth) * 15) / 10)));
1127 pObj->SetMergedItem(XLineEndWidthItem(nValNewEnd));
1132 if(pObj->ISA(SdrTextObj))
1134 SdrTextObj* pTextObj = ((SdrTextObj*)pObj);
1136 if(!aCharWhichIds.empty())
1138 Rectangle aOldBoundRect = pTextObj->GetLastBoundRect();
1140 // #110094#-14 pTextObj->SendRepaintBroadcast(pTextObj->GetBoundRect());
1141 pTextObj->RemoveOutlinerCharacterAttribs( aCharWhichIds );
1143 // object has changed, should be called from
1144 // RemoveOutlinerCharacterAttribs. This will change when the text
1145 // object implementation changes.
1146 pTextObj->SetChanged();
1148 pTextObj->BroadcastObjectChange();
1149 pTextObj->SendUserCall(SDRUSERCALL_CHGATTR, aOldBoundRect);
1153 // #i38495#
1154 if(!bResetAnimationTimer)
1156 if(pObj->GetViewContact().isAnimatedInAnyViewObjectContact())
1158 bResetAnimationTimer = true;
1163 // fire scene updaters
1164 while(!aUpdaters.empty())
1166 delete aUpdaters.back();
1167 aUpdaters.pop_back();
1170 // #i38135#
1171 if(bResetAnimationTimer)
1173 SetAnimationTimer(0L);
1176 // better check before what to do:
1177 // pObj->SetAttr() or SetNotPersistAttr()
1178 // TODO: missing implementation!
1179 SetNotPersistAttrToMarked(rAttr,bReplaceAll);
1181 if( bUndo )
1182 EndUndo();
1186 SfxStyleSheet* SdrEditView::GetStyleSheetFromMarked() const
1188 SfxStyleSheet* pRet=NULL;
1189 bool b1st=true;
1190 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
1191 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++) {
1192 SdrMark* pM=GetSdrMarkByIndex(nm);
1193 SfxStyleSheet* pSS=pM->GetMarkedSdrObj()->GetStyleSheet();
1194 if (b1st) pRet=pSS;
1195 else if (pRet!=pSS) return NULL; // different stylesheets
1196 b1st=false;
1198 return pRet;
1201 void SdrEditView::SetStyleSheetToMarked(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
1203 if (AreObjectsMarked())
1205 const bool bUndo = IsUndoEnabled();
1207 if( bUndo )
1209 OUString aStr;
1210 if (pStyleSheet!=NULL)
1211 ImpTakeDescriptionStr(STR_EditSetStylesheet,aStr);
1212 else
1213 ImpTakeDescriptionStr(STR_EditDelStylesheet,aStr);
1214 BegUndo(aStr);
1217 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
1218 for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
1220 SdrMark* pM=GetSdrMarkByIndex(nm);
1221 if( bUndo )
1223 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pM->GetMarkedSdrObj()));
1224 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pM->GetMarkedSdrObj(),true,true));
1226 pM->GetMarkedSdrObj()->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1229 if( bUndo )
1230 EndUndo();
1236 bool SdrEditView::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
1238 if(GetMarkedObjectCount())
1240 rTargetSet.Put(GetAttrFromMarked(bOnlyHardAttr), false);
1241 return true;
1243 else
1245 return SdrMarkView::GetAttributes(rTargetSet, bOnlyHardAttr);
1249 bool SdrEditView::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
1251 if (GetMarkedObjectCount()!=0) {
1252 SetAttrToMarked(rSet,bReplaceAll);
1253 return true;
1254 } else {
1255 return SdrMarkView::SetAttributes(rSet,bReplaceAll);
1259 SfxStyleSheet* SdrEditView::GetStyleSheet() const
1261 if (GetMarkedObjectCount()!=0) {
1262 return GetStyleSheetFromMarked();
1263 } else {
1264 return SdrMarkView::GetStyleSheet();
1268 bool SdrEditView::SetStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
1270 if (GetMarkedObjectCount()!=0) {
1271 SetStyleSheetToMarked(pStyleSheet,bDontRemoveHardAttr);
1272 return true;
1273 } else {
1274 return SdrMarkView::SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1280 SfxItemSet SdrEditView::GetGeoAttrFromMarked() const
1282 SfxItemSet aRetSet(pMod->GetItemPool(), // SID_ATTR_TRANSFORM_... from s:svxids.hrc
1283 SID_ATTR_TRANSFORM_POS_X, SID_ATTR_TRANSFORM_ANGLE,
1284 SID_ATTR_TRANSFORM_PROTECT_POS, SID_ATTR_TRANSFORM_AUTOHEIGHT,
1285 SDRATTR_ECKENRADIUS, SDRATTR_ECKENRADIUS,
1288 if (AreObjectsMarked())
1290 SfxItemSet aMarkAttr(GetAttrFromMarked(false)); // because of AutoGrowHeight and corner radius
1291 Rectangle aRect(GetMarkedObjRect());
1292 // restore position to that before calc hack
1293 aRect -= GetGridOffset();
1295 if(GetSdrPageView())
1297 GetSdrPageView()->LogicToPagePos(aRect);
1300 // position
1301 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_X,aRect.Left()));
1302 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_Y,aRect.Top()));
1304 // size
1305 long nResizeRefX=aRect.Left();
1306 long nResizeRefY=aRect.Top();
1307 if (eDragMode==SDRDRAG_ROTATE) { // use rotation axis as a reference for resizing, too
1308 nResizeRefX=aRef1.X();
1309 nResizeRefY=aRef1.Y();
1311 aRetSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_WIDTH,aRect.Right()-aRect.Left()));
1312 aRetSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_HEIGHT,aRect.Bottom()-aRect.Top()));
1313 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_RESIZE_REF_X,nResizeRefX));
1314 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_RESIZE_REF_Y,nResizeRefY));
1316 Point aRotateAxe(aRef1);
1318 if(GetSdrPageView())
1320 GetSdrPageView()->LogicToPagePos(aRotateAxe);
1323 // rotation
1324 long nRotateRefX=aRect.Center().X();
1325 long nRotateRefY=aRect.Center().Y();
1326 if (eDragMode==SDRDRAG_ROTATE) {
1327 nRotateRefX=aRotateAxe.X();
1328 nRotateRefY=aRotateAxe.Y();
1330 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ANGLE,GetMarkedObjRotate()));
1331 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_X,nRotateRefX));
1332 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_Y,nRotateRefY));
1334 // shearing
1335 long nShearRefX=aRect.Left();
1336 long nShearRefY=aRect.Bottom();
1337 if (eDragMode==SDRDRAG_ROTATE) { // use rotation axis as a reference for shearing, too
1338 nShearRefX=aRotateAxe.X();
1339 nShearRefY=aRotateAxe.Y();
1341 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR,GetMarkedObjShear()));
1342 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_X,nShearRefX));
1343 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_Y,nShearRefY));
1345 // check every object whether it is protected
1346 const SdrMarkList& rMarkList=GetMarkedObjectList();
1347 sal_uIntPtr nMarkCount=rMarkList.GetMarkCount();
1348 SdrObject* pObj=rMarkList.GetMark(0)->GetMarkedSdrObj();
1349 bool bPosProt=pObj->IsMoveProtect();
1350 bool bSizProt=pObj->IsResizeProtect();
1351 bool bPosProtDontCare=false;
1352 bool bSizProtDontCare=false;
1353 for (sal_uIntPtr i=1; i<nMarkCount && (!bPosProtDontCare || !bSizProtDontCare); i++)
1355 pObj=rMarkList.GetMark(i)->GetMarkedSdrObj();
1356 if (bPosProt!=pObj->IsMoveProtect()) bPosProtDontCare=true;
1357 if (bSizProt!=pObj->IsResizeProtect()) bSizProtDontCare=true;
1360 // InvalidateItem sets item to DONT_CARE
1361 if (bPosProtDontCare) {
1362 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_PROTECT_POS);
1363 } else {
1364 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_PROTECT_POS,bPosProt));
1366 if (bSizProtDontCare) {
1367 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_PROTECT_SIZE);
1368 } else {
1369 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_PROTECT_SIZE,bSizProt));
1372 SfxItemState eState=aMarkAttr.GetItemState(SDRATTR_TEXT_AUTOGROWWIDTH);
1373 bool bAutoGrow=((SdrTextAutoGrowWidthItem&)(aMarkAttr.Get(SDRATTR_TEXT_AUTOGROWWIDTH))).GetValue();
1374 if (eState==SFX_ITEM_DONTCARE) {
1375 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_AUTOWIDTH);
1376 } else if (eState==SFX_ITEM_SET) {
1377 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_AUTOWIDTH,bAutoGrow));
1380 eState=aMarkAttr.GetItemState(SDRATTR_TEXT_AUTOGROWHEIGHT);
1381 bAutoGrow=((SdrTextAutoGrowHeightItem&)(aMarkAttr.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue();
1382 if (eState==SFX_ITEM_DONTCARE) {
1383 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_AUTOHEIGHT);
1384 } else if (eState==SFX_ITEM_SET) {
1385 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_AUTOHEIGHT,bAutoGrow));
1388 eState=aMarkAttr.GetItemState(SDRATTR_ECKENRADIUS);
1389 long nRadius=((SdrEckenradiusItem&)(aMarkAttr.Get(SDRATTR_ECKENRADIUS))).GetValue();
1390 if (eState==SFX_ITEM_DONTCARE) {
1391 aRetSet.InvalidateItem(SDRATTR_ECKENRADIUS);
1392 } else if (eState==SFX_ITEM_SET) {
1393 aRetSet.Put(SdrEckenradiusItem(nRadius));
1396 basegfx::B2DHomMatrix aTransformation;
1398 if(nMarkCount > 1)
1400 // multiple objects, range is collected in aRect
1401 aTransformation = basegfx::tools::createScaleTranslateB2DHomMatrix(
1402 aRect.Left(), aRect.Top(),
1403 aRect.getWidth(), aRect.getHeight());
1405 else
1407 // single object, get homogen transformation
1408 basegfx::B2DPolyPolygon aPolyPolygon;
1410 pObj->TRGetBaseGeometry(aTransformation, aPolyPolygon);
1413 if(aTransformation.isIdentity())
1415 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_MATRIX);
1417 else
1419 com::sun::star::geometry::AffineMatrix2D aAffineMatrix2D;
1420 Point aPageOffset(0, 0);
1422 if(GetSdrPageView())
1424 aPageOffset = GetSdrPageView()->GetPageOrigin();
1427 aAffineMatrix2D.m00 = aTransformation.get(0, 0);
1428 aAffineMatrix2D.m01 = aTransformation.get(0, 1);
1429 aAffineMatrix2D.m02 = aTransformation.get(0, 2) - aPageOffset.X();
1430 aAffineMatrix2D.m10 = aTransformation.get(1, 0);
1431 aAffineMatrix2D.m11 = aTransformation.get(1, 1);
1432 aAffineMatrix2D.m12 = aTransformation.get(1, 2) - aPageOffset.Y();
1434 aRetSet.Put(AffineMatrixItem(&aAffineMatrix2D));
1438 return aRetSet;
1441 Point ImpGetPoint(Rectangle aRect, RECT_POINT eRP)
1443 switch(eRP) {
1444 case RP_LT: return aRect.TopLeft();
1445 case RP_MT: return aRect.TopCenter();
1446 case RP_RT: return aRect.TopRight();
1447 case RP_LM: return aRect.LeftCenter();
1448 case RP_MM: return aRect.Center();
1449 case RP_RM: return aRect.RightCenter();
1450 case RP_LB: return aRect.BottomLeft();
1451 case RP_MB: return aRect.BottomCenter();
1452 case RP_RB: return aRect.BottomRight();
1454 return Point(); // Should not happen!
1457 void SdrEditView::SetGeoAttrToMarked(const SfxItemSet& rAttr)
1459 Rectangle aRect(GetMarkedObjRect());
1461 if(GetSdrPageView())
1463 GetSdrPageView()->LogicToPagePos(aRect);
1466 long nOldRotateAngle=GetMarkedObjRotate();
1467 long nOldShearAngle=GetMarkedObjShear();
1468 const SdrMarkList& rMarkList=GetMarkedObjectList();
1469 sal_uIntPtr nMarkCount=rMarkList.GetMarkCount();
1470 SdrObject* pObj=NULL;
1472 RECT_POINT eSizePoint=RP_MM;
1473 long nPosDX=0;
1474 long nPosDY=0;
1475 long nSizX=0;
1476 long nSizY=0;
1477 long nRotateAngle=0;
1479 bool bModeIsRotate(eDragMode == SDRDRAG_ROTATE);
1480 long nRotateX(0);
1481 long nRotateY(0);
1482 long nOldRotateX(0);
1483 long nOldRotateY(0);
1484 if(bModeIsRotate)
1486 Point aRotateAxe(aRef1);
1488 if(GetSdrPageView())
1490 GetSdrPageView()->LogicToPagePos(aRotateAxe);
1493 nRotateX = nOldRotateX = aRotateAxe.X();
1494 nRotateY = nOldRotateY = aRotateAxe.Y();
1497 long nShearAngle=0;
1498 long nShearX=0;
1499 long nShearY=0;
1500 bool bShearVert=false;
1502 bool bChgPos=false;
1503 bool bChgSiz=false;
1504 bool bChgWdh=false;
1505 bool bChgHgt=false;
1506 bool bRotate=false;
1507 bool bShear =false;
1509 bool bSetAttr=false;
1510 SfxItemSet aSetAttr(pMod->GetItemPool());
1512 const SfxPoolItem* pPoolItem=NULL;
1514 // position
1515 if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_POS_X,true,&pPoolItem)) {
1516 nPosDX=((const SfxInt32Item*)pPoolItem)->GetValue()-aRect.Left();
1517 bChgPos=true;
1519 if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_POS_Y,true,&pPoolItem)){
1520 nPosDY=((const SfxInt32Item*)pPoolItem)->GetValue()-aRect.Top();
1521 bChgPos=true;
1523 // size
1524 if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_WIDTH,true,&pPoolItem)) {
1525 nSizX=((const SfxUInt32Item*)pPoolItem)->GetValue();
1526 bChgSiz=true;
1527 bChgWdh=true;
1529 if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_HEIGHT,true,&pPoolItem)) {
1530 nSizY=((const SfxUInt32Item*)pPoolItem)->GetValue();
1531 bChgSiz=true;
1532 bChgHgt=true;
1534 if (bChgSiz) {
1535 eSizePoint=(RECT_POINT)((const SfxAllEnumItem&)rAttr.Get(SID_ATTR_TRANSFORM_SIZE_POINT)).GetValue();
1538 // rotation
1539 if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ANGLE,true,&pPoolItem)) {
1540 nRotateAngle=((const SfxInt32Item*)pPoolItem)->GetValue()-nOldRotateAngle;
1541 bRotate = (nRotateAngle != 0);
1544 // position rotation point x
1545 if(bRotate || SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ROT_X, true ,&pPoolItem))
1546 nRotateX = ((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_ROT_X)).GetValue();
1548 // position rotation point y
1549 if(bRotate || SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ROT_Y, true ,&pPoolItem))
1550 nRotateY = ((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_ROT_Y)).GetValue();
1552 // shearing
1553 if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_SHEAR,true,&pPoolItem)) {
1554 long nNewShearAngle=((const SfxInt32Item*)pPoolItem)->GetValue();
1555 if (nNewShearAngle>SDRMAXSHEAR) nNewShearAngle=SDRMAXSHEAR;
1556 if (nNewShearAngle<-SDRMAXSHEAR) nNewShearAngle=-SDRMAXSHEAR;
1557 if (nNewShearAngle!=nOldShearAngle) {
1558 bShearVert=((const SfxBoolItem&)rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_VERTICAL)).GetValue();
1559 if (bShearVert) {
1560 nShearAngle=nNewShearAngle;
1561 } else {
1562 if (nNewShearAngle!=0 && nOldShearAngle!=0) {
1563 // bug fix
1564 double nOld=tan((double)nOldShearAngle*nPi180);
1565 double nNew=tan((double)nNewShearAngle*nPi180);
1566 nNew-=nOld;
1567 nNew=atan(nNew)/nPi180;
1568 nShearAngle=Round(nNew);
1569 } else {
1570 nShearAngle=nNewShearAngle-nOldShearAngle;
1573 bShear=nShearAngle!=0;
1574 if (bShear) {
1575 nShearX=((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_X)).GetValue();
1576 nShearY=((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_Y)).GetValue();
1581 // AutoGrow
1582 if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_AUTOWIDTH,true,&pPoolItem)) {
1583 bool bAutoGrow=((const SfxBoolItem*)pPoolItem)->GetValue();
1584 aSetAttr.Put(SdrTextAutoGrowWidthItem(bAutoGrow));
1585 bSetAttr=true;
1588 if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_AUTOHEIGHT,true,&pPoolItem)) {
1589 bool bAutoGrow=((const SfxBoolItem*)pPoolItem)->GetValue();
1590 aSetAttr.Put(SdrTextAutoGrowHeightItem(bAutoGrow));
1591 bSetAttr=true;
1594 // corner radius
1595 if (bEdgeRadiusAllowed && SFX_ITEM_SET==rAttr.GetItemState(SDRATTR_ECKENRADIUS,true,&pPoolItem)) {
1596 long nRadius=((SdrEckenradiusItem*)pPoolItem)->GetValue();
1597 aSetAttr.Put(SdrEckenradiusItem(nRadius));
1598 bSetAttr=true;
1601 ForcePossibilities();
1603 BegUndo(ImpGetResStr(STR_EditTransform),GetDescriptionOfMarkedObjects());
1605 if (bSetAttr) {
1606 SetAttrToMarked(aSetAttr,false);
1609 // change size and height
1610 if (bChgSiz && (bResizeFreeAllowed || bResizePropAllowed)) {
1611 Fraction aWdt(nSizX,aRect.Right()-aRect.Left());
1612 Fraction aHgt(nSizY,aRect.Bottom()-aRect.Top());
1613 Point aRef(ImpGetPoint(aRect,eSizePoint));
1615 if(GetSdrPageView())
1617 GetSdrPageView()->PagePosToLogic(aRef);
1620 ResizeMultMarkedObj(aRef, aWdt, aHgt, false, bChgWdh, bChgHgt);
1623 // rotate
1624 if (bRotate && (bRotateFreeAllowed || bRotate90Allowed)) {
1625 Point aRef(nRotateX,nRotateY);
1627 if(GetSdrPageView())
1629 GetSdrPageView()->PagePosToLogic(aRef);
1632 RotateMarkedObj(aRef,nRotateAngle);
1635 // set rotation point position
1636 if(bModeIsRotate && (nRotateX != nOldRotateX || nRotateY != nOldRotateY))
1638 Point aNewRef1(nRotateX, nRotateY);
1640 if(GetSdrPageView())
1642 GetSdrPageView()->PagePosToLogic(aNewRef1);
1645 SetRef1(aNewRef1);
1648 // shear
1649 if (bShear && bShearAllowed) {
1650 Point aRef(nShearX,nShearY);
1652 if(GetSdrPageView())
1654 GetSdrPageView()->PagePosToLogic(aRef);
1657 ShearMarkedObj(aRef,nShearAngle,bShearVert);
1659 // #i74358#
1660 // ShearMarkedObj creates a linear combination of the existing transformation and
1661 // the new shear to apply. If the object is already transformed (e.g. rotated) the
1662 // linear combination will not decompose to the same start values again, but to a
1663 // new combination. Thus it makes no sense to check if the wanted shear is reached
1664 // or not. Taking out.
1667 // change position
1668 if (bChgPos && bMoveAllowed) {
1669 MoveMarkedObj(Size(nPosDX,nPosDY));
1672 // protect position
1673 if(SFX_ITEM_SET == rAttr.GetItemState(SID_ATTR_TRANSFORM_PROTECT_POS, true, &pPoolItem))
1675 const bool bProtPos(((const SfxBoolItem*)pPoolItem)->GetValue());
1676 bool bChanged(false);
1678 for(sal_uInt32 i(0); i < nMarkCount; i++)
1680 pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
1682 if(pObj->IsMoveProtect() != bProtPos)
1684 bChanged = true;
1685 pObj->SetMoveProtect(bProtPos);
1687 if(bProtPos)
1689 pObj->SetResizeProtect(true);
1694 if(bChanged)
1696 bMoveProtect = bProtPos;
1698 if(bProtPos)
1700 bResizeProtect = true;
1703 // #i77187# there is no simple method to get the toolbars updated
1704 // in the application. The App is listening to selection change and i
1705 // will use it here (even if not true). It's acceptable since changing
1706 // this model data is pretty rare and only possible using the F4 dialog
1707 MarkListHasChanged();
1711 if(!bMoveProtect)
1713 // protect size
1714 if(SFX_ITEM_SET == rAttr.GetItemState(SID_ATTR_TRANSFORM_PROTECT_SIZE, true, &pPoolItem))
1716 const bool bProtSize(((const SfxBoolItem*)pPoolItem)->GetValue());
1717 bool bChanged(false);
1719 for(sal_uInt32 i(0); i < nMarkCount; i++)
1721 pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
1723 if(pObj->IsResizeProtect() != bProtSize)
1725 bChanged = true;
1726 pObj->SetResizeProtect(bProtSize);
1730 if(bChanged)
1732 bResizeProtect = bProtSize;
1734 // #i77187# see above
1735 MarkListHasChanged();
1740 EndUndo();
1745 bool SdrEditView::IsAlignPossible() const
1746 { // at least two selected objects, at least one of them movable
1747 ForcePossibilities();
1748 sal_uIntPtr nAnz=GetMarkedObjectCount();
1749 if (nAnz==0) return false; // nothing selected!
1750 if (nAnz==1) return bMoveAllowed; // align single object to page
1751 return bOneOrMoreMovable; // otherwise: MarkCount>=2
1754 void SdrEditView::AlignMarkedObjects(SdrHorAlign eHor, SdrVertAlign eVert, bool bBoundRects)
1756 if (eHor==SDRHALIGN_NONE && eVert==SDRVALIGN_NONE)
1757 return;
1759 SortMarkedObjects();
1760 if (GetMarkedObjectCount()<1)
1761 return;
1763 const bool bUndo = IsUndoEnabled();
1764 if( bUndo )
1766 OUString aStr(GetDescriptionOfMarkedObjects());
1767 if (eHor==SDRHALIGN_NONE)
1769 switch (eVert)
1771 case SDRVALIGN_TOP : ImpTakeDescriptionStr(STR_EditAlignVTop ,aStr); break;
1772 case SDRVALIGN_BOTTOM: ImpTakeDescriptionStr(STR_EditAlignVBottom,aStr); break;
1773 case SDRVALIGN_CENTER: ImpTakeDescriptionStr(STR_EditAlignVCenter,aStr); break;
1774 default: break;
1777 else if (eVert==SDRVALIGN_NONE)
1779 switch (eHor)
1781 case SDRHALIGN_LEFT : ImpTakeDescriptionStr(STR_EditAlignHLeft ,aStr); break;
1782 case SDRHALIGN_RIGHT : ImpTakeDescriptionStr(STR_EditAlignHRight ,aStr); break;
1783 case SDRHALIGN_CENTER: ImpTakeDescriptionStr(STR_EditAlignHCenter,aStr); break;
1784 default: break;
1787 else if (eHor==SDRHALIGN_CENTER && eVert==SDRVALIGN_CENTER)
1789 ImpTakeDescriptionStr(STR_EditAlignCenter,aStr);
1791 else
1793 ImpTakeDescriptionStr(STR_EditAlign,aStr);
1795 BegUndo(aStr);
1798 Rectangle aBound;
1799 sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
1800 sal_uIntPtr nm;
1801 bool bHasFixed=false;
1802 for (nm=0; nm<nMarkAnz; nm++)
1804 SdrMark* pM=GetSdrMarkByIndex(nm);
1805 SdrObject* pObj=pM->GetMarkedSdrObj();
1806 SdrObjTransformInfoRec aInfo;
1807 pObj->TakeObjInfo(aInfo);
1808 if (!aInfo.bMoveAllowed || pObj->IsMoveProtect())
1810 Rectangle aObjRect(bBoundRects?pObj->GetCurrentBoundRect():pObj->GetSnapRect());
1811 aBound.Union(aObjRect);
1812 bHasFixed=true;
1815 if (!bHasFixed)
1817 if (nMarkAnz==1)
1818 { // align single object to page
1819 const SdrObject* pObj=GetMarkedObjectByIndex(0L);
1820 const SdrPage* pPage=pObj->GetPage();
1821 const SdrPageGridFrameList* pGFL=pPage->GetGridFrameList(GetSdrPageViewOfMarkedByIndex(0),&(pObj->GetSnapRect()));
1822 const SdrPageGridFrame* pFrame=NULL;
1823 if (pGFL!=NULL && pGFL->GetCount()!=0)
1824 { // Writer
1825 pFrame=&((*pGFL)[0]);
1828 if (pFrame!=NULL)
1829 { // Writer
1830 aBound=pFrame->GetUserArea();
1832 else
1834 aBound=Rectangle(pPage->GetLftBorder(),pPage->GetUppBorder(),
1835 pPage->GetWdt()-pPage->GetRgtBorder(),
1836 pPage->GetHgt()-pPage->GetLwrBorder());
1839 else
1841 if (bBoundRects)
1842 aBound=GetMarkedObjBoundRect();
1843 else
1844 aBound=GetMarkedObjRect();
1847 Point aCenter(aBound.Center());
1848 for (nm=0; nm<nMarkAnz; nm++)
1850 SdrMark* pM=GetSdrMarkByIndex(nm);
1851 SdrObject* pObj=pM->GetMarkedSdrObj();
1852 SdrObjTransformInfoRec aInfo;
1853 pObj->TakeObjInfo(aInfo);
1854 if (aInfo.bMoveAllowed && !pObj->IsMoveProtect())
1856 long nXMov=0;
1857 long nYMov=0;
1858 Rectangle aObjRect(bBoundRects?pObj->GetCurrentBoundRect():pObj->GetSnapRect());
1859 switch (eVert)
1861 case SDRVALIGN_TOP : nYMov=aBound.Top() -aObjRect.Top() ; break;
1862 case SDRVALIGN_BOTTOM: nYMov=aBound.Bottom()-aObjRect.Bottom() ; break;
1863 case SDRVALIGN_CENTER: nYMov=aCenter.Y() -aObjRect.Center().Y(); break;
1864 default: break;
1866 switch (eHor)
1868 case SDRHALIGN_LEFT : nXMov=aBound.Left() -aObjRect.Left() ; break;
1869 case SDRHALIGN_RIGHT : nXMov=aBound.Right() -aObjRect.Right() ; break;
1870 case SDRHALIGN_CENTER: nXMov=aCenter.X() -aObjRect.Center().X(); break;
1871 default: break;
1873 if (nXMov!=0 || nYMov!=0)
1875 // SdrEdgeObj needs an extra SdrUndoGeoObj since the
1876 // connections may need to be saved
1877 if( bUndo )
1879 if( dynamic_cast<SdrEdgeObj*>(pObj) )
1881 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
1884 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pObj,Size(nXMov,nYMov)));
1887 pObj->Move(Size(nXMov,nYMov));
1892 if( bUndo )
1893 EndUndo();
1896 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */