bump product version to 5.0.4.1
[LibreOffice.git] / svx / source / svdraw / svdedtv1.cxx
blob8b5e0f35be47f7589f0cfa1dcd7fbfbeb3628981
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 "getallcharpropids.hxx"
32 #include "svdglob.hxx"
33 #include "svx/svditer.hxx"
34 #include "svx/svdstr.hrc"
36 #include <svx/AffineMatrixItem.hxx>
37 #include <svx/e3dsceneupdater.hxx>
38 #include <svx/obj3d.hxx>
39 #include <svx/rectenum.hxx>
40 #include <svx/sdr/contact/objectcontact.hxx>
41 #include <svx/sdr/contact/viewcontact.hxx>
42 #include <svx/svdattr.hxx>
43 #include <svx/svdedtv.hxx>
44 #include <svx/svdetc.hxx>
45 #include <svx/svdlayer.hxx>
46 #include <svx/svdopath.hxx>
47 #include <svx/svdpage.hxx>
48 #include <svx/svdpagv.hxx>
49 #include <svx/svdtrans.hxx>
50 #include <svx/svdundo.hxx>
51 #include <svx/svxids.hrc>
52 #include <sxallitm.hxx>
53 #include <sxmovitm.hxx>
54 #include <sxreaitm.hxx>
55 #include <sxreoitm.hxx>
56 #include <sxroaitm.hxx>
57 #include <sxrooitm.hxx>
58 #include <sxsalitm.hxx>
59 #include <sxsoitm.hxx>
60 #include <sxtraitm.hxx>
61 #include <svx/xlnedwit.hxx>
62 #include <svx/xlnstwit.hxx>
63 #include <svx/xlnwtit.hxx>
67 // EditView
71 void SdrEditView::SetMarkedObjRect(const Rectangle& rRect, bool bCopy)
73 DBG_ASSERT(!rRect.IsEmpty(),"SetMarkedObjRect() with an empty Rect does not make sense.");
74 if (rRect.IsEmpty()) return;
75 const size_t nCount=GetMarkedObjectCount();
76 if (nCount==0) return;
77 Rectangle aR0(GetMarkedObjRect());
78 DBG_ASSERT(!aR0.IsEmpty(),"SetMarkedObjRect(): GetMarkedObjRect() is empty.");
79 if (aR0.IsEmpty()) return;
80 long x0=aR0.Left();
81 long y0=aR0.Top();
82 long w0=aR0.Right()-x0;
83 long h0=aR0.Bottom()-y0;
84 long x1=rRect.Left();
85 long y1=rRect.Top();
86 long w1=rRect.Right()-x1;
87 long h1=rRect.Bottom()-y1;
88 OUString aStr;
89 ImpTakeDescriptionStr(STR_EditPosSize,aStr);
90 if (bCopy)
91 aStr+=ImpGetResStr(STR_EditWithCopy);
93 const bool bUndo = IsUndoEnabled();
94 if( bUndo )
95 BegUndo(aStr);
97 if (bCopy)
98 CopyMarkedObj();
100 for (size_t nm=0; nm<nCount; ++nm)
102 SdrMark* pM=GetSdrMarkByIndex(nm);
103 SdrObject* pO=pM->GetMarkedSdrObj();
104 if( bUndo )
105 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
107 Rectangle aR1(pO->GetSnapRect());
108 if (!aR1.IsEmpty())
110 if (aR1==aR0)
112 aR1=rRect;
114 else
115 { // transform aR1 to aR0 after rRect
116 aR1.Move(-x0,-y0);
117 BigInt l(aR1.Left());
118 BigInt r(aR1.Right());
119 BigInt t(aR1.Top());
120 BigInt b(aR1.Bottom());
121 if (w0!=0) {
122 l*=w1; l/=w0;
123 r*=w1; r/=w0;
124 } else {
125 l=0; r=w1;
127 if (h0!=0) {
128 t*=h1; t/=h0;
129 b*=h1; b/=h0;
130 } else {
131 t=0; b=h1;
133 aR1.Left ()=long(l);
134 aR1.Right ()=long(r);
135 aR1.Top ()=long(t);
136 aR1.Bottom()=long(b);
137 aR1.Move(x1,y1);
139 pO->SetSnapRect(aR1);
140 } else {
141 OSL_FAIL("SetMarkedObjRect(): pObj->GetSnapRect() returns empty Rect");
144 if( bUndo )
145 EndUndo();
148 std::vector< SdrUndoAction* > SdrEditView::CreateConnectorUndo( SdrObject& rO )
150 std::vector< SdrUndoAction* > vUndoActions;
152 if ( rO.GetBroadcaster() )
154 const SdrPage* pPage = rO.GetPage();
155 if ( pPage )
157 SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS );
158 while( aIter.IsMore() )
160 SdrObject* pPartObj = aIter.Next();
161 if ( pPartObj->ISA( SdrEdgeObj ) )
163 if ( ( pPartObj->GetConnectedNode( false ) == &rO ) ||
164 ( pPartObj->GetConnectedNode( true ) == &rO ) )
166 vUndoActions.push_back( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject( *pPartObj ) );
172 return vUndoActions;
175 void SdrEditView::AddUndoActions( std::vector< SdrUndoAction* >& rUndoActions )
177 std::vector< SdrUndoAction* >::iterator aUndoActionIter( rUndoActions.begin() );
178 while( aUndoActionIter != rUndoActions.end() )
179 AddUndo( *aUndoActionIter++ );
182 void SdrEditView::MoveMarkedObj(const Size& rSiz, bool bCopy)
184 const bool bUndo = IsUndoEnabled();
186 if( bUndo )
188 OUString aStr(ImpGetResStr(STR_EditMove));
189 if (bCopy)
190 aStr += ImpGetResStr(STR_EditWithCopy);
191 // meeds its own UndoGroup because of its parameters
192 BegUndo(aStr,GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVE);
195 if (bCopy)
196 CopyMarkedObj();
198 const size_t nMarkCount=GetMarkedObjectCount();
199 for (size_t nm=0; nm<nMarkCount; ++nm)
201 SdrMark* pM=GetSdrMarkByIndex(nm);
202 SdrObject* pO=pM->GetMarkedSdrObj();
203 if( bUndo )
205 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
206 AddUndoActions( vConnectorUndoActions );
207 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pO,rSiz));
209 pO->Move(rSiz);
212 if( bUndo )
213 EndUndo();
216 void SdrEditView::ResizeMarkedObj(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bCopy)
218 const bool bUndo = IsUndoEnabled();
219 if( bUndo )
221 OUString aStr;
222 ImpTakeDescriptionStr(STR_EditResize,aStr);
223 if (bCopy)
224 aStr+=ImpGetResStr(STR_EditWithCopy);
225 BegUndo(aStr);
228 if (bCopy)
229 CopyMarkedObj();
231 const size_t nMarkCount=GetMarkedObjectCount();
232 for (size_t nm=0; nm<nMarkCount; ++nm)
234 SdrMark* pM=GetSdrMarkByIndex(nm);
235 SdrObject* pO=pM->GetMarkedSdrObj();
236 if( bUndo )
238 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
239 AddUndoActions( vConnectorUndoActions );
240 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
242 pO->Resize(rRef,xFact,yFact);
245 if( bUndo )
246 EndUndo();
248 void SdrEditView::ResizeMultMarkedObj(const Point& rRef,
249 const Fraction& xFact,
250 const Fraction& yFact,
251 const bool bCopy,
252 const bool bWdh,
253 const bool bHgt)
255 const bool bUndo = IsUndoEnabled();
256 if( bUndo )
258 OUString aStr;
259 ImpTakeDescriptionStr(STR_EditResize,aStr);
260 if (bCopy)
261 aStr+=ImpGetResStr(STR_EditWithCopy);
262 BegUndo(aStr);
265 if (bCopy)
266 CopyMarkedObj();
268 const size_t nMarkCount=GetMarkedObjectCount();
269 for (size_t nm=0; nm<nMarkCount; ++nm)
271 SdrMark* pM=GetSdrMarkByIndex(nm);
272 SdrObject* pO=pM->GetMarkedSdrObj();
273 if( bUndo )
275 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
276 AddUndoActions( vConnectorUndoActions );
277 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
280 Fraction aFrac(1,1);
281 if (bWdh && bHgt)
282 pO->Resize(rRef, xFact, yFact);
283 else if (bWdh)
284 pO->Resize(rRef, xFact, aFrac);
285 else if (bHgt)
286 pO->Resize(rRef, aFrac, yFact);
288 if( bUndo )
289 EndUndo();
292 long SdrEditView::GetMarkedObjRotate() const
294 long nRetval(0);
296 if(GetMarkedObjectCount())
298 SdrMark* pM = GetSdrMarkByIndex(0);
299 SdrObject* pO = pM->GetMarkedSdrObj();
301 nRetval = pO->GetRotateAngle();
304 return nRetval;
305 //sal_Bool b1st=true;
306 //sal_Bool bOk=true;
307 //long nAngle=0;
308 //sal_uIntPtr nMarkCount=GetMarkedObjectCount();
309 //for (sal_uIntPtr nm=0; nm<nMarkCount && bOk; nm++) {
310 // SdrMark* pM=GetSdrMarkByIndex(nm);
311 // SdrObject* pO=pM->GetMarkedSdrObj();
312 // long nAngle2=pO->GetRotateAngle();
313 // if (b1st) nAngle=nAngle2;
314 // else if (nAngle2!=nAngle) bOk=false;
315 // b1st=false;
317 //if (!bOk) nAngle=0;
318 //return nAngle;
321 void SdrEditView::RotateMarkedObj(const Point& rRef, long nAngle, bool bCopy)
323 const bool bUndo = IsUndoEnabled();
324 if( bUndo )
326 OUString aStr;
327 ImpTakeDescriptionStr(STR_EditRotate,aStr);
328 if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy);
329 BegUndo(aStr);
332 if (bCopy)
333 CopyMarkedObj();
335 double nSin=sin(nAngle*nPi180);
336 double nCos=cos(nAngle*nPi180);
337 const size_t nMarkCount(GetMarkedObjectCount());
339 if(nMarkCount)
341 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
343 for(size_t nm = 0; nm < nMarkCount; ++nm)
345 SdrMark* pM = GetSdrMarkByIndex(nm);
346 SdrObject* pO = pM->GetMarkedSdrObj();
348 if( bUndo )
350 // extra undo actions for changed connector which now may hold its laid out path (SJ)
351 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
352 AddUndoActions( vConnectorUndoActions );
354 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
357 // set up a scene updater if object is a 3d object
358 if(dynamic_cast< E3dObject* >(pO))
360 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO));
363 pO->Rotate(rRef,nAngle,nSin,nCos);
366 // fire scene updaters
367 while(!aUpdaters.empty())
369 delete aUpdaters.back();
370 aUpdaters.pop_back();
374 if( bUndo )
375 EndUndo();
378 void SdrEditView::MirrorMarkedObj(const Point& rRef1, const Point& rRef2, bool bCopy)
380 const bool bUndo = IsUndoEnabled();
382 if( bUndo )
384 OUString aStr;
385 Point aDif(rRef2-rRef1);
386 if (aDif.X()==0) ImpTakeDescriptionStr(STR_EditMirrorHori,aStr);
387 else if (aDif.Y()==0) ImpTakeDescriptionStr(STR_EditMirrorVert,aStr);
388 else if (std::abs(aDif.X()) == std::abs(aDif.Y())) ImpTakeDescriptionStr(STR_EditMirrorDiag,aStr);
389 else ImpTakeDescriptionStr(STR_EditMirrorFree,aStr);
390 if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy);
391 BegUndo(aStr);
394 if (bCopy)
395 CopyMarkedObj();
397 const size_t nMarkCount(GetMarkedObjectCount());
399 if(nMarkCount)
401 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
403 for(size_t nm = 0; nm < nMarkCount; ++nm)
405 SdrMark* pM = GetSdrMarkByIndex(nm);
406 SdrObject* pO = pM->GetMarkedSdrObj();
408 if( bUndo )
410 // extra undo actions for changed connector which now may hold its laid out path (SJ)
411 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
412 AddUndoActions( vConnectorUndoActions );
414 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
417 // set up a scene updater if object is a 3d object
418 if(dynamic_cast< E3dObject* >(pO))
420 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO));
423 pO->Mirror(rRef1,rRef2);
426 // fire scene updaters
427 while(!aUpdaters.empty())
429 delete aUpdaters.back();
430 aUpdaters.pop_back();
434 if( bUndo )
435 EndUndo();
438 void SdrEditView::MirrorMarkedObjHorizontal(bool bCopy)
440 Point aCenter(GetMarkedObjRect().Center());
441 Point aPt2(aCenter);
442 aPt2.Y()++;
443 MirrorMarkedObj(aCenter,aPt2,bCopy);
446 void SdrEditView::MirrorMarkedObjVertical(bool bCopy)
448 Point aCenter(GetMarkedObjRect().Center());
449 Point aPt2(aCenter);
450 aPt2.X()++;
451 MirrorMarkedObj(aCenter,aPt2,bCopy);
454 long SdrEditView::GetMarkedObjShear() const
456 bool b1st=true;
457 bool bOk=true;
458 long nAngle=0;
459 const size_t nMarkCount=GetMarkedObjectCount();
460 for (size_t nm=0; nm<nMarkCount && bOk; ++nm) {
461 SdrMark* pM=GetSdrMarkByIndex(nm);
462 SdrObject* pO=pM->GetMarkedSdrObj();
463 long nAngle2=pO->GetShearAngle();
464 if (b1st) nAngle=nAngle2;
465 else if (nAngle2!=nAngle) bOk=false;
466 b1st=false;
468 if (nAngle>SDRMAXSHEAR) nAngle=SDRMAXSHEAR;
469 if (nAngle<-SDRMAXSHEAR) nAngle=-SDRMAXSHEAR;
470 if (!bOk) nAngle=0;
471 return nAngle;
474 void SdrEditView::ShearMarkedObj(const Point& rRef, long nAngle, bool bVShear, bool bCopy)
476 const bool bUndo = IsUndoEnabled();
478 if( bUndo )
480 OUString aStr;
481 ImpTakeDescriptionStr(STR_EditShear,aStr);
482 if (bCopy)
483 aStr+=ImpGetResStr(STR_EditWithCopy);
484 BegUndo(aStr);
487 if (bCopy)
488 CopyMarkedObj();
490 double nTan=tan(nAngle*nPi180);
491 const size_t nMarkCount=GetMarkedObjectCount();
492 for (size_t nm=0; nm<nMarkCount; ++nm)
494 SdrMark* pM=GetSdrMarkByIndex(nm);
495 SdrObject* pO=pM->GetMarkedSdrObj();
496 if( bUndo )
498 std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
499 AddUndoActions( vConnectorUndoActions );
500 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
502 pO->Shear(rRef,nAngle,nTan,bVShear);
505 if( bUndo )
506 EndUndo();
509 void SdrEditView::ImpCrookObj(SdrObject* pO, const Point& rRef, const Point& rRad,
510 SdrCrookMode eMode, bool bVertical, bool bNoContortion, bool bRotate, const Rectangle& rMarkRect)
512 SdrPathObj* pPath=PTR_CAST(SdrPathObj,pO);
513 bool bDone = false;
515 if(pPath!=NULL && !bNoContortion)
517 XPolyPolygon aXPP(pPath->GetPathPoly());
518 switch (eMode) {
519 case SDRCROOK_ROTATE : CrookRotatePoly (aXPP,rRef,rRad,bVertical); break;
520 case SDRCROOK_SLANT : CrookSlantPoly (aXPP,rRef,rRad,bVertical); break;
521 case SDRCROOK_STRETCH: CrookStretchPoly(aXPP,rRef,rRad,bVertical,rMarkRect); break;
522 } // switch
523 pPath->SetPathPoly(aXPP.getB2DPolyPolygon());
524 bDone = true;
527 if(!bDone && !pPath && pO->IsPolyObj() && 0L != pO->GetPointCount())
529 // for PolyObj's, but NOT for SdrPathObj's, e.g. the measurement object
530 sal_uInt32 nPointCount(pO->GetPointCount());
531 XPolygon aXP((sal_uInt16)nPointCount);
532 sal_uInt32 nPtNum;
534 for(nPtNum = 0L; nPtNum < nPointCount; nPtNum++)
536 Point aPt(pO->GetPoint(nPtNum));
537 aXP[(sal_uInt16)nPtNum]=aPt;
540 switch (eMode)
542 case SDRCROOK_ROTATE : CrookRotatePoly (aXP,rRef,rRad,bVertical); break;
543 case SDRCROOK_SLANT : CrookSlantPoly (aXP,rRef,rRad,bVertical); break;
544 case SDRCROOK_STRETCH: CrookStretchPoly(aXP,rRef,rRad,bVertical,rMarkRect); break;
547 for(nPtNum = 0L; nPtNum < nPointCount; nPtNum++)
549 // broadcasting could be optimized here, but for the
550 // current two points of the measurement object, it's fine
551 pO->SetPoint(aXP[(sal_uInt16)nPtNum],nPtNum);
554 bDone = true;
557 if(!bDone)
559 // for all others or if bNoContortion
560 Point aCtr0(pO->GetSnapRect().Center());
561 Point aCtr1(aCtr0);
562 bool bRotOk(false);
563 double nSin(0.0), nCos(1.0);
564 double nAngle(0.0);
566 if(0 != rRad.X() && 0 != rRad.Y())
568 bRotOk = bRotate;
570 switch (eMode)
572 case SDRCROOK_ROTATE : nAngle=CrookRotateXPoint (aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical); bRotOk=bRotate; break;
573 case SDRCROOK_SLANT : nAngle=CrookSlantXPoint (aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical); break;
574 case SDRCROOK_STRETCH: nAngle=CrookStretchXPoint(aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical,rMarkRect); break;
578 aCtr1 -= aCtr0;
580 if(bRotOk)
581 pO->Rotate(aCtr0, Round(nAngle/nPi180), nSin, nCos);
583 pO->Move(Size(aCtr1.X(),aCtr1.Y()));
587 void SdrEditView::CrookMarkedObj(const Point& rRef, const Point& rRad, SdrCrookMode eMode,
588 bool bVertical, bool bNoContortion, bool bCopy)
590 Rectangle aMarkRect(GetMarkedObjRect());
591 const bool bUndo = IsUndoEnabled();
593 bool bRotate=bNoContortion && eMode==SDRCROOK_ROTATE && IsRotateAllowed(false);
595 if( bUndo )
597 OUString aStr;
598 ImpTakeDescriptionStr(bNoContortion?STR_EditCrook:STR_EditCrookContortion,aStr);
599 if (bCopy)
600 aStr+=ImpGetResStr(STR_EditWithCopy);
601 BegUndo(aStr);
604 if (bCopy)
605 CopyMarkedObj();
607 const size_t nMarkCount=GetMarkedObjectCount();
608 for (size_t nm=0; nm<nMarkCount; ++nm)
610 SdrMark* pM=GetSdrMarkByIndex(nm);
611 SdrObject* pO=pM->GetMarkedSdrObj();
612 if( bUndo )
613 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
615 const SdrObjList* pOL=pO->GetSubList();
616 if (bNoContortion || pOL==NULL) {
617 ImpCrookObj(pO,rRef,rRad,eMode,bVertical,bNoContortion,bRotate,aMarkRect);
618 } else {
619 SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS);
620 while (aIter.IsMore()) {
621 SdrObject* pO1=aIter.Next();
622 ImpCrookObj(pO1,rRef,rRad,eMode,bVertical,bNoContortion,bRotate,aMarkRect);
627 if( bUndo )
628 EndUndo();
631 void SdrEditView::ImpDistortObj(SdrObject* pO, const Rectangle& rRef, const XPolygon& rDistortedRect, bool bNoContortion)
633 SdrPathObj* pPath = PTR_CAST(SdrPathObj, pO);
635 if(!bNoContortion && pPath)
637 XPolyPolygon aXPP(pPath->GetPathPoly());
638 aXPP.Distort(rRef, rDistortedRect);
639 pPath->SetPathPoly(aXPP.getB2DPolyPolygon());
641 else if(pO->IsPolyObj())
643 // e. g. for the measurement object
644 sal_uInt32 nPointCount(pO->GetPointCount());
645 XPolygon aXP((sal_uInt16)nPointCount);
646 sal_uInt32 nPtNum;
648 for(nPtNum = 0L; nPtNum < nPointCount; nPtNum++)
650 Point aPt(pO->GetPoint(nPtNum));
651 aXP[(sal_uInt16)nPtNum]=aPt;
654 aXP.Distort(rRef, rDistortedRect);
656 for(nPtNum = 0L; nPtNum < nPointCount; nPtNum++)
658 // broadcasting could be optimized here, but for the
659 // current two points of the measurement object it's fine
660 pO->SetPoint(aXP[(sal_uInt16)nPtNum],nPtNum);
665 void SdrEditView::DistortMarkedObj(const Rectangle& rRef, const XPolygon& rDistortedRect, bool bNoContortion, bool bCopy)
667 const bool bUndo = IsUndoEnabled();
669 if( bUndo )
671 OUString aStr;
672 ImpTakeDescriptionStr(STR_EditDistort,aStr);
673 if (bCopy)
674 aStr+=ImpGetResStr(STR_EditWithCopy);
675 BegUndo(aStr);
678 if (bCopy)
679 CopyMarkedObj();
681 const size_t nMarkCount=GetMarkedObjectCount();
682 for (size_t nm=0; nm<nMarkCount; ++nm)
684 SdrMark* pM=GetSdrMarkByIndex(nm);
685 SdrObject* pO=pM->GetMarkedSdrObj();
686 if( bUndo )
687 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
689 Rectangle aRefRect(rRef);
690 XPolygon aRefPoly(rDistortedRect);
691 const SdrObjList* pOL=pO->GetSubList();
692 if (bNoContortion || pOL==NULL) {
693 ImpDistortObj(pO,aRefRect,aRefPoly,bNoContortion);
694 } else {
695 SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS);
696 while (aIter.IsMore()) {
697 SdrObject* pO1=aIter.Next();
698 ImpDistortObj(pO1,aRefRect,aRefPoly,bNoContortion);
702 if( bUndo )
703 EndUndo();
708 void SdrEditView::SetNotPersistAttrToMarked(const SfxItemSet& rAttr, bool /*bReplaceAll*/)
710 // bReplaceAll has no effect here
711 Rectangle aAllSnapRect(GetMarkedObjRect());
712 const SfxPoolItem *pPoolItem=NULL;
713 if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1X,true,&pPoolItem)==SfxItemState::SET) {
714 long n=static_cast<const SdrTransformRef1XItem*>(pPoolItem)->GetValue();
715 SetRef1(Point(n,GetRef1().Y()));
717 if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1Y,true,&pPoolItem)==SfxItemState::SET) {
718 long n=static_cast<const SdrTransformRef1YItem*>(pPoolItem)->GetValue();
719 SetRef1(Point(GetRef1().X(),n));
721 if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2X,true,&pPoolItem)==SfxItemState::SET) {
722 long n=static_cast<const SdrTransformRef2XItem*>(pPoolItem)->GetValue();
723 SetRef2(Point(n,GetRef2().Y()));
725 if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2Y,true,&pPoolItem)==SfxItemState::SET) {
726 long n=static_cast<const SdrTransformRef2YItem*>(pPoolItem)->GetValue();
727 SetRef2(Point(GetRef2().X(),n));
729 long nAllPosX=0; bool bAllPosX=false;
730 long nAllPosY=0; bool bAllPosY=false;
731 long nAllWdt=0; bool bAllWdt=false;
732 long nAllHgt=0; bool bAllHgt=false;
733 bool bDoIt=false;
734 if (rAttr.GetItemState(SDRATTR_ALLPOSITIONX,true,&pPoolItem)==SfxItemState::SET) {
735 nAllPosX=static_cast<const SdrAllPositionXItem*>(pPoolItem)->GetValue();
736 bAllPosX=true; bDoIt=true;
738 if (rAttr.GetItemState(SDRATTR_ALLPOSITIONY,true,&pPoolItem)==SfxItemState::SET) {
739 nAllPosY=static_cast<const SdrAllPositionYItem*>(pPoolItem)->GetValue();
740 bAllPosY=true; bDoIt=true;
742 if (rAttr.GetItemState(SDRATTR_ALLSIZEWIDTH,true,&pPoolItem)==SfxItemState::SET) {
743 nAllWdt=static_cast<const SdrAllSizeWidthItem*>(pPoolItem)->GetValue();
744 bAllWdt=true; bDoIt=true;
746 if (rAttr.GetItemState(SDRATTR_ALLSIZEHEIGHT,true,&pPoolItem)==SfxItemState::SET) {
747 nAllHgt=static_cast<const SdrAllSizeHeightItem*>(pPoolItem)->GetValue();
748 bAllHgt=true; bDoIt=true;
750 if (bDoIt) {
751 Rectangle aRect(aAllSnapRect); // TODO: change this for PolyPt's and GluePt's!!!
752 if (bAllPosX) aRect.Move(nAllPosX-aRect.Left(),0);
753 if (bAllPosY) aRect.Move(0,nAllPosY-aRect.Top());
754 if (bAllWdt) aRect.Right()=aAllSnapRect.Left()+nAllWdt;
755 if (bAllHgt) aRect.Bottom()=aAllSnapRect.Top()+nAllHgt;
756 SetMarkedObjRect(aRect);
758 if (rAttr.GetItemState(SDRATTR_RESIZEXALL,true,&pPoolItem)==SfxItemState::SET) {
759 Fraction aXFact=static_cast<const SdrResizeXAllItem*>(pPoolItem)->GetValue();
760 ResizeMarkedObj(aAllSnapRect.TopLeft(),aXFact,Fraction(1,1));
762 if (rAttr.GetItemState(SDRATTR_RESIZEYALL,true,&pPoolItem)==SfxItemState::SET) {
763 Fraction aYFact=static_cast<const SdrResizeYAllItem*>(pPoolItem)->GetValue();
764 ResizeMarkedObj(aAllSnapRect.TopLeft(),Fraction(1,1),aYFact);
766 if (rAttr.GetItemState(SDRATTR_ROTATEALL,true,&pPoolItem)==SfxItemState::SET) {
767 long nAngle=static_cast<const SdrRotateAllItem*>(pPoolItem)->GetValue();
768 RotateMarkedObj(aAllSnapRect.Center(),nAngle);
770 if (rAttr.GetItemState(SDRATTR_HORZSHEARALL,true,&pPoolItem)==SfxItemState::SET) {
771 long nAngle=static_cast<const SdrHorzShearAllItem*>(pPoolItem)->GetValue();
772 ShearMarkedObj(aAllSnapRect.Center(),nAngle,false);
774 if (rAttr.GetItemState(SDRATTR_VERTSHEARALL,true,&pPoolItem)==SfxItemState::SET) {
775 long nAngle=static_cast<const SdrVertShearAllItem*>(pPoolItem)->GetValue();
776 ShearMarkedObj(aAllSnapRect.Center(),nAngle,true);
779 const bool bUndo = IsUndoEnabled();
781 // TODO: check if WhichRange is necessary.
782 const size_t nMarkCount=GetMarkedObjectCount();
783 for (size_t nm=0; nm<nMarkCount; ++nm)
785 const SdrMark* pM=GetSdrMarkByIndex(nm);
786 SdrObject* pObj=pM->GetMarkedSdrObj();
787 if( bUndo )
788 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
790 pObj->ApplyNotPersistAttr(rAttr);
794 void SdrEditView::MergeNotPersistAttrFromMarked(SfxItemSet& rAttr, bool /*bOnlyHardAttr*/) const
796 // bOnlyHardAttr has no effect here.
797 // TODO: Take into account the origin and PvPos.
798 Rectangle aAllSnapRect(GetMarkedObjRect()); // TODO: change this for PolyPt's and GluePt's!!!
799 long nAllSnapPosX=aAllSnapRect.Left();
800 long nAllSnapPosY=aAllSnapRect.Top();
801 long nAllSnapWdt=aAllSnapRect.GetWidth()-1;
802 long nAllSnapHgt=aAllSnapRect.GetHeight()-1;
803 // TODO: could go into CheckPossibilities
804 bool bMovProtect = false, bMovProtectDC = false;
805 bool bSizProtect = false, bSizProtectDC = false;
806 bool bPrintable = true, bPrintableDC = false;
807 bool bVisible = true, bVisibleDC = false;
808 SdrLayerID nLayerId=0; bool bLayerDC=false;
809 OUString aObjName;
810 bool bObjNameDC=false,bObjNameSet=false;
811 long nSnapPosX=0; bool bSnapPosXDC=false;
812 long nSnapPosY=0; bool bSnapPosYDC=false;
813 long nSnapWdt=0; bool bSnapWdtDC=false;
814 long nSnapHgt=0; bool bSnapHgtDC=false;
815 long nLogicWdt=0; bool bLogicWdtDC=false,bLogicWdtDiff=false;
816 long nLogicHgt=0; bool bLogicHgtDC=false,bLogicHgtDiff=false;
817 long nRotAngle=0; bool bRotAngleDC=false;
818 long nShrAngle=0; bool bShrAngleDC=false;
819 Rectangle aSnapRect;
820 Rectangle aLogicRect;
821 const size_t nMarkCount=GetMarkedObjectCount();
822 for (size_t nm=0; nm<nMarkCount; ++nm) {
823 const SdrMark* pM=GetSdrMarkByIndex(nm);
824 const SdrObject* pObj=pM->GetMarkedSdrObj();
825 if (nm==0) {
826 nLayerId=pObj->GetLayer();
827 bMovProtect=pObj->IsMoveProtect();
828 bSizProtect=pObj->IsResizeProtect();
829 bPrintable =pObj->IsPrintable();
830 bVisible = pObj->IsVisible();
831 Rectangle aSnapRect2(pObj->GetSnapRect());
832 Rectangle aLogicRect2(pObj->GetLogicRect());
833 nSnapPosX=aSnapRect2.Left();
834 nSnapPosY=aSnapRect2.Top();
835 nSnapWdt=aSnapRect2.GetWidth()-1;
836 nSnapHgt=aSnapRect2.GetHeight()-1;
837 nLogicWdt=aLogicRect2.GetWidth()-1;
838 nLogicHgt=aLogicRect2.GetHeight()-1;
839 bLogicWdtDiff=nLogicWdt!=nSnapWdt;
840 bLogicHgtDiff=nLogicHgt!=nSnapHgt;
841 nRotAngle=pObj->GetRotateAngle();
842 nShrAngle=pObj->GetShearAngle();
843 } else {
844 if (!bLayerDC && nLayerId !=pObj->GetLayer()) bLayerDC = true;
845 if (!bMovProtectDC && bMovProtect!=pObj->IsMoveProtect()) bMovProtectDC = true;
846 if (!bSizProtectDC && bSizProtect!=pObj->IsResizeProtect()) bSizProtectDC = true;
847 if (!bPrintableDC && bPrintable !=pObj->IsPrintable()) bPrintableDC = true;
848 if (!bVisibleDC && bVisible !=pObj->IsVisible()) bVisibleDC=true;
849 if (!bRotAngleDC && nRotAngle !=pObj->GetRotateAngle()) bRotAngleDC=true;
850 if (!bShrAngleDC && nShrAngle !=pObj->GetShearAngle()) bShrAngleDC=true;
851 if (!bSnapWdtDC || !bSnapHgtDC || !bSnapPosXDC || !bSnapPosYDC || !bLogicWdtDiff || !bLogicHgtDiff) {
852 aSnapRect=pObj->GetSnapRect();
853 if (nSnapPosX!=aSnapRect.Left()) bSnapPosXDC=true;
854 if (nSnapPosY!=aSnapRect.Top()) bSnapPosYDC=true;
855 if (nSnapWdt!=aSnapRect.GetWidth()-1) bSnapWdtDC=true;
856 if (nSnapHgt!=aSnapRect.GetHeight()-1) bSnapHgtDC=true;
858 if (!bLogicWdtDC || !bLogicHgtDC || !bLogicWdtDiff || !bLogicHgtDiff) {
859 aLogicRect=pObj->GetLogicRect();
860 if (nLogicWdt!=aLogicRect.GetWidth()-1) bLogicWdtDC=true;
861 if (nLogicHgt!=aLogicRect.GetHeight()-1) bLogicHgtDC=true;
862 if (!bLogicWdtDiff && aSnapRect.GetWidth()!=aLogicRect.GetWidth()) bLogicWdtDiff=true;
863 if (!bLogicHgtDiff && aSnapRect.GetHeight()!=aLogicRect.GetHeight()) bLogicHgtDiff=true;
866 if (!bObjNameDC ) {
867 if (!bObjNameSet) {
868 aObjName=pObj->GetName();
869 } else {
870 if (!aObjName.equals(pObj->GetName()))
871 bObjNameDC = true;
876 if (bSnapPosXDC || nAllSnapPosX!=nSnapPosX) rAttr.Put(SdrAllPositionXItem(nAllSnapPosX));
877 if (bSnapPosYDC || nAllSnapPosY!=nSnapPosY) rAttr.Put(SdrAllPositionYItem(nAllSnapPosY));
878 if (bSnapWdtDC || nAllSnapWdt !=nSnapWdt ) rAttr.Put(SdrAllSizeWidthItem(nAllSnapWdt));
879 if (bSnapHgtDC || nAllSnapHgt !=nSnapHgt ) rAttr.Put(SdrAllSizeHeightItem(nAllSnapHgt));
881 // items for pure transformations
882 rAttr.Put(SdrMoveXItem());
883 rAttr.Put(SdrMoveYItem());
884 rAttr.Put(SdrResizeXOneItem());
885 rAttr.Put(SdrResizeYOneItem());
886 rAttr.Put(SdrRotateOneItem());
887 rAttr.Put(SdrHorzShearOneItem());
888 rAttr.Put(SdrVertShearOneItem());
890 if (nMarkCount>1) {
891 rAttr.Put(SdrResizeXAllItem());
892 rAttr.Put(SdrResizeYAllItem());
893 rAttr.Put(SdrRotateAllItem());
894 rAttr.Put(SdrHorzShearAllItem());
895 rAttr.Put(SdrVertShearAllItem());
898 if(eDragMode == SDRDRAG_ROTATE || eDragMode == SDRDRAG_MIRROR)
900 rAttr.Put(SdrTransformRef1XItem(GetRef1().X()));
901 rAttr.Put(SdrTransformRef1YItem(GetRef1().Y()));
904 if(eDragMode == SDRDRAG_MIRROR)
906 rAttr.Put(SdrTransformRef2XItem(GetRef2().X()));
907 rAttr.Put(SdrTransformRef2YItem(GetRef2().Y()));
911 SfxItemSet SdrEditView::GetAttrFromMarked(bool bOnlyHardAttr) const
913 SfxItemSet aSet(pMod->GetItemPool());
914 MergeAttrFromMarked(aSet,bOnlyHardAttr);
915 //the EE_FEATURE items should not be set with SetAttrToMarked (see error message there)
916 //so we do not set them here
917 // #i32448#
918 // Do not disable, but clear the items.
919 aSet.ClearItem(EE_FEATURE_TAB);
920 aSet.ClearItem(EE_FEATURE_LINEBR);
921 aSet.ClearItem(EE_FEATURE_NOTCONV);
922 aSet.ClearItem(EE_FEATURE_FIELD);
923 return aSet;
926 void SdrEditView::MergeAttrFromMarked(SfxItemSet& rAttr, bool bOnlyHardAttr) const
928 const size_t nMarkCount(GetMarkedObjectCount());
930 for(size_t a = 0; a < nMarkCount; ++a)
932 // #80277# merging was done wrong in the prev version
933 const SfxItemSet& rSet = GetMarkedObjectByIndex(a)->GetMergedItemSet();
934 SfxWhichIter aIter(rSet);
935 sal_uInt16 nWhich(aIter.FirstWhich());
937 while(nWhich)
939 if(!bOnlyHardAttr)
941 if(SfxItemState::DONTCARE == rSet.GetItemState(nWhich, false))
942 rAttr.InvalidateItem(nWhich);
943 else
944 rAttr.MergeValue(rSet.Get(nWhich), true);
946 else if(SfxItemState::SET == rSet.GetItemState(nWhich, false))
948 const SfxPoolItem& rItem = rSet.Get(nWhich);
949 rAttr.MergeValue(rItem, true);
952 nWhich = aIter.NextWhich();
957 std::vector<sal_uInt16> GetAllCharPropIds(const SfxItemSet& rSet)
959 std::vector<sal_uInt16> aCharWhichIds;
961 SfxItemIter aIter(rSet);
962 const SfxPoolItem* pItem=aIter.FirstItem();
963 while (pItem!=NULL)
965 if (!IsInvalidItem(pItem))
967 sal_uInt16 nWhich = pItem->Which();
968 if (nWhich>=EE_CHAR_START && nWhich<=EE_CHAR_END)
969 aCharWhichIds.push_back( nWhich );
971 pItem=aIter.NextItem();
974 return aCharWhichIds;
977 void SdrEditView::SetAttrToMarked(const SfxItemSet& rAttr, bool bReplaceAll)
979 if (AreObjectsMarked())
981 #ifdef DBG_UTIL
983 bool bHasEEFeatureItems=false;
984 SfxItemIter aIter(rAttr);
985 const SfxPoolItem* pItem=aIter.FirstItem();
986 while (!bHasEEFeatureItems && pItem!=NULL) {
987 if (!IsInvalidItem(pItem)) {
988 sal_uInt16 nW=pItem->Which();
989 if (nW>=EE_FEATURE_START && nW<=EE_FEATURE_END) bHasEEFeatureItems=true;
991 pItem=aIter.NextItem();
993 if(bHasEEFeatureItems)
995 OUString aMessage("SdrEditView::SetAttrToMarked(): Setting EE_FEATURE items at the SdrView does not make sense! It only leads to overhead and unreadable documents.");
996 ScopedVclPtr<InfoBox>::Create(nullptr, aMessage)->Execute();
999 #endif
1001 // #103836# if the user sets character attributes to the complete shape,
1002 // we want to remove all hard set character attributes with same
1003 // which ids from the text. We do that later but here we remember
1004 // all character attribute which id's that are set.
1005 std::vector<sal_uInt16> aCharWhichIds(GetAllCharPropIds(rAttr));
1007 // To make Undo reconstruct text attributes correctly after Format.Standard
1008 bool bHasEEItems=SearchOutlinerItems(rAttr,bReplaceAll);
1010 // save additional geometry information when paragraph or character attributes
1011 // are changed and the geometrical shape of the text object might be changed
1012 bool bPossibleGeomChange(false);
1013 SfxWhichIter aIter(rAttr);
1014 sal_uInt16 nWhich = aIter.FirstWhich();
1015 while(!bPossibleGeomChange && nWhich)
1017 SfxItemState eState = rAttr.GetItemState(nWhich);
1018 if(eState == SfxItemState::SET)
1020 if((nWhich >= SDRATTR_TEXT_MINFRAMEHEIGHT && nWhich <= SDRATTR_TEXT_CONTOURFRAME)
1021 || nWhich == SDRATTR_3DOBJ_PERCENT_DIAGONAL
1022 || nWhich == SDRATTR_3DOBJ_BACKSCALE
1023 || nWhich == SDRATTR_3DOBJ_DEPTH
1024 || nWhich == SDRATTR_3DOBJ_END_ANGLE
1025 || nWhich == SDRATTR_3DSCENE_DISTANCE)
1027 bPossibleGeomChange = true;
1030 nWhich = aIter.NextWhich();
1033 const bool bUndo = IsUndoEnabled();
1034 if( bUndo )
1036 OUString aStr;
1037 ImpTakeDescriptionStr(STR_EditSetAttributes,aStr);
1038 BegUndo(aStr);
1041 const size_t nMarkCount(GetMarkedObjectCount());
1042 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
1044 // create ItemSet without SfxItemState::DONTCARE. Put()
1045 // uses its second parameter (bInvalidAsDefault) to
1046 // remove all such items to set them to default.
1047 SfxItemSet aAttr(*rAttr.GetPool(), rAttr.GetRanges());
1048 aAttr.Put(rAttr, true);
1050 // #i38135#
1051 bool bResetAnimationTimer(false);
1053 // check if LineWidth is part of the change
1054 const bool bLineWidthChange(SfxItemState::SET == aAttr.GetItemState(XATTR_LINEWIDTH));
1055 sal_Int32 nNewLineWidth(0);
1056 sal_Int32 nOldLineWidth(0);
1058 if(bLineWidthChange)
1060 nNewLineWidth = static_cast<const XLineWidthItem&>(aAttr.Get(XATTR_LINEWIDTH)).GetValue();
1063 for (size_t nm=0; nm<nMarkCount; ++nm)
1065 SdrMark* pM=GetSdrMarkByIndex(nm);
1066 SdrObject* pObj = pM->GetMarkedSdrObj();
1068 if( bUndo )
1070 std::vector< SdrUndoAction* > vConnectorUndoActions;
1071 SdrEdgeObj* pEdgeObj = dynamic_cast< SdrEdgeObj* >( pObj );
1072 if ( pEdgeObj )
1073 bPossibleGeomChange = true;
1074 else if( bUndo )
1075 vConnectorUndoActions = CreateConnectorUndo( *pObj );
1077 AddUndoActions( vConnectorUndoActions );
1080 // new geometry undo
1081 if(bPossibleGeomChange && bUndo)
1083 // save position and size of object, too
1084 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
1087 if( bUndo )
1089 // #i8508#
1090 // If this is a text object also rescue the OutlinerParaObject since
1091 // applying attributes to the object may change text layout when
1092 // multiple portions exist with multiple formats. If a OutlinerParaObject
1093 // really exists and needs to be rescued is evaluated in the undo
1094 // implementation itself.
1095 const bool bRescueText = dynamic_cast< SdrTextObj* >(pObj) != 0;
1097 // add attribute undo
1098 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj,false,bHasEEItems || bPossibleGeomChange || bRescueText));
1101 // set up a scene updater if object is a 3d object
1102 if(dynamic_cast< E3dObject* >(pObj))
1104 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pObj));
1107 if(bLineWidthChange)
1109 nOldLineWidth = static_cast<const XLineWidthItem&>(pObj->GetMergedItem(XATTR_LINEWIDTH)).GetValue();
1112 // set attributes at object
1113 pObj->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
1115 if(bLineWidthChange)
1117 const SfxItemSet& rSet = pObj->GetMergedItemSet();
1119 if(nOldLineWidth != nNewLineWidth)
1121 if(SfxItemState::DONTCARE != rSet.GetItemState(XATTR_LINESTARTWIDTH))
1123 const sal_Int32 nValAct(static_cast<const XLineStartWidthItem&>(rSet.Get(XATTR_LINESTARTWIDTH)).GetValue());
1124 const sal_Int32 nValNewStart(std::max((sal_Int32)0, nValAct + (((nNewLineWidth - nOldLineWidth) * 15) / 10)));
1126 pObj->SetMergedItem(XLineStartWidthItem(nValNewStart));
1129 if(SfxItemState::DONTCARE != rSet.GetItemState(XATTR_LINEENDWIDTH))
1131 const sal_Int32 nValAct(static_cast<const XLineEndWidthItem&>(rSet.Get(XATTR_LINEENDWIDTH)).GetValue());
1132 const sal_Int32 nValNewEnd(std::max((sal_Int32)0, nValAct + (((nNewLineWidth - nOldLineWidth) * 15) / 10)));
1134 pObj->SetMergedItem(XLineEndWidthItem(nValNewEnd));
1139 if(pObj->ISA(SdrTextObj))
1141 SdrTextObj* pTextObj = static_cast<SdrTextObj*>(pObj);
1143 if(!aCharWhichIds.empty())
1145 Rectangle aOldBoundRect = pTextObj->GetLastBoundRect();
1147 // #110094#-14 pTextObj->SendRepaintBroadcast(pTextObj->GetBoundRect());
1148 pTextObj->RemoveOutlinerCharacterAttribs( aCharWhichIds );
1150 // object has changed, should be called from
1151 // RemoveOutlinerCharacterAttribs. This will change when the text
1152 // object implementation changes.
1153 pTextObj->SetChanged();
1155 pTextObj->BroadcastObjectChange();
1156 pTextObj->SendUserCall(SDRUSERCALL_CHGATTR, aOldBoundRect);
1160 // #i38495#
1161 if(!bResetAnimationTimer)
1163 if(pObj->GetViewContact().isAnimatedInAnyViewObjectContact())
1165 bResetAnimationTimer = true;
1170 // fire scene updaters
1171 while(!aUpdaters.empty())
1173 delete aUpdaters.back();
1174 aUpdaters.pop_back();
1177 // #i38135#
1178 if(bResetAnimationTimer)
1180 SetAnimationTimer(0L);
1183 // better check before what to do:
1184 // pObj->SetAttr() or SetNotPersistAttr()
1185 // TODO: missing implementation!
1186 SetNotPersistAttrToMarked(rAttr,bReplaceAll);
1188 if( bUndo )
1189 EndUndo();
1193 SfxStyleSheet* SdrEditView::GetStyleSheetFromMarked() const
1195 SfxStyleSheet* pRet=NULL;
1196 bool b1st=true;
1197 const size_t nMarkCount=GetMarkedObjectCount();
1198 for (size_t nm=0; nm<nMarkCount; ++nm) {
1199 SdrMark* pM=GetSdrMarkByIndex(nm);
1200 SfxStyleSheet* pSS=pM->GetMarkedSdrObj()->GetStyleSheet();
1201 if (b1st) pRet=pSS;
1202 else if (pRet!=pSS) return NULL; // different stylesheets
1203 b1st=false;
1205 return pRet;
1208 void SdrEditView::SetStyleSheetToMarked(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
1210 if (AreObjectsMarked())
1212 const bool bUndo = IsUndoEnabled();
1214 if( bUndo )
1216 OUString aStr;
1217 if (pStyleSheet!=NULL)
1218 ImpTakeDescriptionStr(STR_EditSetStylesheet,aStr);
1219 else
1220 ImpTakeDescriptionStr(STR_EditDelStylesheet,aStr);
1221 BegUndo(aStr);
1224 const size_t nMarkCount=GetMarkedObjectCount();
1225 for (size_t nm=0; nm<nMarkCount; ++nm)
1227 SdrMark* pM=GetSdrMarkByIndex(nm);
1228 if( bUndo )
1230 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pM->GetMarkedSdrObj()));
1231 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pM->GetMarkedSdrObj(),true,true));
1233 pM->GetMarkedSdrObj()->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1236 if( bUndo )
1237 EndUndo();
1243 bool SdrEditView::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
1245 if(GetMarkedObjectCount())
1247 rTargetSet.Put(GetAttrFromMarked(bOnlyHardAttr), false);
1248 return true;
1250 else
1252 return SdrMarkView::GetAttributes(rTargetSet, bOnlyHardAttr);
1256 bool SdrEditView::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
1258 if (GetMarkedObjectCount()!=0) {
1259 SetAttrToMarked(rSet,bReplaceAll);
1260 return true;
1261 } else {
1262 return SdrMarkView::SetAttributes(rSet,bReplaceAll);
1266 SfxStyleSheet* SdrEditView::GetStyleSheet() const
1268 if (GetMarkedObjectCount()!=0) {
1269 return GetStyleSheetFromMarked();
1270 } else {
1271 return SdrMarkView::GetStyleSheet();
1275 bool SdrEditView::SetStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
1277 if (GetMarkedObjectCount()!=0) {
1278 SetStyleSheetToMarked(pStyleSheet,bDontRemoveHardAttr);
1279 return true;
1280 } else {
1281 return SdrMarkView::SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1287 SfxItemSet SdrEditView::GetGeoAttrFromMarked() const
1289 SfxItemSet aRetSet(pMod->GetItemPool(), // SID_ATTR_TRANSFORM_... from s:svxids.hrc
1290 SID_ATTR_TRANSFORM_POS_X, SID_ATTR_TRANSFORM_ANGLE,
1291 SID_ATTR_TRANSFORM_PROTECT_POS, SID_ATTR_TRANSFORM_AUTOHEIGHT,
1292 SDRATTR_ECKENRADIUS, SDRATTR_ECKENRADIUS,
1295 if (AreObjectsMarked())
1297 SfxItemSet aMarkAttr(GetAttrFromMarked(false)); // because of AutoGrowHeight and corner radius
1298 Rectangle aRect(GetMarkedObjRect());
1299 // restore position to that before calc hack
1300 aRect -= GetGridOffset();
1302 if(GetSdrPageView())
1304 GetSdrPageView()->LogicToPagePos(aRect);
1307 // position
1308 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_X,aRect.Left()));
1309 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_Y,aRect.Top()));
1311 // size
1312 long nResizeRefX=aRect.Left();
1313 long nResizeRefY=aRect.Top();
1314 if (eDragMode==SDRDRAG_ROTATE) { // use rotation axis as a reference for resizing, too
1315 nResizeRefX=aRef1.X();
1316 nResizeRefY=aRef1.Y();
1318 aRetSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_WIDTH,aRect.Right()-aRect.Left()));
1319 aRetSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_HEIGHT,aRect.Bottom()-aRect.Top()));
1320 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_RESIZE_REF_X,nResizeRefX));
1321 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_RESIZE_REF_Y,nResizeRefY));
1323 Point aRotateAxe(aRef1);
1325 if(GetSdrPageView())
1327 GetSdrPageView()->LogicToPagePos(aRotateAxe);
1330 // rotation
1331 long nRotateRefX=aRect.Center().X();
1332 long nRotateRefY=aRect.Center().Y();
1333 if (eDragMode==SDRDRAG_ROTATE) {
1334 nRotateRefX=aRotateAxe.X();
1335 nRotateRefY=aRotateAxe.Y();
1337 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ANGLE,GetMarkedObjRotate()));
1338 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_X,nRotateRefX));
1339 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_Y,nRotateRefY));
1341 // shearing
1342 long nShearRefX=aRect.Left();
1343 long nShearRefY=aRect.Bottom();
1344 if (eDragMode==SDRDRAG_ROTATE) { // use rotation axis as a reference for shearing, too
1345 nShearRefX=aRotateAxe.X();
1346 nShearRefY=aRotateAxe.Y();
1348 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR,GetMarkedObjShear()));
1349 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_X,nShearRefX));
1350 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_Y,nShearRefY));
1352 // check every object whether it is protected
1353 const SdrMarkList& rMarkList=GetMarkedObjectList();
1354 const size_t nMarkCount=rMarkList.GetMarkCount();
1355 SdrObject* pObj=rMarkList.GetMark(0)->GetMarkedSdrObj();
1356 bool bPosProt=pObj->IsMoveProtect();
1357 bool bSizProt=pObj->IsResizeProtect();
1358 bool bPosProtDontCare=false;
1359 bool bSizProtDontCare=false;
1360 for (size_t i=1; i<nMarkCount && (!bPosProtDontCare || !bSizProtDontCare); ++i)
1362 pObj=rMarkList.GetMark(i)->GetMarkedSdrObj();
1363 if (bPosProt!=pObj->IsMoveProtect()) bPosProtDontCare=true;
1364 if (bSizProt!=pObj->IsResizeProtect()) bSizProtDontCare=true;
1367 // InvalidateItem sets item to DONT_CARE
1368 if (bPosProtDontCare) {
1369 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_PROTECT_POS);
1370 } else {
1371 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_PROTECT_POS,bPosProt));
1373 if (bSizProtDontCare) {
1374 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_PROTECT_SIZE);
1375 } else {
1376 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_PROTECT_SIZE,bSizProt));
1379 SfxItemState eState=aMarkAttr.GetItemState(SDRATTR_TEXT_AUTOGROWWIDTH);
1380 bool bAutoGrow=static_cast<const SdrOnOffItem&>(aMarkAttr.Get(SDRATTR_TEXT_AUTOGROWWIDTH)).GetValue();
1381 if (eState==SfxItemState::DONTCARE) {
1382 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_AUTOWIDTH);
1383 } else if (eState==SfxItemState::SET) {
1384 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_AUTOWIDTH,bAutoGrow));
1387 eState=aMarkAttr.GetItemState(SDRATTR_TEXT_AUTOGROWHEIGHT);
1388 bAutoGrow=static_cast<const SdrOnOffItem&>(aMarkAttr.Get(SDRATTR_TEXT_AUTOGROWHEIGHT)).GetValue();
1389 if (eState==SfxItemState::DONTCARE) {
1390 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_AUTOHEIGHT);
1391 } else if (eState==SfxItemState::SET) {
1392 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_AUTOHEIGHT,bAutoGrow));
1395 eState=aMarkAttr.GetItemState(SDRATTR_ECKENRADIUS);
1396 long nRadius=static_cast<const SdrMetricItem&>(aMarkAttr.Get(SDRATTR_ECKENRADIUS)).GetValue();
1397 if (eState==SfxItemState::DONTCARE) {
1398 aRetSet.InvalidateItem(SDRATTR_ECKENRADIUS);
1399 } else if (eState==SfxItemState::SET) {
1400 aRetSet.Put(makeSdrEckenradiusItem(nRadius));
1403 basegfx::B2DHomMatrix aTransformation;
1405 if(nMarkCount > 1)
1407 // multiple objects, range is collected in aRect
1408 aTransformation = basegfx::tools::createScaleTranslateB2DHomMatrix(
1409 aRect.Left(), aRect.Top(),
1410 aRect.getWidth(), aRect.getHeight());
1412 else
1414 // single object, get homogen transformation
1415 basegfx::B2DPolyPolygon aPolyPolygon;
1417 pObj->TRGetBaseGeometry(aTransformation, aPolyPolygon);
1420 if(aTransformation.isIdentity())
1422 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_MATRIX);
1424 else
1426 com::sun::star::geometry::AffineMatrix2D aAffineMatrix2D;
1427 Point aPageOffset(0, 0);
1429 if(GetSdrPageView())
1431 aPageOffset = GetSdrPageView()->GetPageOrigin();
1434 aAffineMatrix2D.m00 = aTransformation.get(0, 0);
1435 aAffineMatrix2D.m01 = aTransformation.get(0, 1);
1436 aAffineMatrix2D.m02 = aTransformation.get(0, 2) - aPageOffset.X();
1437 aAffineMatrix2D.m10 = aTransformation.get(1, 0);
1438 aAffineMatrix2D.m11 = aTransformation.get(1, 1);
1439 aAffineMatrix2D.m12 = aTransformation.get(1, 2) - aPageOffset.Y();
1441 aRetSet.Put(AffineMatrixItem(&aAffineMatrix2D));
1445 return aRetSet;
1448 Point ImpGetPoint(const Rectangle& rRect, RECT_POINT eRP)
1450 switch(eRP) {
1451 case RP_LT: return rRect.TopLeft();
1452 case RP_MT: return rRect.TopCenter();
1453 case RP_RT: return rRect.TopRight();
1454 case RP_LM: return rRect.LeftCenter();
1455 case RP_MM: return rRect.Center();
1456 case RP_RM: return rRect.RightCenter();
1457 case RP_LB: return rRect.BottomLeft();
1458 case RP_MB: return rRect.BottomCenter();
1459 case RP_RB: return rRect.BottomRight();
1461 return Point(); // Should not happen!
1464 void SdrEditView::SetGeoAttrToMarked(const SfxItemSet& rAttr)
1466 Rectangle aRect(GetMarkedObjRect());
1468 if(GetSdrPageView())
1470 GetSdrPageView()->LogicToPagePos(aRect);
1473 long nOldRotateAngle=GetMarkedObjRotate();
1474 long nOldShearAngle=GetMarkedObjShear();
1475 const SdrMarkList& rMarkList=GetMarkedObjectList();
1476 const size_t nMarkCount=rMarkList.GetMarkCount();
1477 SdrObject* pObj=NULL;
1479 RECT_POINT eSizePoint=RP_MM;
1480 long nPosDX=0;
1481 long nPosDY=0;
1482 long nSizX=0;
1483 long nSizY=0;
1484 long nRotateAngle=0;
1486 bool bModeIsRotate(eDragMode == SDRDRAG_ROTATE);
1487 long nRotateX(0);
1488 long nRotateY(0);
1489 long nOldRotateX(0);
1490 long nOldRotateY(0);
1491 if(bModeIsRotate)
1493 Point aRotateAxe(aRef1);
1495 if(GetSdrPageView())
1497 GetSdrPageView()->LogicToPagePos(aRotateAxe);
1500 nRotateX = nOldRotateX = aRotateAxe.X();
1501 nRotateY = nOldRotateY = aRotateAxe.Y();
1504 long nShearAngle=0;
1505 long nShearX=0;
1506 long nShearY=0;
1507 bool bShearVert=false;
1509 bool bChgPos=false;
1510 bool bChgSiz=false;
1511 bool bChgWdh=false;
1512 bool bChgHgt=false;
1513 bool bRotate=false;
1514 bool bShear =false;
1516 bool bSetAttr=false;
1517 SfxItemSet aSetAttr(pMod->GetItemPool());
1519 const SfxPoolItem* pPoolItem=NULL;
1521 // position
1522 if (SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_POS_X,true,&pPoolItem)) {
1523 nPosDX=static_cast<const SfxInt32Item*>(pPoolItem)->GetValue()-aRect.Left();
1524 bChgPos=true;
1526 if (SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_POS_Y,true,&pPoolItem)){
1527 nPosDY=static_cast<const SfxInt32Item*>(pPoolItem)->GetValue()-aRect.Top();
1528 bChgPos=true;
1530 // size
1531 if (SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_WIDTH,true,&pPoolItem)) {
1532 nSizX=static_cast<const SfxUInt32Item*>(pPoolItem)->GetValue();
1533 bChgSiz=true;
1534 bChgWdh=true;
1536 if (SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_HEIGHT,true,&pPoolItem)) {
1537 nSizY=static_cast<const SfxUInt32Item*>(pPoolItem)->GetValue();
1538 bChgSiz=true;
1539 bChgHgt=true;
1541 if (bChgSiz) {
1542 eSizePoint=(RECT_POINT)static_cast<const SfxAllEnumItem&>(rAttr.Get(SID_ATTR_TRANSFORM_SIZE_POINT)).GetValue();
1545 // rotation
1546 if (SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ANGLE,true,&pPoolItem)) {
1547 nRotateAngle=static_cast<const SfxInt32Item*>(pPoolItem)->GetValue()-nOldRotateAngle;
1548 bRotate = (nRotateAngle != 0);
1551 // position rotation point x
1552 if(bRotate || SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ROT_X, true ,&pPoolItem))
1553 nRotateX = static_cast<const SfxInt32Item&>(rAttr.Get(SID_ATTR_TRANSFORM_ROT_X)).GetValue();
1555 // position rotation point y
1556 if(bRotate || SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ROT_Y, true ,&pPoolItem))
1557 nRotateY = static_cast<const SfxInt32Item&>(rAttr.Get(SID_ATTR_TRANSFORM_ROT_Y)).GetValue();
1559 // shearing
1560 if (SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_SHEAR,true,&pPoolItem)) {
1561 long nNewShearAngle=static_cast<const SfxInt32Item*>(pPoolItem)->GetValue();
1562 if (nNewShearAngle>SDRMAXSHEAR) nNewShearAngle=SDRMAXSHEAR;
1563 if (nNewShearAngle<-SDRMAXSHEAR) nNewShearAngle=-SDRMAXSHEAR;
1564 if (nNewShearAngle!=nOldShearAngle) {
1565 bShearVert=static_cast<const SfxBoolItem&>(rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_VERTICAL)).GetValue();
1566 if (bShearVert) {
1567 nShearAngle=nNewShearAngle;
1568 } else {
1569 if (nNewShearAngle!=0 && nOldShearAngle!=0) {
1570 // bug fix
1571 double nOld=tan((double)nOldShearAngle*nPi180);
1572 double nNew=tan((double)nNewShearAngle*nPi180);
1573 nNew-=nOld;
1574 nNew=atan(nNew)/nPi180;
1575 nShearAngle=Round(nNew);
1576 } else {
1577 nShearAngle=nNewShearAngle-nOldShearAngle;
1580 bShear=nShearAngle!=0;
1581 if (bShear) {
1582 nShearX=static_cast<const SfxInt32Item&>(rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_X)).GetValue();
1583 nShearY=static_cast<const SfxInt32Item&>(rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_Y)).GetValue();
1588 // AutoGrow
1589 if (SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_AUTOWIDTH,true,&pPoolItem)) {
1590 bool bAutoGrow=static_cast<const SfxBoolItem*>(pPoolItem)->GetValue();
1591 aSetAttr.Put(makeSdrTextAutoGrowWidthItem(bAutoGrow));
1592 bSetAttr=true;
1595 if (SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_AUTOHEIGHT,true,&pPoolItem)) {
1596 bool bAutoGrow=static_cast<const SfxBoolItem*>(pPoolItem)->GetValue();
1597 aSetAttr.Put(makeSdrTextAutoGrowHeightItem(bAutoGrow));
1598 bSetAttr=true;
1601 // corner radius
1602 if (bEdgeRadiusAllowed && SfxItemState::SET==rAttr.GetItemState(SDRATTR_ECKENRADIUS,true,&pPoolItem)) {
1603 long nRadius=static_cast<const SdrMetricItem*>(pPoolItem)->GetValue();
1604 aSetAttr.Put(makeSdrEckenradiusItem(nRadius));
1605 bSetAttr=true;
1608 ForcePossibilities();
1610 BegUndo(ImpGetResStr(STR_EditTransform),GetDescriptionOfMarkedObjects());
1612 if (bSetAttr) {
1613 SetAttrToMarked(aSetAttr,false);
1616 // change size and height
1617 if (bChgSiz && (bResizeFreeAllowed || bResizePropAllowed)) {
1618 Fraction aWdt(nSizX,aRect.Right()-aRect.Left());
1619 Fraction aHgt(nSizY,aRect.Bottom()-aRect.Top());
1620 Point aRef(ImpGetPoint(aRect,eSizePoint));
1622 if(GetSdrPageView())
1624 GetSdrPageView()->PagePosToLogic(aRef);
1627 ResizeMultMarkedObj(aRef, aWdt, aHgt, false, bChgWdh, bChgHgt);
1630 // rotate
1631 if (bRotate && (bRotateFreeAllowed || bRotate90Allowed)) {
1632 Point aRef(nRotateX,nRotateY);
1634 if(GetSdrPageView())
1636 GetSdrPageView()->PagePosToLogic(aRef);
1639 RotateMarkedObj(aRef,nRotateAngle);
1642 // set rotation point position
1643 if(bModeIsRotate && (nRotateX != nOldRotateX || nRotateY != nOldRotateY))
1645 Point aNewRef1(nRotateX, nRotateY);
1647 if(GetSdrPageView())
1649 GetSdrPageView()->PagePosToLogic(aNewRef1);
1652 SetRef1(aNewRef1);
1655 // shear
1656 if (bShear && bShearAllowed) {
1657 Point aRef(nShearX,nShearY);
1659 if(GetSdrPageView())
1661 GetSdrPageView()->PagePosToLogic(aRef);
1664 ShearMarkedObj(aRef,nShearAngle,bShearVert);
1666 // #i74358#
1667 // ShearMarkedObj creates a linear combination of the existing transformation and
1668 // the new shear to apply. If the object is already transformed (e.g. rotated) the
1669 // linear combination will not decompose to the same start values again, but to a
1670 // new combination. Thus it makes no sense to check if the wanted shear is reached
1671 // or not. Taking out.
1674 // change position
1675 if (bChgPos && bMoveAllowed) {
1676 MoveMarkedObj(Size(nPosDX,nPosDY));
1679 // protect position
1680 if(SfxItemState::SET == rAttr.GetItemState(SID_ATTR_TRANSFORM_PROTECT_POS, true, &pPoolItem))
1682 const bool bProtPos(static_cast<const SfxBoolItem*>(pPoolItem)->GetValue());
1683 bool bChanged(false);
1685 for(size_t i = 0; i < nMarkCount; ++i)
1687 pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
1689 if(pObj->IsMoveProtect() != bProtPos)
1691 bChanged = true;
1692 pObj->SetMoveProtect(bProtPos);
1694 if(bProtPos)
1696 pObj->SetResizeProtect(true);
1701 if(bChanged)
1703 bMoveProtect = bProtPos;
1705 if(bProtPos)
1707 bResizeProtect = true;
1710 // #i77187# there is no simple method to get the toolbars updated
1711 // in the application. The App is listening to selection change and i
1712 // will use it here (even if not true). It's acceptable since changing
1713 // this model data is pretty rare and only possible using the F4 dialog
1714 MarkListHasChanged();
1718 if(!bMoveProtect)
1720 // protect size
1721 if(SfxItemState::SET == rAttr.GetItemState(SID_ATTR_TRANSFORM_PROTECT_SIZE, true, &pPoolItem))
1723 const bool bProtSize(static_cast<const SfxBoolItem*>(pPoolItem)->GetValue());
1724 bool bChanged(false);
1726 for(size_t i = 0; i < nMarkCount; ++i)
1728 pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
1730 if(pObj->IsResizeProtect() != bProtSize)
1732 bChanged = true;
1733 pObj->SetResizeProtect(bProtSize);
1737 if(bChanged)
1739 bResizeProtect = bProtSize;
1741 // #i77187# see above
1742 MarkListHasChanged();
1747 EndUndo();
1752 bool SdrEditView::IsAlignPossible() const
1753 { // at least two selected objects, at least one of them movable
1754 ForcePossibilities();
1755 const size_t nCount=GetMarkedObjectCount();
1756 if (nCount==0) return false; // nothing selected!
1757 if (nCount==1) return bMoveAllowed; // align single object to page
1758 return bOneOrMoreMovable; // otherwise: MarkCount>=2
1761 void SdrEditView::AlignMarkedObjects(SdrHorAlign eHor, SdrVertAlign eVert, bool bBoundRects)
1763 if (eHor==SDRHALIGN_NONE && eVert==SDRVALIGN_NONE)
1764 return;
1766 SortMarkedObjects();
1767 if (!GetMarkedObjectCount())
1768 return;
1770 const bool bUndo = IsUndoEnabled();
1771 if( bUndo )
1773 OUString aStr(GetDescriptionOfMarkedObjects());
1774 if (eHor==SDRHALIGN_NONE)
1776 switch (eVert)
1778 case SDRVALIGN_TOP : ImpTakeDescriptionStr(STR_EditAlignVTop ,aStr); break;
1779 case SDRVALIGN_BOTTOM: ImpTakeDescriptionStr(STR_EditAlignVBottom,aStr); break;
1780 case SDRVALIGN_CENTER: ImpTakeDescriptionStr(STR_EditAlignVCenter,aStr); break;
1781 default: break;
1784 else if (eVert==SDRVALIGN_NONE)
1786 switch (eHor)
1788 case SDRHALIGN_LEFT : ImpTakeDescriptionStr(STR_EditAlignHLeft ,aStr); break;
1789 case SDRHALIGN_RIGHT : ImpTakeDescriptionStr(STR_EditAlignHRight ,aStr); break;
1790 case SDRHALIGN_CENTER: ImpTakeDescriptionStr(STR_EditAlignHCenter,aStr); break;
1791 default: break;
1794 else if (eHor==SDRHALIGN_CENTER && eVert==SDRVALIGN_CENTER)
1796 ImpTakeDescriptionStr(STR_EditAlignCenter,aStr);
1798 else
1800 ImpTakeDescriptionStr(STR_EditAlign,aStr);
1802 BegUndo(aStr);
1805 Rectangle aBound;
1806 const size_t nMarkCount=GetMarkedObjectCount();
1807 bool bHasFixed=false;
1808 for (size_t nm=0; nm<nMarkCount; ++nm)
1810 SdrMark* pM=GetSdrMarkByIndex(nm);
1811 SdrObject* pObj=pM->GetMarkedSdrObj();
1812 SdrObjTransformInfoRec aInfo;
1813 pObj->TakeObjInfo(aInfo);
1814 if (!aInfo.bMoveAllowed || pObj->IsMoveProtect())
1816 Rectangle aObjRect(bBoundRects?pObj->GetCurrentBoundRect():pObj->GetSnapRect());
1817 aBound.Union(aObjRect);
1818 bHasFixed=true;
1821 if (!bHasFixed)
1823 if (nMarkCount==1)
1824 { // align single object to page
1825 const SdrObject* pObj=GetMarkedObjectByIndex(0);
1826 const SdrPage* pPage=pObj->GetPage();
1827 const SdrPageGridFrameList* pGFL=pPage->GetGridFrameList(GetSdrPageViewOfMarkedByIndex(0),&(pObj->GetSnapRect()));
1828 const SdrPageGridFrame* pFrame=NULL;
1829 if (pGFL!=NULL && pGFL->GetCount()!=0)
1830 { // Writer
1831 pFrame=&((*pGFL)[0]);
1834 if (pFrame!=NULL)
1835 { // Writer
1836 aBound=pFrame->GetUserArea();
1838 else
1840 aBound=Rectangle(pPage->GetLftBorder(),pPage->GetUppBorder(),
1841 pPage->GetWdt()-pPage->GetRgtBorder(),
1842 pPage->GetHgt()-pPage->GetLwrBorder());
1845 else
1847 if (bBoundRects)
1848 aBound=GetMarkedObjBoundRect();
1849 else
1850 aBound=GetMarkedObjRect();
1853 Point aCenter(aBound.Center());
1854 for (size_t nm=0; nm<nMarkCount; ++nm)
1856 SdrMark* pM=GetSdrMarkByIndex(nm);
1857 SdrObject* pObj=pM->GetMarkedSdrObj();
1858 SdrObjTransformInfoRec aInfo;
1859 pObj->TakeObjInfo(aInfo);
1860 if (aInfo.bMoveAllowed && !pObj->IsMoveProtect())
1862 long nXMov=0;
1863 long nYMov=0;
1864 Rectangle aObjRect(bBoundRects?pObj->GetCurrentBoundRect():pObj->GetSnapRect());
1865 switch (eVert)
1867 case SDRVALIGN_TOP : nYMov=aBound.Top() -aObjRect.Top() ; break;
1868 case SDRVALIGN_BOTTOM: nYMov=aBound.Bottom()-aObjRect.Bottom() ; break;
1869 case SDRVALIGN_CENTER: nYMov=aCenter.Y() -aObjRect.Center().Y(); break;
1870 default: break;
1872 switch (eHor)
1874 case SDRHALIGN_LEFT : nXMov=aBound.Left() -aObjRect.Left() ; break;
1875 case SDRHALIGN_RIGHT : nXMov=aBound.Right() -aObjRect.Right() ; break;
1876 case SDRHALIGN_CENTER: nXMov=aCenter.X() -aObjRect.Center().X(); break;
1877 default: break;
1879 if (nXMov!=0 || nYMov!=0)
1881 // SdrEdgeObj needs an extra SdrUndoGeoObj since the
1882 // connections may need to be saved
1883 if( bUndo )
1885 if( dynamic_cast<SdrEdgeObj*>(pObj) )
1887 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
1890 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pObj,Size(nXMov,nYMov)));
1893 pObj->Move(Size(nXMov,nYMov));
1898 if( bUndo )
1899 EndUndo();
1902 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */