tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / svx / source / svdraw / svdedtv1.cxx
blob6a098d3568a061c909c05cf40deb85b535ec0710
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/eeitem.hxx>
23 #include <math.h>
24 #include <svl/itemiter.hxx>
25 #include <svl/whiter.hxx>
26 #include <tools/bigint.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/weld.hxx>
30 #include <getallcharpropids.hxx>
31 #include <svx/dialmgr.hxx>
32 #include <svx/svditer.hxx>
33 #include <svx/strings.hrc>
35 #include <AffineMatrixItem.hxx>
36 #include <svx/e3dsceneupdater.hxx>
37 #include <svx/rectenum.hxx>
38 #include <svx/sdr/contact/viewcontact.hxx>
39 #include <svx/sdooitm.hxx>
40 #include <svx/sderitm.hxx>
41 #include <svx/sdtagitm.hxx>
42 #include <svx/svdedtv.hxx>
43 #include <svx/svdetc.hxx>
44 #include <svx/svdopath.hxx>
45 #include <svx/svdpage.hxx>
46 #include <svx/svdpagv.hxx>
47 #include <svx/svdtrans.hxx>
48 #include <svx/svdundo.hxx>
49 #include <svx/svxids.hrc>
50 #include <sxallitm.hxx>
51 #include <sxmovitm.hxx>
52 #include <sxreaitm.hxx>
53 #include <sxreoitm.hxx>
54 #include <sxroaitm.hxx>
55 #include <sxrooitm.hxx>
56 #include <sxsalitm.hxx>
57 #include <sxsoitm.hxx>
58 #include <sxtraitm.hxx>
59 #include <svx/xlnedwit.hxx>
60 #include <svx/xlnstwit.hxx>
61 #include <svx/xlnwtit.hxx>
62 #include <svx/xlnclit.hxx>
63 #include <svx/xflclit.hxx>
64 #include <svx/xlntrit.hxx>
65 #include <svx/xfltrit.hxx>
66 #include <svx/sdprcitm.hxx>
67 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
68 #include <rtl/ustring.hxx>
69 #include <sfx2/viewsh.hxx>
70 #include <comphelper/lok.hxx>
71 #include <osl/diagnose.h>
73 // EditView
76 void SdrEditView::SetMarkedObjRect(const tools::Rectangle& rRect)
78 DBG_ASSERT(!rRect.IsEmpty(),"SetMarkedObjRect() with an empty Rect does not make sense.");
79 if (rRect.IsEmpty())
80 return;
81 const SdrMarkList& rMarkList = GetMarkedObjectList();
82 const size_t nCount=rMarkList.GetMarkCount();
83 if (nCount==0) return;
84 tools::Rectangle aR0(GetMarkedObjRect());
85 DBG_ASSERT(!aR0.IsEmpty(),"SetMarkedObjRect(): GetMarkedObjRect() is empty.");
86 if (aR0.IsEmpty()) return;
87 tools::Long x0=aR0.Left();
88 tools::Long y0=aR0.Top();
89 tools::Long w0=aR0.Right()-x0;
90 tools::Long h0=aR0.Bottom()-y0;
91 tools::Long x1=rRect.Left();
92 tools::Long y1=rRect.Top();
93 tools::Long w1=rRect.Right()-x1;
94 tools::Long h1=rRect.Bottom()-y1;
96 const bool bUndo = IsUndoEnabled();
97 if( bUndo )
99 EndTextEditCurrentView();
100 BegUndo(ImpGetDescriptionString(STR_EditPosSize));
103 for (size_t nm=0; nm<nCount; ++nm)
105 SdrMark* pM=rMarkList.GetMark(nm);
106 SdrObject* pO=pM->GetMarkedSdrObj();
107 if (bUndo)
108 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pO));
110 tools::Rectangle aR1(pO->GetSnapRect());
111 if (!aR1.IsEmpty())
113 if (aR1==aR0)
115 aR1=rRect;
117 else
118 { // transform aR1 to aR0 after rRect
119 aR1.Move(-x0,-y0);
120 BigInt l(aR1.Left());
121 BigInt r(aR1.Right());
122 BigInt t(aR1.Top());
123 BigInt b(aR1.Bottom());
124 if (w0!=0) {
125 l*=w1; l/=w0;
126 r*=w1; r/=w0;
127 } else {
128 l=0; r=w1;
130 if (h0!=0) {
131 t*=h1; t/=h0;
132 b*=h1; b/=h0;
133 } else {
134 t=0; b=h1;
136 aR1.SetLeft(tools::Long(l) );
137 aR1.SetRight(tools::Long(r) );
138 aR1.SetTop(tools::Long(t) );
139 aR1.SetBottom(tools::Long(b) );
140 aR1.Move(x1,y1);
142 pO->SetSnapRect(aR1);
143 } else {
144 OSL_FAIL("SetMarkedObjRect(): pObj->GetSnapRect() returns empty Rect");
147 if( bUndo )
148 EndUndo();
151 std::vector< std::unique_ptr<SdrUndoAction> > SdrEditView::CreateConnectorUndo( const SdrObject& rO )
153 std::vector< std::unique_ptr<SdrUndoAction> > vUndoActions;
155 if ( rO.GetBroadcaster() )
157 const SdrPage* pPage = rO.getSdrPageFromSdrObject();
158 if ( pPage )
160 SdrObjListIter aIter(pPage, SdrIterMode::DeepWithGroups);
161 while( aIter.IsMore() )
163 SdrObject* pPartObj = aIter.Next();
164 if ( dynamic_cast<const SdrEdgeObj*>( pPartObj) != nullptr )
166 if ( ( pPartObj->GetConnectedNode( false ) == &rO ) ||
167 ( pPartObj->GetConnectedNode( true ) == &rO ) )
169 vUndoActions.push_back(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pPartObj));
175 return vUndoActions;
178 void SdrEditView::AddUndoActions( std::vector< std::unique_ptr<SdrUndoAction> > aUndoActions )
180 for (auto & rAction : aUndoActions)
181 AddUndo( std::move(rAction) );
184 void SdrEditView::MoveMarkedObj(const Size& rSiz, bool bCopy)
186 const bool bUndo = IsUndoEnabled();
187 const SdrMarkList& rMarkList = GetMarkedObjectList();
189 if( bUndo )
191 EndTextEditCurrentView();
192 OUString aStr(SvxResId(STR_EditMove));
193 if (bCopy)
194 aStr += SvxResId(STR_EditWithCopy);
195 // needs its own UndoGroup because of its parameters
196 BegUndo(aStr,rMarkList.GetMarkDescription(),SdrRepeatFunc::Move);
199 if (bCopy)
200 CopyMarkedObj();
202 const size_t nMarkCount=rMarkList.GetMarkCount();
203 for (size_t nm=0; nm<nMarkCount; ++nm)
205 SdrMark* pM=rMarkList.GetMark(nm);
206 SdrObject* pO=pM->GetMarkedSdrObj();
207 if( bUndo )
209 AddUndoActions( CreateConnectorUndo( *pO ) );
210 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoMoveObject(*pO,rSiz));
212 pO->Move(rSiz);
215 if( bUndo )
216 EndUndo();
219 bool SdrEditView::IsMarkedObjSizeValid(Size& aTargetSize)
221 SdrMark* pM=GetMarkedObjectList().GetMark(0);
222 SdrObject* pO=pM->GetMarkedSdrObj();
223 if (!pO->IsSizeValid(aTargetSize))
224 return false;
225 return true;
228 void SdrEditView::ResizeMarkedObj(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bCopy)
230 const bool bUndo = IsUndoEnabled();
231 if( bUndo )
233 EndTextEditCurrentView();
234 OUString aStr {ImpGetDescriptionString(STR_EditResize)};
235 if (bCopy)
236 aStr+=SvxResId(STR_EditWithCopy);
237 BegUndo(aStr);
240 if (bCopy)
241 CopyMarkedObj();
243 const SdrMarkList& rMarkList = GetMarkedObjectList();
244 const size_t nMarkCount=rMarkList.GetMarkCount();
245 for (size_t nm=0; nm<nMarkCount; ++nm)
247 SdrMark* pM=rMarkList.GetMark(nm);
248 SdrObject* pO=pM->GetMarkedSdrObj();
249 if( bUndo )
251 AddUndoActions( CreateConnectorUndo( *pO ) );
252 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pO));
254 pO->Resize(rRef,xFact,yFact);
257 if( bUndo )
258 EndUndo();
260 void SdrEditView::ResizeMultMarkedObj(const Point& rRef,
261 const Fraction& xFact,
262 const Fraction& yFact,
263 const bool bWdh,
264 const bool bHgt)
266 const bool bUndo = IsUndoEnabled();
267 if( bUndo )
269 EndTextEditCurrentView();
270 BegUndo(ImpGetDescriptionString(STR_EditResize));
273 const SdrMarkList& rMarkList = GetMarkedObjectList();
274 const size_t nMarkCount=rMarkList.GetMarkCount();
275 for (size_t nm=0; nm<nMarkCount; ++nm)
277 SdrMark* pM=rMarkList.GetMark(nm);
278 SdrObject* pO=pM->GetMarkedSdrObj();
279 if( bUndo )
281 AddUndoActions( CreateConnectorUndo( *pO ) );
282 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pO));
285 Fraction aFrac(1,1);
286 if (bWdh && xFact.IsValid() && bHgt && yFact.IsValid())
287 pO->Resize(rRef, xFact, yFact);
288 else if (bWdh && xFact.IsValid())
289 pO->Resize(rRef, xFact, aFrac);
290 else if (bHgt && yFact.IsValid())
291 pO->Resize(rRef, aFrac, yFact);
293 if( bUndo )
294 EndUndo();
297 Degree100 SdrEditView::GetMarkedObjRotate() const
299 Degree100 nRetval(0);
301 const SdrMarkList& rMarkList = GetMarkedObjectList();
302 if(rMarkList.GetMarkCount())
304 SdrMark* pM = rMarkList.GetMark(0);
305 SdrObject* pO = pM->GetMarkedSdrObj();
307 nRetval = pO->GetRotateAngle();
310 return nRetval;
313 void SdrEditView::RotateMarkedObj(const Point& rRef, Degree100 nAngle, bool bCopy)
315 const bool bUndo = IsUndoEnabled();
316 if( bUndo )
318 EndTextEditCurrentView();
319 OUString aStr {ImpGetDescriptionString(STR_EditRotate)};
320 if (bCopy) aStr+=SvxResId(STR_EditWithCopy);
321 BegUndo(aStr);
324 if (bCopy)
325 CopyMarkedObj();
327 double nSin = sin(toRadians(nAngle));
328 double nCos = cos(toRadians(nAngle));
329 const SdrMarkList& rMarkList = GetMarkedObjectList();
330 const size_t nMarkCount(rMarkList.GetMarkCount());
332 if(nMarkCount)
334 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
336 for(size_t nm = 0; nm < nMarkCount; ++nm)
338 SdrMark* pM = rMarkList.GetMark(nm);
339 SdrObject* pO = pM->GetMarkedSdrObj();
341 if( bUndo )
343 // extra undo actions for changed connector which now may hold its laid out path (SJ)
344 AddUndoActions( CreateConnectorUndo( *pO ) );
346 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pO));
349 // set up a scene updater if object is a 3d object
350 if(DynCastE3dObject(pO))
352 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO));
355 pO->Rotate(rRef,nAngle,nSin,nCos);
358 // fire scene updaters
359 while(!aUpdaters.empty())
361 delete aUpdaters.back();
362 aUpdaters.pop_back();
366 if( bUndo )
367 EndUndo();
370 void SdrEditView::MirrorMarkedObj(const Point& rRef1, const Point& rRef2, bool bCopy)
372 const bool bUndo = IsUndoEnabled();
374 if( bUndo )
376 EndTextEditCurrentView();
377 OUString aStr;
378 Point aDif(rRef2-rRef1);
379 if (aDif.X()==0)
380 aStr = ImpGetDescriptionString(STR_EditMirrorHori);
381 else if (aDif.Y()==0)
382 aStr = ImpGetDescriptionString(STR_EditMirrorVert);
383 else if (std::abs(aDif.X()) == std::abs(aDif.Y()))
384 aStr = ImpGetDescriptionString(STR_EditMirrorDiag);
385 else
386 aStr = ImpGetDescriptionString(STR_EditMirrorFree);
387 if (bCopy) aStr+=SvxResId(STR_EditWithCopy);
388 BegUndo(aStr);
391 if (bCopy)
392 CopyMarkedObj();
394 const SdrMarkList& rMarkList = GetMarkedObjectList();
395 const size_t nMarkCount(rMarkList.GetMarkCount());
397 if(nMarkCount)
399 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
401 for(size_t nm = 0; nm < nMarkCount; ++nm)
403 SdrMark* pM = rMarkList.GetMark(nm);
404 SdrObject* pO = pM->GetMarkedSdrObj();
406 if( bUndo )
408 // extra undo actions for changed connector which now may hold its laid out path (SJ)
409 AddUndoActions( CreateConnectorUndo( *pO ) );
411 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pO));
414 // set up a scene updater if object is a 3d object
415 if(DynCastE3dObject(pO))
417 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO));
420 pO->Mirror(rRef1,rRef2);
423 // fire scene updaters
424 while(!aUpdaters.empty())
426 delete aUpdaters.back();
427 aUpdaters.pop_back();
431 if( bUndo )
432 EndUndo();
435 void SdrEditView::MirrorMarkedObjHorizontal()
437 Point aCenter(GetMarkedObjRect().Center());
438 Point aPt2(aCenter);
439 aPt2.AdjustY( 1 );
440 MirrorMarkedObj(aCenter,aPt2);
443 void SdrEditView::MirrorMarkedObjVertical()
445 Point aCenter(GetMarkedObjRect().Center());
446 Point aPt2(aCenter);
447 aPt2.AdjustX( 1 );
448 MirrorMarkedObj(aCenter,aPt2);
451 Degree100 SdrEditView::GetMarkedObjShear() const
453 bool b1st=true;
454 bool bOk=true;
455 Degree100 nAngle(0);
456 const SdrMarkList& rMarkList = GetMarkedObjectList();
457 const size_t nMarkCount=rMarkList.GetMarkCount();
458 for (size_t nm=0; nm<nMarkCount && bOk; ++nm) {
459 SdrMark* pM=rMarkList.GetMark(nm);
460 SdrObject* pO=pM->GetMarkedSdrObj();
461 Degree100 nAngle2=pO->GetShearAngle();
462 if (b1st) nAngle=nAngle2;
463 else if (nAngle2!=nAngle) bOk=false;
464 b1st=false;
466 if (nAngle>SDRMAXSHEAR) nAngle=SDRMAXSHEAR;
467 if (nAngle<-SDRMAXSHEAR) nAngle=-SDRMAXSHEAR;
468 if (!bOk) nAngle=0_deg100;
469 return nAngle;
472 void SdrEditView::ShearMarkedObj(const Point& rRef, Degree100 nAngle, bool bVShear, bool bCopy)
474 const bool bUndo = IsUndoEnabled();
476 if( bUndo )
478 EndTextEditCurrentView();
479 OUString aStr {ImpGetDescriptionString(STR_EditShear)};
480 if (bCopy)
481 aStr+=SvxResId(STR_EditWithCopy);
482 BegUndo(aStr);
485 if (bCopy)
486 CopyMarkedObj();
488 double nTan = tan(toRadians(nAngle));
489 const SdrMarkList& rMarkList = GetMarkedObjectList();
490 const size_t nMarkCount=rMarkList.GetMarkCount();
491 for (size_t nm=0; nm<nMarkCount; ++nm)
493 SdrMark* pM=rMarkList.GetMark(nm);
494 SdrObject* pO=pM->GetMarkedSdrObj();
495 if( bUndo )
497 AddUndoActions( CreateConnectorUndo( *pO ) );
498 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pO));
500 pO->Shear(rRef,nAngle,nTan,bVShear);
503 if( bUndo )
504 EndUndo();
507 void SdrEditView::ImpCrookObj(SdrObject* pO, const Point& rRef, const Point& rRad,
508 SdrCrookMode eMode, bool bVertical, bool bNoContortion, bool bRotate, const tools::Rectangle& rMarkRect)
510 SdrPathObj* pPath=dynamic_cast<SdrPathObj*>( pO );
511 bool bDone = false;
513 if(pPath!=nullptr && !bNoContortion)
515 XPolyPolygon aXPP(pPath->GetPathPoly());
516 switch (eMode) {
517 case SdrCrookMode::Rotate : CrookRotatePoly (aXPP,rRef,rRad,bVertical); break;
518 case SdrCrookMode::Slant : CrookSlantPoly (aXPP,rRef,rRad,bVertical); break;
519 case SdrCrookMode::Stretch: CrookStretchPoly(aXPP,rRef,rRad,bVertical,rMarkRect); break;
520 } // switch
521 pPath->SetPathPoly(aXPP.getB2DPolyPolygon());
522 bDone = true;
525 if(!bDone && !pPath && pO->IsPolyObj() && 0 != pO->GetPointCount())
527 // for PolyObj's, but NOT for SdrPathObj's, e.g. the measurement object
528 sal_uInt32 nPointCount(pO->GetPointCount());
529 XPolygon aXP(static_cast<sal_uInt16>(nPointCount));
530 sal_uInt32 nPtNum;
532 for(nPtNum = 0; nPtNum < nPointCount; nPtNum++)
534 Point aPt(pO->GetPoint(nPtNum));
535 aXP[static_cast<sal_uInt16>(nPtNum)]=aPt;
538 switch (eMode)
540 case SdrCrookMode::Rotate : CrookRotatePoly (aXP,rRef,rRad,bVertical); break;
541 case SdrCrookMode::Slant : CrookSlantPoly (aXP,rRef,rRad,bVertical); break;
542 case SdrCrookMode::Stretch: CrookStretchPoly(aXP,rRef,rRad,bVertical,rMarkRect); break;
545 for(nPtNum = 0; nPtNum < nPointCount; nPtNum++)
547 // broadcasting could be optimized here, but for the
548 // current two points of the measurement object, it's fine
549 pO->SetPoint(aXP[static_cast<sal_uInt16>(nPtNum)],nPtNum);
552 bDone = true;
555 if(bDone)
556 return;
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 nAngle(0.0);
565 if(0 != rRad.X() && 0 != rRad.Y())
567 bRotOk = bRotate;
569 switch (eMode)
571 case SdrCrookMode::Rotate : nAngle=CrookRotateXPoint (aCtr1,nullptr,nullptr,rRef,rRad,nSin,nCos,bVertical); bRotOk=bRotate; break;
572 case SdrCrookMode::Slant : nAngle=CrookSlantXPoint (aCtr1,nullptr,nullptr,rRef,rRad,nSin,nCos,bVertical); break;
573 case SdrCrookMode::Stretch: nAngle=CrookStretchXPoint(aCtr1,nullptr,nullptr,rRef,rRad,nSin,nCos,bVertical,rMarkRect); break;
577 aCtr1 -= aCtr0;
579 if(bRotOk)
580 pO->Rotate(aCtr0, Degree100(basegfx::fround(basegfx::rad2deg<100>(nAngle))), nSin, nCos);
582 pO->Move(Size(aCtr1.X(),aCtr1.Y()));
585 void SdrEditView::CrookMarkedObj(const Point& rRef, const Point& rRad, SdrCrookMode eMode,
586 bool bVertical, bool bNoContortion, bool bCopy)
588 tools::Rectangle aMarkRect(GetMarkedObjRect());
589 const bool bUndo = IsUndoEnabled();
591 bool bRotate=bNoContortion && eMode==SdrCrookMode::Rotate && IsRotateAllowed();
593 if( bUndo )
595 EndTextEditCurrentView();
596 OUString aStr {ImpGetDescriptionString(bNoContortion ? STR_EditCrook : STR_EditCrookContortion)};
597 if (bCopy)
598 aStr+=SvxResId(STR_EditWithCopy);
599 BegUndo(aStr);
602 if (bCopy)
603 CopyMarkedObj();
605 const SdrMarkList& rMarkList = GetMarkedObjectList();
606 const size_t nMarkCount=rMarkList.GetMarkCount();
607 for (size_t nm=0; nm<nMarkCount; ++nm)
609 SdrMark* pM=rMarkList.GetMark(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==nullptr) {
616 ImpCrookObj(pO,rRef,rRad,eMode,bVertical,bNoContortion,bRotate,aMarkRect);
617 } else {
618 SdrObjListIter aIter(pOL,SdrIterMode::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 tools::Rectangle& rRef, const XPolygon& rDistortedRect, bool bNoContortion)
632 SdrPathObj* pPath = dynamic_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 nPointCount(pO->GetPointCount());
644 XPolygon aXP(static_cast<sal_uInt16>(nPointCount));
645 sal_uInt32 nPtNum;
647 for(nPtNum = 0; nPtNum < nPointCount; nPtNum++)
649 Point aPt(pO->GetPoint(nPtNum));
650 aXP[static_cast<sal_uInt16>(nPtNum)]=aPt;
653 aXP.Distort(rRef, rDistortedRect);
655 for(nPtNum = 0; nPtNum < nPointCount; 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[static_cast<sal_uInt16>(nPtNum)],nPtNum);
664 void SdrEditView::DistortMarkedObj(const tools::Rectangle& rRef, const XPolygon& rDistortedRect, bool bNoContortion, bool bCopy)
666 const bool bUndo = IsUndoEnabled();
668 if( bUndo )
670 EndTextEditCurrentView();
671 OUString aStr {ImpGetDescriptionString(STR_EditDistort)};
672 if (bCopy)
673 aStr+=SvxResId(STR_EditWithCopy);
674 BegUndo(aStr);
677 if (bCopy)
678 CopyMarkedObj();
680 const SdrMarkList& rMarkList = GetMarkedObjectList();
681 const size_t nMarkCount=rMarkList.GetMarkCount();
682 for (size_t nm=0; nm<nMarkCount; ++nm)
684 SdrMark* pM=rMarkList.GetMark(nm);
685 SdrObject* pO=pM->GetMarkedSdrObj();
686 if (bUndo)
687 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pO));
689 tools::Rectangle aRefRect(rRef);
690 const SdrObjList* pOL=pO->GetSubList();
691 if (bNoContortion || pOL==nullptr) {
692 ImpDistortObj(pO,aRefRect,rDistortedRect,bNoContortion);
693 } else {
694 SdrObjListIter aIter(pOL,SdrIterMode::DeepNoGroups);
695 while (aIter.IsMore()) {
696 SdrObject* pO1=aIter.Next();
697 ImpDistortObj(pO1,aRefRect,rDistortedRect,bNoContortion);
701 if( bUndo )
702 EndUndo();
706 void SdrEditView::SetNotPersistAttrToMarked(const SfxItemSet& rAttr)
708 // bReplaceAll has no effect here
709 tools::Rectangle aAllSnapRect(GetMarkedObjRect());
710 if (const SdrTransformRef1XItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_TRANSFORMREF1X))
712 tools::Long n = pPoolItem->GetValue();
713 SetRef1(Point(n,GetRef1().Y()));
715 if (const SdrTransformRef1YItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_TRANSFORMREF1Y))
717 tools::Long n = pPoolItem->GetValue();
718 SetRef1(Point(GetRef1().X(),n));
720 if (const SdrTransformRef2XItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_TRANSFORMREF2X))
722 tools::Long n = pPoolItem->GetValue();
723 SetRef2(Point(n,GetRef2().Y()));
725 if (const SdrTransformRef2YItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_TRANSFORMREF2Y))
727 tools::Long n = pPoolItem->GetValue();
728 SetRef2(Point(GetRef2().X(),n));
730 tools::Long nAllPosX=0; bool bAllPosX=false;
731 tools::Long nAllPosY=0; bool bAllPosY=false;
732 tools::Long nAllWdt=0; bool bAllWdt=false;
733 tools::Long nAllHgt=0; bool bAllHgt=false;
734 bool bDoIt=false;
735 if (const SdrAllPositionXItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ALLPOSITIONX))
737 nAllPosX = pPoolItem->GetValue();
738 bAllPosX=true; bDoIt=true;
740 if (const SdrAllPositionYItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ALLPOSITIONY))
742 nAllPosY = pPoolItem->GetValue();
743 bAllPosY=true; bDoIt=true;
745 if (const SdrAllSizeWidthItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ALLSIZEWIDTH))
747 nAllWdt = pPoolItem->GetValue();
748 bAllWdt=true; bDoIt=true;
750 if (const SdrAllSizeHeightItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ALLSIZEHEIGHT))
752 nAllHgt = pPoolItem->GetValue();
753 bAllHgt=true; bDoIt=true;
755 if (bDoIt) {
756 tools::Rectangle aRect(aAllSnapRect); // TODO: change this for PolyPt's and GluePt's!!!
757 if (bAllPosX) aRect.Move(nAllPosX-aRect.Left(),0);
758 if (bAllPosY) aRect.Move(0,nAllPosY-aRect.Top());
759 if (bAllWdt) aRect.SetRight(aAllSnapRect.Left()+nAllWdt );
760 if (bAllHgt) aRect.SetBottom(aAllSnapRect.Top()+nAllHgt );
761 SetMarkedObjRect(aRect);
763 if (const SdrResizeXAllItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_RESIZEXALL))
765 Fraction aXFact = pPoolItem->GetValue();
766 ResizeMarkedObj(aAllSnapRect.TopLeft(),aXFact,Fraction(1,1));
768 if (const SdrResizeYAllItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_RESIZEYALL))
770 Fraction aYFact = pPoolItem->GetValue();
771 ResizeMarkedObj(aAllSnapRect.TopLeft(),Fraction(1,1),aYFact);
773 if (const SdrRotateAllItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ROTATEALL))
775 Degree100 nAngle = pPoolItem->GetValue();
776 RotateMarkedObj(aAllSnapRect.Center(),nAngle);
778 if (const SdrHorzShearAllItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_HORZSHEARALL))
780 Degree100 nAngle = pPoolItem->GetValue();
781 ShearMarkedObj(aAllSnapRect.Center(),nAngle);
783 if (const SdrVertShearAllItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_VERTSHEARALL))
785 Degree100 nAngle = pPoolItem->GetValue();
786 ShearMarkedObj(aAllSnapRect.Center(),nAngle,true);
789 const bool bUndo = IsUndoEnabled();
791 // TODO: check if WhichRange is necessary.
792 const SdrMarkList& rMarkList = GetMarkedObjectList();
793 const size_t nMarkCount=rMarkList.GetMarkCount();
794 for (size_t nm=0; nm<nMarkCount; ++nm)
796 const SdrMark* pM=rMarkList.GetMark(nm);
797 SdrObject* pObj=pM->GetMarkedSdrObj();
798 if (bUndo)
799 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
801 pObj->ApplyNotPersistAttr(rAttr);
805 void SdrEditView::MergeNotPersistAttrFromMarked(SfxItemSet& rAttr) const
807 // TODO: Take into account the origin and PvPos.
808 tools::Rectangle aAllSnapRect(GetMarkedObjRect()); // TODO: change this for PolyPt's and GluePt's!!!
809 tools::Long nAllSnapPosX=aAllSnapRect.Left();
810 tools::Long nAllSnapPosY=aAllSnapRect.Top();
811 tools::Long nAllSnapWdt=aAllSnapRect.GetWidth()-1;
812 tools::Long nAllSnapHgt=aAllSnapRect.GetHeight()-1;
813 // TODO: could go into CheckPossibilities
814 bool bMovProtect = false, bMovProtectDC = false;
815 bool bSizProtect = false, bSizProtectDC = false;
816 bool bPrintable = true, bPrintableDC = false;
817 bool bVisible = true, bVisibleDC = false;
818 SdrLayerID nLayerId(0);
819 bool bLayerDC=false;
820 tools::Long nSnapPosX=0; bool bSnapPosXDC=false;
821 tools::Long nSnapPosY=0; bool bSnapPosYDC=false;
822 tools::Long nSnapWdt=0; bool bSnapWdtDC=false;
823 tools::Long nSnapHgt=0; bool bSnapHgtDC=false;
824 tools::Long nLogicWdt=0; bool bLogicWdtDC=false,bLogicWdtDiff=false;
825 tools::Long nLogicHgt=0; bool bLogicHgtDC=false,bLogicHgtDiff=false;
826 Degree100 nRotAngle(0); bool bRotAngleDC=false;
827 Degree100 nShrAngle(0); bool bShrAngleDC=false;
828 tools::Rectangle aSnapRect;
829 tools::Rectangle aLogicRect;
830 const SdrMarkList& rMarkList = GetMarkedObjectList();
831 const size_t nMarkCount=rMarkList.GetMarkCount();
832 for (size_t nm=0; nm<nMarkCount; ++nm) {
833 const SdrMark* pM=rMarkList.GetMark(nm);
834 const SdrObject* pObj=pM->GetMarkedSdrObj();
835 if (nm==0) {
836 nLayerId=pObj->GetLayer();
837 bMovProtect=pObj->IsMoveProtect();
838 bSizProtect=pObj->IsResizeProtect();
839 bPrintable =pObj->IsPrintable();
840 bVisible = pObj->IsVisible();
841 tools::Rectangle aSnapRect2(pObj->GetSnapRect());
842 tools::Rectangle aLogicRect2(pObj->GetLogicRect());
843 nSnapPosX=aSnapRect2.Left();
844 nSnapPosY=aSnapRect2.Top();
845 nSnapWdt=aSnapRect2.GetWidth()-1;
846 nSnapHgt=aSnapRect2.GetHeight()-1;
847 nLogicWdt=aLogicRect2.GetWidth()-1;
848 nLogicHgt=aLogicRect2.GetHeight()-1;
849 bLogicWdtDiff=nLogicWdt!=nSnapWdt;
850 bLogicHgtDiff=nLogicHgt!=nSnapHgt;
851 nRotAngle=pObj->GetRotateAngle();
852 nShrAngle=pObj->GetShearAngle();
853 } else {
854 if (!bLayerDC && nLayerId !=pObj->GetLayer()) bLayerDC = true;
855 if (!bMovProtectDC && bMovProtect!=pObj->IsMoveProtect()) bMovProtectDC = true;
856 if (!bSizProtectDC && bSizProtect!=pObj->IsResizeProtect()) bSizProtectDC = true;
857 if (!bPrintableDC && bPrintable !=pObj->IsPrintable()) bPrintableDC = true;
858 if (!bVisibleDC && bVisible !=pObj->IsVisible()) bVisibleDC=true;
859 if (!bRotAngleDC && nRotAngle !=pObj->GetRotateAngle()) bRotAngleDC=true;
860 if (!bShrAngleDC && nShrAngle !=pObj->GetShearAngle()) bShrAngleDC=true;
861 if (!bSnapWdtDC || !bSnapHgtDC || !bSnapPosXDC || !bSnapPosYDC || !bLogicWdtDiff || !bLogicHgtDiff) {
862 aSnapRect=pObj->GetSnapRect();
863 if (nSnapPosX!=aSnapRect.Left()) bSnapPosXDC=true;
864 if (nSnapPosY!=aSnapRect.Top()) bSnapPosYDC=true;
865 if (nSnapWdt!=aSnapRect.GetWidth()-1) bSnapWdtDC=true;
866 if (nSnapHgt!=aSnapRect.GetHeight()-1) bSnapHgtDC=true;
868 if (!bLogicWdtDC || !bLogicHgtDC || !bLogicWdtDiff || !bLogicHgtDiff) {
869 aLogicRect=pObj->GetLogicRect();
870 if (nLogicWdt!=aLogicRect.GetWidth()-1) bLogicWdtDC=true;
871 if (nLogicHgt!=aLogicRect.GetHeight()-1) bLogicHgtDC=true;
872 if (!bLogicWdtDiff && aSnapRect.GetWidth()!=aLogicRect.GetWidth()) bLogicWdtDiff=true;
873 if (!bLogicHgtDiff && aSnapRect.GetHeight()!=aLogicRect.GetHeight()) bLogicHgtDiff=true;
878 if (bSnapPosXDC || nAllSnapPosX!=nSnapPosX) rAttr.Put(SdrAllPositionXItem(nAllSnapPosX));
879 if (bSnapPosYDC || nAllSnapPosY!=nSnapPosY) rAttr.Put(SdrAllPositionYItem(nAllSnapPosY));
880 if (bSnapWdtDC || nAllSnapWdt !=nSnapWdt ) rAttr.Put(SdrAllSizeWidthItem(nAllSnapWdt));
881 if (bSnapHgtDC || nAllSnapHgt !=nSnapHgt ) rAttr.Put(SdrAllSizeHeightItem(nAllSnapHgt));
883 // items for pure transformations
884 rAttr.Put(SdrMoveXItem());
885 rAttr.Put(SdrMoveYItem());
886 rAttr.Put(SdrResizeXOneItem());
887 rAttr.Put(SdrResizeYOneItem());
888 rAttr.Put(SdrRotateOneItem());
889 rAttr.Put(SdrHorzShearOneItem());
890 rAttr.Put(SdrVertShearOneItem());
892 if (nMarkCount>1) {
893 rAttr.Put(SdrResizeXAllItem());
894 rAttr.Put(SdrResizeYAllItem());
895 rAttr.Put(SdrRotateAllItem());
896 rAttr.Put(SdrHorzShearAllItem());
897 rAttr.Put(SdrVertShearAllItem());
900 if(meDragMode == SdrDragMode::Rotate || meDragMode == SdrDragMode::Mirror)
902 rAttr.Put(SdrTransformRef1XItem(GetRef1().X()));
903 rAttr.Put(SdrTransformRef1YItem(GetRef1().Y()));
906 if(meDragMode == SdrDragMode::Mirror)
908 rAttr.Put(SdrTransformRef2XItem(GetRef2().X()));
909 rAttr.Put(SdrTransformRef2YItem(GetRef2().Y()));
913 SfxItemSet SdrEditView::GetAttrFromMarked(bool bOnlyHardAttr) const
915 SfxItemSet aSet(GetModel().GetItemPool());
916 MergeAttrFromMarked(aSet,bOnlyHardAttr);
917 //the EE_FEATURE items should not be set with SetAttrToMarked (see error message there)
918 //so we do not set them here
919 // #i32448#
920 // Do not disable, but clear the items.
921 aSet.ClearItem(EE_FEATURE_TAB);
922 aSet.ClearItem(EE_FEATURE_LINEBR);
923 aSet.ClearItem(EE_FEATURE_NOTCONV);
924 aSet.ClearItem(EE_FEATURE_FIELD);
926 return aSet;
929 void SdrEditView::MergeAttrFromMarked(SfxItemSet& rAttr, bool bOnlyHardAttr) const
931 const SdrMarkList& rMarkList = GetMarkedObjectList();
932 const size_t nMarkCount(rMarkList.GetMarkCount());
934 for(size_t a = 0; a < nMarkCount; ++a)
936 // #80277# merging was done wrong in the prev version
937 SdrObject *pObj = rMarkList.GetMark(a)->GetMarkedSdrObj();
938 if (!pObj)
940 continue;
943 const SfxItemSet& rSet = pObj->GetMergedItemSet();
944 SfxWhichIter aIter(rSet);
945 sal_uInt16 nWhich(aIter.FirstWhich());
947 while(nWhich)
949 if(!bOnlyHardAttr)
951 if(SfxItemState::INVALID == aIter.GetItemState(false))
952 rAttr.InvalidateItem(nWhich);
953 else
954 rAttr.MergeValue(rSet.Get(nWhich));
956 else if(SfxItemState::SET == aIter.GetItemState(false))
958 const SfxPoolItem& rItem = rSet.Get(nWhich);
959 rAttr.MergeValue(rItem);
962 if (comphelper::LibreOfficeKit::isActive())
964 OUString sPayload;
965 switch(nWhich)
967 case XATTR_LINECOLOR:
969 const SfxPoolItem* pItem = rSet.GetItem(XATTR_LINECOLOR);
970 if (pItem)
972 Color aColor = static_cast<const XLineColorItem*>(pItem)->GetColorValue();
973 sPayload = OUString::number(static_cast<sal_uInt32>(aColor));
975 sPayload = ".uno:XLineColor=" + sPayload;
977 break;
980 case XATTR_FILLCOLOR:
982 const SfxPoolItem* pItem = rSet.GetItem(XATTR_FILLCOLOR);
983 if (pItem)
985 Color aColor = static_cast<const XFillColorItem*>(pItem)->GetColorValue();
986 sPayload = OUString::number(static_cast<sal_uInt32>(aColor));
988 sPayload = ".uno:FillColor=" + sPayload;
990 break;
993 case XATTR_FILLTRANSPARENCE:
995 const SfxPoolItem* pItem = rSet.GetItem(XATTR_FILLTRANSPARENCE);
996 if (pItem)
998 sal_uInt16 nTransparency = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
999 sPayload = OUString::number(nTransparency);
1001 sPayload = ".uno:FillTransparence=" + sPayload;
1003 break;
1006 case XATTR_LINETRANSPARENCE:
1008 const SfxPoolItem* pItem = rSet.GetItem(XATTR_LINETRANSPARENCE);
1009 if (pItem)
1011 sal_uInt16 nTransparency = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
1012 sPayload = OUString::number(nTransparency);
1014 sPayload = ".uno:LineTransparence=" + sPayload;
1016 break;
1019 case XATTR_LINEWIDTH:
1021 const SfxPoolItem* pItem = rSet.GetItem(XATTR_LINEWIDTH);
1022 if (pItem)
1024 sal_uInt32 nWidth = static_cast<const XLineWidthItem*>(pItem)->GetValue();
1025 sPayload = OUString::number(nWidth);
1027 sPayload = ".uno:LineWidth=" + sPayload;
1029 break;
1032 case SDRATTR_SHADOWTRANSPARENCE:
1034 const SfxPoolItem* pItem = rSet.GetItem(SDRATTR_SHADOWTRANSPARENCE);
1035 if (pItem)
1037 sal_uInt16 nWidth = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
1038 sPayload = OUString::number(nWidth);
1040 sPayload = ".uno:FillShadowTransparency=" + sPayload;
1042 break;
1046 if (!sPayload.isEmpty())
1048 if (SfxViewShell* pViewShell = GetSfxViewShell())
1050 pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED,
1051 OUStringToOString(sPayload, RTL_TEXTENCODING_ASCII_US));
1056 nWhich = aIter.NextWhich();
1061 std::vector<sal_uInt16> GetAllCharPropIds(const SfxItemSet& rSet)
1063 std::vector<sal_uInt16> aCharWhichIds;
1065 SfxItemIter aIter(rSet);
1066 for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
1068 if (!IsInvalidItem(pItem))
1070 sal_uInt16 nWhich = pItem->Which();
1071 if (nWhich>=EE_CHAR_START && nWhich<=EE_CHAR_END)
1072 aCharWhichIds.push_back( nWhich );
1076 return aCharWhichIds;
1079 std::vector<sal_uInt16> GetAllCharPropIds(std::span< const SfxPoolItem* const > aChangedItems)
1081 std::vector<sal_uInt16> aCharWhichIds;
1082 for (const SfxPoolItem* pItem : aChangedItems)
1084 sal_uInt16 nWhich = pItem->Which();
1085 if (nWhich>=EE_CHAR_START && nWhich<=EE_CHAR_END)
1086 aCharWhichIds.push_back( nWhich );
1088 return aCharWhichIds;
1091 void SdrEditView::SetAttrToMarked(const SfxItemSet& rAttr, bool bReplaceAll)
1093 const SdrMarkList& rMarkList = GetMarkedObjectList();
1094 if (rMarkList.GetMarkCount() == 0)
1095 return;
1097 #ifdef DBG_UTIL
1099 bool bHasEEFeatureItems=false;
1100 SfxItemIter aIter(rAttr);
1101 for (const SfxPoolItem* pItem = aIter.GetCurItem(); !bHasEEFeatureItems && pItem;
1102 pItem = aIter.NextItem())
1104 if (!IsInvalidItem(pItem)) {
1105 sal_uInt16 nW=pItem->Which();
1106 if (nW>=EE_FEATURE_START && nW<=EE_FEATURE_END) bHasEEFeatureItems=true;
1109 if(bHasEEFeatureItems)
1111 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr,
1112 VclMessageType::Info, VclButtonsType::Ok,
1113 u"SdrEditView::SetAttrToMarked(): Setting EE_FEATURE items at the SdrView does not make sense! It only leads to overhead and unreadable documents."_ustr));
1114 xInfoBox->run();
1117 #endif
1119 // #103836# if the user sets character attributes to the complete shape,
1120 // we want to remove all hard set character attributes with same
1121 // which ids from the text. We do that later but here we remember
1122 // all character attribute which id's that are set.
1123 std::vector<sal_uInt16> aCharWhichIds(GetAllCharPropIds(rAttr));
1125 // To make Undo reconstruct text attributes correctly after Format.Standard
1126 bool bHasEEItems=SearchOutlinerItems(rAttr,bReplaceAll);
1128 // save additional geometry information when paragraph or character attributes
1129 // are changed and the geometrical shape of the text object might be changed
1130 bool bPossibleGeomChange(false);
1131 SfxWhichIter aIter(rAttr);
1132 sal_uInt16 nWhich = aIter.FirstWhich();
1133 while(!bPossibleGeomChange && nWhich)
1135 SfxItemState eState = aIter.GetItemState();
1136 if(eState == SfxItemState::SET)
1138 if((nWhich >= SDRATTR_TEXT_MINFRAMEHEIGHT && nWhich <= SDRATTR_TEXT_CONTOURFRAME)
1139 || nWhich == SDRATTR_3DOBJ_PERCENT_DIAGONAL
1140 || nWhich == SDRATTR_3DOBJ_BACKSCALE
1141 || nWhich == SDRATTR_3DOBJ_DEPTH
1142 || nWhich == SDRATTR_3DOBJ_END_ANGLE
1143 || nWhich == SDRATTR_3DSCENE_DISTANCE)
1145 bPossibleGeomChange = true;
1148 nWhich = aIter.NextWhich();
1151 const bool bUndo = IsUndoEnabled();
1152 if( bUndo )
1154 EndTextEditCurrentView();
1155 BegUndo(ImpGetDescriptionString(STR_EditSetAttributes));
1158 const size_t nMarkCount(rMarkList.GetMarkCount());
1159 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
1161 // create ItemSet without SfxItemState::INVALID. Put()
1162 // uses its second parameter (bInvalidAsDefault) to
1163 // remove all such items to set them to default.
1164 SfxItemSet aAttr(*rAttr.GetPool(), rAttr.GetRanges());
1165 aAttr.Put(rAttr);
1167 // #i38135#
1168 bool bResetAnimationTimer(false);
1170 const bool bLineStartWidthExplicitChange(SfxItemState::SET
1171 == aAttr.GetItemState(XATTR_LINESTARTWIDTH));
1172 const bool bLineEndWidthExplicitChange(SfxItemState::SET
1173 == aAttr.GetItemState(XATTR_LINEENDWIDTH));
1174 // check if LineWidth is part of the change
1175 const bool bAdaptStartEndWidths(!(bLineStartWidthExplicitChange && bLineEndWidthExplicitChange)
1176 && SfxItemState::SET == aAttr.GetItemState(XATTR_LINEWIDTH));
1177 sal_Int32 nNewLineWidth(0);
1179 if(bAdaptStartEndWidths)
1181 nNewLineWidth = aAttr.Get(XATTR_LINEWIDTH).GetValue();
1184 for (size_t nm=0; nm<nMarkCount; ++nm)
1186 SdrMark* pM=rMarkList.GetMark(nm);
1187 SdrObject* pObj = pM->GetMarkedSdrObj();
1189 if( bUndo )
1191 SdrEdgeObj* pEdgeObj = dynamic_cast< SdrEdgeObj* >( pObj );
1192 if ( pEdgeObj )
1193 bPossibleGeomChange = true;
1194 else
1195 AddUndoActions( CreateConnectorUndo( *pObj ) );
1198 // new geometry undo
1199 if(bPossibleGeomChange && bUndo)
1201 // save position and size of object, too
1202 AddUndo( GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
1205 if( bUndo )
1207 // #i8508#
1208 // If this is a text object also rescue the OutlinerParaObject since
1209 // applying attributes to the object may change text layout when
1210 // multiple portions exist with multiple formats. If an OutlinerParaObject
1211 // really exists and needs to be rescued is evaluated in the undo
1212 // implementation itself.
1213 const bool bRescueText = DynCastSdrTextObj(pObj) != nullptr;
1215 // add attribute undo
1216 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoAttrObject(*pObj,false,bHasEEItems || bPossibleGeomChange || bRescueText));
1219 // set up a scene updater if object is a 3d object
1220 if(DynCastE3dObject(pObj))
1222 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pObj));
1225 sal_Int32 nOldLineWidth(0);
1226 if (bAdaptStartEndWidths)
1228 nOldLineWidth = pObj->GetMergedItem(XATTR_LINEWIDTH).GetValue();
1231 // set attributes at object
1232 pObj->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
1234 if(bAdaptStartEndWidths)
1236 const SfxItemSet& rSet = pObj->GetMergedItemSet();
1238 if(nOldLineWidth != nNewLineWidth)
1240 if(SfxItemState::INVALID != rSet.GetItemState(XATTR_LINESTARTWIDTH))
1242 const sal_Int32 nValAct(rSet.Get(XATTR_LINESTARTWIDTH).GetValue());
1243 const sal_Int32 nValNewStart(std::max(sal_Int32(0), nValAct + (((nNewLineWidth - nOldLineWidth) * 15) / 10)));
1245 pObj->SetMergedItem(XLineStartWidthItem(nValNewStart));
1248 if(SfxItemState::INVALID != rSet.GetItemState(XATTR_LINEENDWIDTH))
1250 const sal_Int32 nValAct(rSet.Get(XATTR_LINEENDWIDTH).GetValue());
1251 const sal_Int32 nValNewEnd(std::max(sal_Int32(0), nValAct + (((nNewLineWidth - nOldLineWidth) * 15) / 10)));
1253 pObj->SetMergedItem(XLineEndWidthItem(nValNewEnd));
1258 if(auto pTextObj = DynCastSdrTextObj( pObj))
1260 if(!aCharWhichIds.empty())
1262 tools::Rectangle aOldBoundRect = pTextObj->GetLastBoundRect();
1264 // #110094#-14 pTextObj->SendRepaintBroadcast(pTextObj->GetBoundRect());
1265 pTextObj->RemoveOutlinerCharacterAttribs( aCharWhichIds );
1267 // object has changed, should be called from
1268 // RemoveOutlinerCharacterAttribs. This will change when the text
1269 // object implementation changes.
1270 pTextObj->SetChanged();
1272 pTextObj->BroadcastObjectChange();
1273 pTextObj->SendUserCall(SdrUserCallType::ChangeAttr, aOldBoundRect);
1277 // #i38495#
1278 if(!bResetAnimationTimer)
1280 if(pObj->GetViewContact().isAnimatedInAnyViewObjectContact())
1282 bResetAnimationTimer = true;
1287 // fire scene updaters
1288 while(!aUpdaters.empty())
1290 delete aUpdaters.back();
1291 aUpdaters.pop_back();
1294 // #i38135#
1295 if(bResetAnimationTimer)
1297 SetAnimationTimer(0);
1300 // better check before what to do:
1301 // pObj->SetAttr() or SetNotPersistAttr()
1302 // TODO: missing implementation!
1303 SetNotPersistAttrToMarked(rAttr);
1305 if( bUndo )
1306 EndUndo();
1309 SfxStyleSheet* SdrEditView::GetStyleSheetFromMarked() const
1311 SfxStyleSheet* pRet=nullptr;
1312 bool b1st=true;
1313 const SdrMarkList& rMarkList = GetMarkedObjectList();
1314 const size_t nMarkCount=rMarkList.GetMarkCount();
1315 for (size_t nm=0; nm<nMarkCount; ++nm) {
1316 SdrMark* pM=rMarkList.GetMark(nm);
1317 SfxStyleSheet* pSS=pM->GetMarkedSdrObj()->GetStyleSheet();
1318 if (b1st) pRet=pSS;
1319 else if (pRet!=pSS) return nullptr; // different stylesheets
1320 b1st=false;
1322 return pRet;
1325 void SdrEditView::SetStyleSheetToMarked(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
1327 const SdrMarkList& rMarkList = GetMarkedObjectList();
1328 if (rMarkList.GetMarkCount() == 0)
1329 return;
1331 const bool bUndo = IsUndoEnabled();
1333 if( bUndo )
1335 EndTextEditCurrentView();
1336 OUString aStr;
1337 if (pStyleSheet!=nullptr)
1338 aStr = ImpGetDescriptionString(STR_EditSetStylesheet);
1339 else
1340 aStr = ImpGetDescriptionString(STR_EditDelStylesheet);
1341 BegUndo(aStr);
1344 const size_t nMarkCount=rMarkList.GetMarkCount();
1345 for (size_t nm=0; nm<nMarkCount; ++nm)
1347 SdrMark* pM=rMarkList.GetMark(nm);
1348 if( bUndo )
1350 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pM->GetMarkedSdrObj()));
1351 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoAttrObject(*pM->GetMarkedSdrObj(),true,true));
1353 pM->GetMarkedSdrObj()->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1356 if( bUndo )
1357 EndUndo();
1361 void SdrEditView::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
1363 const SdrMarkList& rMarkList = GetMarkedObjectList();
1364 if(rMarkList.GetMarkCount())
1366 rTargetSet.Put(GetAttrFromMarked(bOnlyHardAttr), false);
1368 else
1370 SdrMarkView::GetAttributes(rTargetSet, bOnlyHardAttr);
1374 void SdrEditView::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
1376 const SdrMarkList& rMarkList = GetMarkedObjectList();
1377 if (rMarkList.GetMarkCount()!=0) {
1378 SetAttrToMarked(rSet,bReplaceAll);
1379 } else {
1380 SdrMarkView::SetAttributes(rSet,bReplaceAll);
1384 SfxStyleSheet* SdrEditView::GetStyleSheet() const
1386 const SdrMarkList& rMarkList = GetMarkedObjectList();
1387 if (rMarkList.GetMarkCount()!=0) {
1388 return GetStyleSheetFromMarked();
1389 } else {
1390 return SdrMarkView::GetStyleSheet();
1394 void SdrEditView::SetStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
1396 const SdrMarkList& rMarkList = GetMarkedObjectList();
1397 if (rMarkList.GetMarkCount()!=0) {
1398 SetStyleSheetToMarked(pStyleSheet,bDontRemoveHardAttr);
1399 } else {
1400 SdrMarkView::SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1405 SfxItemSet SdrEditView::GetGeoAttrFromMarked() const
1407 SfxItemSet aRetSet(
1408 GetModel().GetItemPool(),
1409 svl::Items< // SID_ATTR_TRANSFORM_... from s:svxids.hrc
1410 SDRATTR_CORNER_RADIUS, SDRATTR_CORNER_RADIUS,
1411 SID_ATTR_TRANSFORM_POS_X, SID_ATTR_TRANSFORM_ANGLE,
1412 SID_ATTR_TRANSFORM_PROTECT_POS, SID_ATTR_TRANSFORM_AUTOHEIGHT>);
1414 const SdrMarkList& rMarkList = GetMarkedObjectList();
1415 if (rMarkList.GetMarkCount() != 0)
1417 SfxItemSet aMarkAttr(GetAttrFromMarked(false)); // because of AutoGrowHeight and corner radius
1418 tools::Rectangle aRect(GetMarkedObjRect());
1420 if(GetSdrPageView())
1422 GetSdrPageView()->LogicToPagePos(aRect);
1425 // position
1426 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_X,aRect.Left()));
1427 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_Y,aRect.Top()));
1429 // size
1430 tools::Long nResizeRefX=aRect.Left();
1431 tools::Long nResizeRefY=aRect.Top();
1432 if (meDragMode==SdrDragMode::Rotate) { // use rotation axis as a reference for resizing, too
1433 nResizeRefX=maRef1.X();
1434 nResizeRefY=maRef1.Y();
1436 aRetSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_WIDTH,aRect.Right()-aRect.Left()));
1437 aRetSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_HEIGHT,aRect.Bottom()-aRect.Top()));
1438 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_RESIZE_REF_X,nResizeRefX));
1439 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_RESIZE_REF_Y,nResizeRefY));
1441 Point aRotateAxe(maRef1);
1443 if(GetSdrPageView())
1445 GetSdrPageView()->LogicToPagePos(aRotateAxe);
1448 // rotation
1449 tools::Long nRotateRefX=aRect.Center().X();
1450 tools::Long nRotateRefY=aRect.Center().Y();
1451 if (meDragMode==SdrDragMode::Rotate) {
1452 nRotateRefX=aRotateAxe.X();
1453 nRotateRefY=aRotateAxe.Y();
1455 aRetSet.Put(SdrAngleItem(SID_ATTR_TRANSFORM_ANGLE,GetMarkedObjRotate()));
1456 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_X,nRotateRefX));
1457 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_Y,nRotateRefY));
1459 // shearing
1460 tools::Long nShearRefX=aRect.Left();
1461 tools::Long nShearRefY=aRect.Bottom();
1462 if (meDragMode==SdrDragMode::Rotate) { // use rotation axis as a reference for shearing, too
1463 nShearRefX=aRotateAxe.X();
1464 nShearRefY=aRotateAxe.Y();
1466 aRetSet.Put(SdrAngleItem(SID_ATTR_TRANSFORM_SHEAR,GetMarkedObjShear()));
1467 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_X,nShearRefX));
1468 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_Y,nShearRefY));
1470 // check every object whether it is protected
1471 const size_t nMarkCount=rMarkList.GetMarkCount();
1472 SdrObject* pObj=rMarkList.GetMark(0)->GetMarkedSdrObj();
1473 bool bPosProt=pObj->IsMoveProtect();
1474 bool bSizProt=pObj->IsResizeProtect();
1475 bool bPosProtDontCare=false;
1476 bool bSizProtDontCare=false;
1477 for (size_t i=1; i<nMarkCount && (!bPosProtDontCare || !bSizProtDontCare); ++i)
1479 pObj=rMarkList.GetMark(i)->GetMarkedSdrObj();
1480 if (bPosProt!=pObj->IsMoveProtect()) bPosProtDontCare=true;
1481 if (bSizProt!=pObj->IsResizeProtect()) bSizProtDontCare=true;
1484 // InvalidateItem sets item to DONT_CARE
1485 if (bPosProtDontCare) {
1486 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_PROTECT_POS);
1487 } else {
1488 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_PROTECT_POS,bPosProt));
1490 if (bSizProtDontCare) {
1491 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_PROTECT_SIZE);
1492 } else {
1493 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_PROTECT_SIZE,bSizProt));
1496 SfxItemState eState=aMarkAttr.GetItemState(SDRATTR_TEXT_AUTOGROWWIDTH);
1497 bool bAutoGrow=aMarkAttr.Get(SDRATTR_TEXT_AUTOGROWWIDTH).GetValue();
1498 if (eState==SfxItemState::INVALID) {
1499 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_AUTOWIDTH);
1500 } else if (eState==SfxItemState::SET) {
1501 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_AUTOWIDTH,bAutoGrow));
1504 eState=aMarkAttr.GetItemState(SDRATTR_TEXT_AUTOGROWHEIGHT);
1505 bAutoGrow=aMarkAttr.Get(SDRATTR_TEXT_AUTOGROWHEIGHT).GetValue();
1506 if (eState==SfxItemState::INVALID) {
1507 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_AUTOHEIGHT);
1508 } else if (eState==SfxItemState::SET) {
1509 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_AUTOHEIGHT,bAutoGrow));
1512 eState=aMarkAttr.GetItemState(SDRATTR_CORNER_RADIUS);
1513 tools::Long nRadius=aMarkAttr.Get(SDRATTR_CORNER_RADIUS).GetValue();
1514 if (eState==SfxItemState::INVALID) {
1515 aRetSet.InvalidateItem(SDRATTR_CORNER_RADIUS);
1516 } else if (eState==SfxItemState::SET) {
1517 aRetSet.Put(makeSdrEckenradiusItem(nRadius));
1520 basegfx::B2DHomMatrix aTransformation;
1522 if(nMarkCount > 1)
1524 // multiple objects, range is collected in aRect
1525 aTransformation = basegfx::utils::createScaleTranslateB2DHomMatrix(
1526 aRect.Left(), aRect.Top(),
1527 aRect.getOpenWidth(), aRect.getOpenHeight());
1529 else
1531 // single object, get homogen transformation
1532 basegfx::B2DPolyPolygon aPolyPolygon;
1534 pObj->TRGetBaseGeometry(aTransformation, aPolyPolygon);
1537 if(aTransformation.isIdentity())
1539 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_MATRIX);
1541 else
1543 css::geometry::AffineMatrix2D aAffineMatrix2D;
1544 Point aPageOffset(0, 0);
1546 if(GetSdrPageView())
1548 aPageOffset = GetSdrPageView()->GetPageOrigin();
1551 aAffineMatrix2D.m00 = aTransformation.get(0, 0);
1552 aAffineMatrix2D.m01 = aTransformation.get(0, 1);
1553 aAffineMatrix2D.m02 = aTransformation.get(0, 2) - aPageOffset.X();
1554 aAffineMatrix2D.m10 = aTransformation.get(1, 0);
1555 aAffineMatrix2D.m11 = aTransformation.get(1, 1);
1556 aAffineMatrix2D.m12 = aTransformation.get(1, 2) - aPageOffset.Y();
1558 aRetSet.Put(AffineMatrixItem(&aAffineMatrix2D));
1562 return aRetSet;
1565 static Point ImpGetPoint(const tools::Rectangle& rRect, RectPoint eRP)
1567 switch(eRP) {
1568 case RectPoint::LT: return rRect.TopLeft();
1569 case RectPoint::MT: return rRect.TopCenter();
1570 case RectPoint::RT: return rRect.TopRight();
1571 case RectPoint::LM: return rRect.LeftCenter();
1572 case RectPoint::MM: return rRect.Center();
1573 case RectPoint::RM: return rRect.RightCenter();
1574 case RectPoint::LB: return rRect.BottomLeft();
1575 case RectPoint::MB: return rRect.BottomCenter();
1576 case RectPoint::RB: return rRect.BottomRight();
1578 return Point(); // Should not happen!
1581 void SdrEditView::SetGeoAttrToMarked(const SfxItemSet& rAttr, bool addPageMargin)
1583 const bool bTiledRendering = comphelper::LibreOfficeKit::isActive();
1585 tools::Rectangle aRect(GetMarkedObjRect());
1587 if(GetSdrPageView())
1589 if (addPageMargin)
1591 SdrPage * pPage = GetSdrPageView()->GetPage();
1592 Point upperLeft(pPage->GetLeftBorder(), pPage->GetUpperBorder());
1593 aRect.Move(upperLeft.getX(), upperLeft.getY());
1595 GetSdrPageView()->LogicToPagePos(aRect);
1598 Degree100 nOldRotateAngle=GetMarkedObjRotate();
1599 Degree100 nOldShearAngle=GetMarkedObjShear();
1600 const SdrMarkList& rMarkList=GetMarkedObjectList();
1601 SdrObject* pObj=nullptr;
1603 RectPoint eSizePoint=RectPoint::MM;
1604 tools::Long nPosDX=0;
1605 tools::Long nPosDY=0;
1606 tools::Long nSizX=0;
1607 tools::Long nSizY=0;
1608 Degree100 nRotateAngle(0);
1610 bool bModeIsRotate(meDragMode == SdrDragMode::Rotate);
1611 tools::Long nRotateX(0);
1612 tools::Long nRotateY(0);
1613 tools::Long nOldRotateX(0);
1614 tools::Long nOldRotateY(0);
1615 if(bModeIsRotate)
1617 Point aRotateAxe(maRef1);
1619 if(GetSdrPageView())
1621 GetSdrPageView()->LogicToPagePos(aRotateAxe);
1624 nRotateX = nOldRotateX = aRotateAxe.X();
1625 nRotateY = nOldRotateY = aRotateAxe.Y();
1628 Degree100 nShearAngle(0);
1629 tools::Long nShearX=0;
1630 tools::Long nShearY=0;
1631 bool bShearVert=false;
1633 bool bChgPos=false;
1634 bool bChgSiz=false;
1635 bool bChgWdh=false;
1636 bool bChgHgt=false;
1637 bool bRotate=false;
1638 bool bShear =false;
1640 bool bSetAttr=false;
1641 SfxItemSet aSetAttr(GetModel().GetItemPool());
1643 // position
1644 if (const SfxInt32Item *pPoolItem = rAttr.GetItemIfSet(SID_ATTR_TRANSFORM_POS_X))
1646 nPosDX = pPoolItem->GetValue() - aRect.Left();
1647 bChgPos=true;
1649 if (const SfxInt32Item *pPoolItem = rAttr.GetItemIfSet(SID_ATTR_TRANSFORM_POS_Y))
1651 nPosDY = pPoolItem->GetValue() - aRect.Top();
1652 bChgPos=true;
1654 // size
1655 if (const SfxUInt32Item *pPoolItem = rAttr.GetItemIfSet(SID_ATTR_TRANSFORM_WIDTH))
1657 nSizX = pPoolItem->GetValue();
1658 bChgSiz=true;
1659 bChgWdh=true;
1661 if (const SfxUInt32Item *pPoolItem = rAttr.GetItemIfSet(SID_ATTR_TRANSFORM_HEIGHT))
1663 nSizY = pPoolItem->GetValue();
1664 bChgSiz=true;
1665 bChgHgt=true;
1667 if (bChgSiz) {
1668 if (bTiledRendering && SfxItemState::SET != rAttr.GetItemState(SID_ATTR_TRANSFORM_SIZE_POINT))
1669 eSizePoint = RectPoint::LT;
1670 else
1671 eSizePoint = static_cast<RectPoint>(rAttr.Get(SID_ATTR_TRANSFORM_SIZE_POINT).GetValue());
1674 // rotation
1675 if (const SdrAngleItem *pPoolItem = rAttr.GetItemIfSet(SID_ATTR_TRANSFORM_DELTA_ANGLE))
1677 nRotateAngle = pPoolItem->GetValue();
1678 bRotate = (nRotateAngle != 0_deg100);
1681 // rotation
1682 if (const SdrAngleItem *pPoolItem = rAttr.GetItemIfSet(SID_ATTR_TRANSFORM_ANGLE))
1684 nRotateAngle = pPoolItem->GetValue() - nOldRotateAngle;
1685 bRotate = (nRotateAngle != 0_deg100);
1688 // position rotation point x
1689 if(bRotate || rAttr.GetItemIfSet(SID_ATTR_TRANSFORM_ROT_X))
1690 nRotateX = rAttr.Get(SID_ATTR_TRANSFORM_ROT_X).GetValue();
1692 // position rotation point y
1693 if(bRotate || rAttr.GetItemIfSet(SID_ATTR_TRANSFORM_ROT_Y))
1694 nRotateY = rAttr.Get(SID_ATTR_TRANSFORM_ROT_Y).GetValue();
1696 // shearing
1697 if (const SdrAngleItem *pPoolItem = rAttr.GetItemIfSet(SID_ATTR_TRANSFORM_SHEAR))
1699 Degree100 nNewShearAngle=pPoolItem->GetValue();
1700 if (nNewShearAngle>SDRMAXSHEAR) nNewShearAngle=SDRMAXSHEAR;
1701 if (nNewShearAngle<-SDRMAXSHEAR) nNewShearAngle=-SDRMAXSHEAR;
1702 if (nNewShearAngle!=nOldShearAngle) {
1703 bShearVert = rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_VERTICAL).GetValue();
1704 if (bShearVert) {
1705 nShearAngle=nNewShearAngle;
1706 } else {
1707 if (nNewShearAngle!=0_deg100 && nOldShearAngle!=0_deg100) {
1708 // bug fix
1709 double nOld = tan(toRadians(nOldShearAngle));
1710 double nNew = tan(toRadians(nNewShearAngle));
1711 nNew-=nOld;
1712 nNew = basegfx::rad2deg<100>(atan(nNew));
1713 nShearAngle = Degree100(basegfx::fround(nNew));
1714 } else {
1715 nShearAngle=nNewShearAngle-nOldShearAngle;
1718 bShear=nShearAngle!=0_deg100;
1719 if (bShear) {
1720 nShearX = rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_X).GetValue();
1721 nShearY = rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_Y).GetValue();
1726 // AutoGrow
1727 if (const SfxBoolItem *pPoolItem = rAttr.GetItemIfSet(SID_ATTR_TRANSFORM_AUTOWIDTH))
1729 bool bAutoGrow = pPoolItem->GetValue();
1730 aSetAttr.Put(makeSdrTextAutoGrowWidthItem(bAutoGrow));
1731 bSetAttr=true;
1734 if (const SfxBoolItem *pPoolItem = rAttr.GetItemIfSet(SID_ATTR_TRANSFORM_AUTOHEIGHT))
1736 bool bAutoGrow = pPoolItem->GetValue();
1737 aSetAttr.Put(makeSdrTextAutoGrowHeightItem(bAutoGrow));
1738 bSetAttr=true;
1741 // corner radius
1742 if (m_bEdgeRadiusAllowed)
1743 if (const SdrMetricItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_CORNER_RADIUS))
1745 tools::Long nRadius = pPoolItem->GetValue();
1746 aSetAttr.Put(makeSdrEckenradiusItem(nRadius));
1747 bSetAttr=true;
1750 ForcePossibilities();
1752 BegUndo(SvxResId(STR_EditTransform),rMarkList.GetMarkDescription());
1754 if (bSetAttr) {
1755 SetAttrToMarked(aSetAttr,false);
1758 // change size and height
1759 if (bChgSiz && (m_bResizeFreeAllowed || m_bResizePropAllowed)) {
1760 Fraction aWdt(nSizX,aRect.Right()-aRect.Left());
1761 Fraction aHgt(nSizY,aRect.Bottom()-aRect.Top());
1762 Point aRef(ImpGetPoint(aRect,eSizePoint));
1764 if(GetSdrPageView())
1766 GetSdrPageView()->PagePosToLogic(aRef);
1769 ResizeMultMarkedObj(aRef, aWdt, aHgt, bChgWdh, bChgHgt);
1772 // rotate
1773 if (bRotate && (m_bRotateFreeAllowed || m_bRotate90Allowed)) {
1774 Point aRef(nRotateX,nRotateY);
1776 if(GetSdrPageView())
1778 GetSdrPageView()->PagePosToLogic(aRef);
1781 RotateMarkedObj(aRef,nRotateAngle);
1784 // set rotation point position
1785 if(bModeIsRotate && (nRotateX != nOldRotateX || nRotateY != nOldRotateY))
1787 Point aNewRef1(nRotateX, nRotateY);
1789 if(GetSdrPageView())
1791 GetSdrPageView()->PagePosToLogic(aNewRef1);
1794 SetRef1(aNewRef1);
1797 // shear
1798 if (bShear && m_bShearAllowed) {
1799 Point aRef(nShearX,nShearY);
1801 if(GetSdrPageView())
1803 GetSdrPageView()->PagePosToLogic(aRef);
1806 ShearMarkedObj(aRef,nShearAngle,bShearVert);
1808 // #i74358#
1809 // ShearMarkedObj creates a linear combination of the existing transformation and
1810 // the new shear to apply. If the object is already transformed (e.g. rotated) the
1811 // linear combination will not decompose to the same start values again, but to a
1812 // new combination. Thus it makes no sense to check if the wanted shear is reached
1813 // or not. Taking out.
1816 // change position
1817 if (bChgPos && m_bMoveAllowed) {
1818 MoveMarkedObj(Size(nPosDX,nPosDY));
1821 const size_t nMarkCount=rMarkList.GetMarkCount();
1822 // protect position
1823 if(const SfxBoolItem *pPoolItem = rAttr.GetItemIfSet(SID_ATTR_TRANSFORM_PROTECT_POS))
1825 const bool bProtPos(pPoolItem->GetValue());
1826 bool bChanged(false);
1828 for(size_t i = 0; i < nMarkCount; ++i)
1830 pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
1832 if(pObj->IsMoveProtect() != bProtPos)
1834 bChanged = true;
1835 pObj->SetMoveProtect(bProtPos);
1837 if(bProtPos)
1839 pObj->SetResizeProtect(true);
1844 if(bChanged)
1846 m_bMoveProtect = bProtPos;
1848 if(bProtPos)
1850 m_bResizeProtect = true;
1853 // #i77187# there is no simple method to get the toolbars updated
1854 // in the application. The App is listening to selection change and i
1855 // will use it here (even if not true). It's acceptable since changing
1856 // this model data is pretty rare and only possible using the F4 dialog
1857 MarkListHasChanged();
1861 if(!m_bMoveProtect)
1863 // protect size
1864 if(const SfxBoolItem *pPoolItem = rAttr.GetItemIfSet(SID_ATTR_TRANSFORM_PROTECT_SIZE))
1866 const bool bProtSize(pPoolItem->GetValue());
1867 bool bChanged(false);
1869 for(size_t i = 0; i < nMarkCount; ++i)
1871 pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
1873 if(pObj->IsResizeProtect() != bProtSize)
1875 bChanged = true;
1876 pObj->SetResizeProtect(bProtSize);
1880 if(bChanged)
1882 m_bResizeProtect = bProtSize;
1884 // #i77187# see above
1885 MarkListHasChanged();
1890 EndUndo();
1894 bool SdrEditView::IsAlignPossible() const
1895 { // at least two selected objects, at least one of them movable
1896 ForcePossibilities();
1897 const SdrMarkList& rMarkList = GetMarkedObjectList();
1898 const size_t nCount=rMarkList.GetMarkCount();
1899 if (nCount==0) return false; // nothing selected!
1900 if (nCount==1) return m_bMoveAllowed; // align single object to page
1901 return m_bOneOrMoreMovable; // otherwise: MarkCount>=2
1904 void SdrEditView::AlignMarkedObjects(SdrHorAlign eHor, SdrVertAlign eVert)
1906 if (eHor==SdrHorAlign::NONE && eVert==SdrVertAlign::NONE)
1907 return;
1909 const SdrMarkList& rMarkList = GetMarkedObjectList();
1910 rMarkList.ForceSort();
1911 if (!rMarkList.GetMarkCount())
1912 return;
1914 const bool bUndo = IsUndoEnabled();
1915 if( bUndo )
1917 EndTextEditCurrentView();
1918 OUString aStr(rMarkList.GetMarkDescription());
1919 if (eHor==SdrHorAlign::NONE)
1921 switch (eVert)
1923 case SdrVertAlign::Top:
1924 aStr = ImpGetDescriptionString(STR_EditAlignVTop);
1925 break;
1926 case SdrVertAlign::Bottom:
1927 aStr = ImpGetDescriptionString(STR_EditAlignVBottom);
1928 break;
1929 case SdrVertAlign::Center:
1930 aStr = ImpGetDescriptionString(STR_EditAlignVCenter);
1931 break;
1932 default: break;
1935 else if (eVert==SdrVertAlign::NONE)
1937 switch (eHor)
1939 case SdrHorAlign::Left:
1940 aStr = ImpGetDescriptionString(STR_EditAlignHLeft);
1941 break;
1942 case SdrHorAlign::Right:
1943 aStr = ImpGetDescriptionString(STR_EditAlignHRight);
1944 break;
1945 case SdrHorAlign::Center:
1946 aStr = ImpGetDescriptionString(STR_EditAlignHCenter);
1947 break;
1948 default: break;
1951 else if (eHor==SdrHorAlign::Center && eVert==SdrVertAlign::Center)
1953 aStr = ImpGetDescriptionString(STR_EditAlignCenter);
1955 else
1957 aStr = ImpGetDescriptionString(STR_EditAlign);
1959 BegUndo(aStr);
1962 tools::Rectangle aBound;
1963 const size_t nMarkCount=rMarkList.GetMarkCount();
1964 bool bHasFixed=false;
1965 for (size_t nm=0; nm<nMarkCount; ++nm)
1967 SdrMark* pM=rMarkList.GetMark(nm);
1968 SdrObject* pObj=pM->GetMarkedSdrObj();
1969 SdrObjTransformInfoRec aInfo;
1970 pObj->TakeObjInfo(aInfo);
1971 if (!aInfo.bMoveAllowed || pObj->IsMoveProtect())
1973 tools::Rectangle aObjRect(pObj->GetSnapRect());
1974 aBound.Union(aObjRect);
1975 bHasFixed=true;
1978 if (!bHasFixed)
1980 if (nMarkCount==1)
1981 { // align single object to page
1982 const SdrObject* pObj=rMarkList.GetMark(0)->GetMarkedSdrObj();
1983 const SdrPage* pPage=pObj->getSdrPageFromSdrObject();
1984 const SdrPageGridFrameList* pGFL=pPage->GetGridFrameList(rMarkList.GetMark(0)->GetPageView(),&(pObj->GetSnapRect()));
1985 const SdrPageGridFrame* pFrame=nullptr;
1986 if (pGFL!=nullptr && pGFL->GetCount()!=0)
1987 { // Writer
1988 pFrame=&((*pGFL)[0]);
1991 if (pFrame!=nullptr)
1992 { // Writer
1993 aBound=pFrame->GetUserArea();
1995 else
1997 aBound=tools::Rectangle(pPage->GetLeftBorder(),pPage->GetUpperBorder(),
1998 pPage->GetWidth()-pPage->GetRightBorder(),
1999 pPage->GetHeight()-pPage->GetLowerBorder());
2002 else
2004 aBound=GetMarkedObjRect();
2007 Point aCenter(aBound.Center());
2008 for (size_t nm=0; nm<nMarkCount; ++nm)
2010 SdrMark* pM=rMarkList.GetMark(nm);
2011 SdrObject* pObj=pM->GetMarkedSdrObj();
2012 SdrObjTransformInfoRec aInfo;
2013 pObj->TakeObjInfo(aInfo);
2014 if (aInfo.bMoveAllowed && !pObj->IsMoveProtect())
2016 tools::Long nXMov=0;
2017 tools::Long nYMov=0;
2018 tools::Rectangle aObjRect(pObj->GetSnapRect());
2019 switch (eVert)
2021 case SdrVertAlign::Top : nYMov=aBound.Top() -aObjRect.Top() ; break;
2022 case SdrVertAlign::Bottom: nYMov=aBound.Bottom()-aObjRect.Bottom() ; break;
2023 case SdrVertAlign::Center: nYMov=aCenter.Y() -aObjRect.Center().Y(); break;
2024 default: break;
2026 switch (eHor)
2028 case SdrHorAlign::Left : nXMov=aBound.Left() -aObjRect.Left() ; break;
2029 case SdrHorAlign::Right : nXMov=aBound.Right() -aObjRect.Right() ; break;
2030 case SdrHorAlign::Center: nXMov=aCenter.X() -aObjRect.Center().X(); break;
2031 default: break;
2033 if (nXMov!=0 || nYMov!=0)
2035 // SdrEdgeObj needs an extra SdrUndoGeoObj since the
2036 // connections may need to be saved
2037 if( bUndo )
2039 if( dynamic_cast<SdrEdgeObj*>(pObj) )
2041 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
2044 AddUndo(GetModel().GetSdrUndoFactory().CreateUndoMoveObject(*pObj,Size(nXMov,nYMov)));
2047 pObj->Move(Size(nXMov,nYMov));
2052 if( bUndo )
2053 EndUndo();
2056 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */