1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "svddrgm1.hxx"
23 #include <o3tl/numeric.hxx>
24 #include <osl/diagnose.h>
26 #include <vcl/canvastools.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/settings.hxx>
29 #include <vcl/ptrstyle.hxx>
30 #include <svx/xpoly.hxx>
31 #include <svx/svdtrans.hxx>
32 #include <svx/svdundo.hxx>
33 #include <svx/svdmark.hxx>
34 #include <svx/svdpagv.hxx>
35 #include <svx/svddrgv.hxx>
36 #include <svx/svdograf.hxx>
37 #include <svx/strings.hrc>
38 #include <svx/dialmgr.hxx>
39 #include <svx/sdgcpitm.hxx>
40 #include <svx/sdooitm.hxx>
41 #include <svx/sdtagitm.hxx>
42 #include <basegfx/polygon/b2dpolygon.hxx>
43 #include <basegfx/polygon/b2dpolygontools.hxx>
44 #include <svx/sdr/overlay/overlaymanager.hxx>
45 #include <sdr/overlay/overlayrollingrectangle.hxx>
46 #include <svx/sdrpagewindow.hxx>
47 #include <svx/sdrpaintwindow.hxx>
48 #include <basegfx/matrix/b2dhommatrix.hxx>
49 #include <basegfx/polygon/b2dpolypolygontools.hxx>
50 #include <svx/sdr/contact/viewcontact.hxx>
51 #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
52 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
53 #include <svx/sdr/contact/objectcontact.hxx>
54 #include <svx/svditer.hxx>
55 #include <svx/svdopath.hxx>
56 #include <svx/polypolygoneditor.hxx>
57 #include <drawinglayer/primitive2d/PolygonMarkerPrimitive2D.hxx>
58 #include <drawinglayer/primitive2d/PolyPolygonSelectionPrimitive2D.hxx>
59 #include <drawinglayer/primitive2d/PolyPolygonMarkerPrimitive2D.hxx>
60 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
61 #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
62 #include <sdr/primitive2d/sdrattributecreator.hxx>
63 #include <sdr/primitive2d/sdrdecompositiontools.hxx>
64 #include <sdr/primitive2d/sdrprimitivetools.hxx>
65 #include <basegfx/matrix/b2dhommatrixtools.hxx>
66 #include <drawinglayer/attribute/sdrlineattribute.hxx>
67 #include <drawinglayer/attribute/sdrlinestartendattribute.hxx>
68 #include <svl/itempool.hxx>
69 #include <svtools/optionsdrawinglayer.hxx>
70 #include <officecfg/Office/Common.hxx>
71 #include <comphelper/lok.hxx>
76 SdrDragEntry::SdrDragEntry()
77 : mbAddToTransparent(false)
81 SdrDragEntry::~SdrDragEntry()
86 SdrDragEntryPolyPolygon::SdrDragEntryPolyPolygon(basegfx::B2DPolyPolygon aOriginalPolyPolygon
)
87 : maOriginalPolyPolygon(std::move(aOriginalPolyPolygon
))
91 SdrDragEntryPolyPolygon::~SdrDragEntryPolyPolygon()
95 drawinglayer::primitive2d::Primitive2DContainer
SdrDragEntryPolyPolygon::createPrimitive2DSequenceInCurrentState(SdrDragMethod
& rDragMethod
, bool IsDragSizeValid
)
97 drawinglayer::primitive2d::Primitive2DContainer aRetval
;
99 if(maOriginalPolyPolygon
.count())
101 basegfx::B2DPolyPolygon
aCopy(maOriginalPolyPolygon
);
103 rDragMethod
.applyCurrentTransformationToPolyPolygon(aCopy
);
104 basegfx::BColor
aColA(SvtOptionsDrawinglayer::GetStripeColorA().getBColor());
105 basegfx::BColor
aColB(SvtOptionsDrawinglayer::GetStripeColorB().getBColor());
106 const double fStripeLength(officecfg::Office::Common::Drawinglayer::StripeLength::get());
108 if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
110 aColA
= aColB
= Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
115 aRetval
[0] = new drawinglayer::primitive2d::PolyPolygonMarkerPrimitive2D(
121 basegfx::BColor aHilightColor
;
123 aHilightColor
= SvtOptionsDrawinglayer::getHilightColor().getBColor();
125 aHilightColor
= basegfx::BColor(1.0, 0, 0);
127 const double fTransparence(SvtOptionsDrawinglayer::GetTransparentSelectionPercent() * 0.01);
128 aRetval
[1] = new drawinglayer::primitive2d::PolyPolygonSelectionPrimitive2D(
140 SdrDragEntrySdrObject::SdrDragEntrySdrObject(
141 const SdrObject
& rOriginal
,
143 : maOriginal(rOriginal
),
146 // add SdrObject parts to transparent overlay stuff
147 setAddToTransparent(true);
150 SdrDragEntrySdrObject::~SdrDragEntrySdrObject()
154 void SdrDragEntrySdrObject::prepareCurrentState(SdrDragMethod
& rDragMethod
)
156 // for the moment, i need to re-create the clone in all cases. I need to figure
157 // out when clone and original have the same class, so that i can use operator=
164 mxClone
= maOriginal
.getFullDragClone();
166 // apply original transformation, implemented at the DragMethods
167 rDragMethod
.applyCurrentTransformationToSdrObject(*mxClone
);
171 drawinglayer::primitive2d::Primitive2DContainer
SdrDragEntrySdrObject::createPrimitive2DSequenceInCurrentState(SdrDragMethod
&, bool /* IsDragSizeValid */)
173 const SdrObject
* pSource
= &maOriginal
;
175 if(mbModify
&& mxClone
)
177 // choose source for geometry data
178 pSource
= mxClone
.get();
181 // use the view-independent primitive representation (without
182 // evtl. GridOffset, that may be applied to the DragEntry individually)
183 drawinglayer::primitive2d::Primitive2DContainer xRetval
;
184 pSource
->GetViewContact().getViewIndependentPrimitive2DContainer(xRetval
);
189 SdrDragEntryPrimitive2DSequence::SdrDragEntryPrimitive2DSequence(
190 drawinglayer::primitive2d::Primitive2DContainer
&& rSequence
)
191 : maPrimitive2DSequence(std::move(rSequence
))
193 // add parts to transparent overlay stuff if necessary
194 setAddToTransparent(true);
197 SdrDragEntryPrimitive2DSequence::~SdrDragEntryPrimitive2DSequence()
201 drawinglayer::primitive2d::Primitive2DContainer
SdrDragEntryPrimitive2DSequence::createPrimitive2DSequenceInCurrentState(SdrDragMethod
& rDragMethod
, bool /* IsDragSizeValid */)
203 return drawinglayer::primitive2d::Primitive2DContainer
{
204 new drawinglayer::primitive2d::TransformPrimitive2D(
205 rDragMethod
.getCurrentTransformation(),
206 drawinglayer::primitive2d::Primitive2DContainer(maPrimitive2DSequence
))
210 SdrDragEntryPointGlueDrag::SdrDragEntryPointGlueDrag(std::vector
< basegfx::B2DPoint
>&& rPositions
, bool bIsPointDrag
)
211 : maPositions(std::move(rPositions
)),
212 mbIsPointDrag(bIsPointDrag
)
214 // add SdrObject parts to transparent overlay stuff
215 setAddToTransparent(true);
218 SdrDragEntryPointGlueDrag::~SdrDragEntryPointGlueDrag()
222 drawinglayer::primitive2d::Primitive2DContainer
SdrDragEntryPointGlueDrag::createPrimitive2DSequenceInCurrentState(SdrDragMethod
& rDragMethod
, bool /* IsDragSizeValid */)
224 drawinglayer::primitive2d::Primitive2DContainer aRetval
;
226 if(!maPositions
.empty())
228 basegfx::B2DPolygon aPolygon
;
230 for(auto const & a
: maPositions
)
235 basegfx::B2DPolyPolygon
aPolyPolygon(aPolygon
);
237 rDragMethod
.applyCurrentTransformationToPolyPolygon(aPolyPolygon
);
239 const basegfx::B2DPolygon
aTransformed(aPolyPolygon
.getB2DPolygon(0));
240 std::vector
< basegfx::B2DPoint
> aTransformedPositions
;
242 aTransformedPositions
.reserve(aTransformed
.count());
244 for(sal_uInt32 a
= 0; a
< aTransformed
.count(); a
++)
246 aTransformedPositions
.push_back(aTransformed
.getB2DPoint(a
));
251 basegfx::BColor
aColor(SvtOptionsDrawinglayer::GetStripeColorA().getBColor());
253 if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
255 aColor
= Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
258 aRetval
= drawinglayer::primitive2d::Primitive2DContainer
{
259 new drawinglayer::primitive2d::MarkerArrayPrimitive2D(std::move(aTransformedPositions
),
260 drawinglayer::primitive2d::createDefaultCross_3x3(aColor
))
265 aRetval
= drawinglayer::primitive2d::Primitive2DContainer
{
266 new drawinglayer::primitive2d::MarkerArrayPrimitive2D(std::move(aTransformedPositions
),
267 SdrHdl::createGluePointBitmap())
276 void SdrDragMethod::resetSdrDragEntries()
278 // clear entries; creation is on demand
279 clearSdrDragEntries();
282 basegfx::B2DRange
SdrDragMethod::getCurrentRange() const
284 return maOverlayObjectList
.getBaseRange();
287 void SdrDragMethod::clearSdrDragEntries()
289 maSdrDragEntries
.clear();
292 void SdrDragMethod::addSdrDragEntry(std::unique_ptr
<SdrDragEntry
> pNew
)
295 maSdrDragEntries
.push_back(std::move(pNew
));
298 void SdrDragMethod::createSdrDragEntries()
300 if(!(getSdrDragView().GetSdrPageView() && getSdrDragView().GetSdrPageView()->HasMarkedObjPageView()))
303 if(getSdrDragView().IsDraggingPoints())
305 createSdrDragEntries_PointDrag();
307 else if(getSdrDragView().IsDraggingGluePoints())
309 createSdrDragEntries_GlueDrag();
313 if(getSolidDraggingActive())
315 createSdrDragEntries_SolidDrag();
319 createSdrDragEntries_PolygonDrag();
324 void SdrDragMethod::createSdrDragEntryForSdrObject(const SdrObject
& rOriginal
)
326 // add full object drag; Clone() at the object has to work
328 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntrySdrObject(rOriginal
, true/*bModify*/)));
331 void SdrDragMethod::insertNewlyCreatedOverlayObjectForSdrDragMethod(
332 std::unique_ptr
<sdr::overlay::OverlayObject
> pOverlayObject
,
333 const sdr::contact::ObjectContact
& rObjectContact
,
334 sdr::overlay::OverlayManager
& rOverlayManager
)
336 // check if we have an OverlayObject
342 // add to OverlayManager
343 rOverlayManager
.add(*pOverlayObject
);
345 // Add GridOffset for non-linear ViewToDevice transformation (calc)
346 if(rObjectContact
.supportsGridOffsets())
348 const basegfx::B2DRange
& rNewRange(pOverlayObject
->getBaseRange());
350 if(!rNewRange
.isEmpty())
352 basegfx::B2DVector
aOffset(0.0, 0.0);
353 rObjectContact
.calculateGridOffsetForB2DRange(aOffset
, rNewRange
);
355 if(!aOffset
.equalZero())
357 pOverlayObject
->setOffset(aOffset
);
362 // add to local OverlayObjectList - ownership change (!)
363 maOverlayObjectList
.append(std::move(pOverlayObject
));
366 void SdrDragMethod::createSdrDragEntries_SolidDrag()
368 const SdrMarkList
& rMarkList
= getSdrDragView().GetMarkedObjectList();
369 const size_t nMarkCount(rMarkList
.GetMarkCount());
370 SdrPageView
* pPV
= getSdrDragView().GetSdrPageView();
375 for(size_t a
= 0; a
< nMarkCount
; ++a
)
377 SdrMark
* pM
= rMarkList
.GetMark(a
);
379 if(pM
->GetPageView() == pPV
)
381 const SdrObject
* pObject
= pM
->GetMarkedSdrObj();
385 if(pPV
->PageWindowCount())
387 SdrObjListIter
aIter(*pObject
);
389 while(aIter
.IsMore())
391 SdrObject
* pCandidate
= aIter
.Next();
395 const bool bSuppressFullDrag(!pCandidate
->supportsFullDrag());
396 bool bAddWireframe(bSuppressFullDrag
);
398 if(!bAddWireframe
&& !pCandidate
->HasLineStyle())
400 // add wireframe for objects without outline
401 bAddWireframe
= true;
404 if(!bSuppressFullDrag
)
406 // add full object drag; Clone() at the object has to work
408 createSdrDragEntryForSdrObject(*pCandidate
);
413 // when dragging a 50% transparent copy of a filled or not filled object without
414 // outline, this is normally hard to see. Add extra wireframe in that case. This
415 // works nice e.g. with text frames etc.
416 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntryPolyPolygon(pCandidate
->TakeXorPoly())));
426 void SdrDragMethod::createSdrDragEntries_PolygonDrag()
428 const SdrMarkList
& rMarkList
= getSdrDragView().GetMarkedObjectList();
429 const size_t nMarkCount(rMarkList
.GetMarkCount());
430 bool bNoPolygons(getSdrDragView().IsNoDragXorPolys() || nMarkCount
> SdrDragView::GetDragXorPolyLimit());
431 basegfx::B2DPolyPolygon aResult
;
432 sal_uInt32
nPointCount(0);
434 for(size_t a
= 0; !bNoPolygons
&& a
< nMarkCount
; ++a
)
436 SdrMark
* pM
= rMarkList
.GetMark(a
);
438 if(pM
->GetPageView() == getSdrDragView().GetSdrPageView())
440 const basegfx::B2DPolyPolygon
aNewPolyPolygon(pM
->GetMarkedSdrObj()->TakeXorPoly());
442 for(auto const& rPolygon
: aNewPolyPolygon
)
444 nPointCount
+= rPolygon
.count();
447 if(nPointCount
> SdrDragView::GetDragXorPointLimit())
454 aResult
.append(aNewPolyPolygon
);
461 const tools::Rectangle
aR(getSdrDragView().GetSdrPageView()->MarkSnap());
462 const basegfx::B2DRange aNewRectangle
= vcl::unotools::b2DRectangleFromRectangle(aR
);
463 basegfx::B2DPolygon
aNewPolygon(basegfx::utils::createPolygonFromRect(aNewRectangle
));
465 aResult
= basegfx::B2DPolyPolygon(basegfx::utils::expandToCurve(aNewPolygon
));
470 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntryPolyPolygon(std::move(aResult
))));
474 void SdrDragMethod::createSdrDragEntries_PointDrag()
476 const SdrMarkList
& rMarkList
= getSdrDragView().GetMarkedObjectList();
477 const size_t nMarkCount(rMarkList
.GetMarkCount());
478 std::vector
< basegfx::B2DPoint
> aPositions
;
480 for(size_t nm
= 0; nm
< nMarkCount
; ++nm
)
482 SdrMark
* pM
= rMarkList
.GetMark(nm
);
484 if(pM
->GetPageView() == getSdrDragView().GetSdrPageView())
486 const SdrUShortCont
& rPts
= pM
->GetMarkedPoints();
490 const SdrObject
* pObj
= pM
->GetMarkedSdrObj();
491 const SdrPathObj
* pPath
= dynamic_cast< const SdrPathObj
* >(pObj
);
495 const basegfx::B2DPolyPolygon
& aPathXPP
= pPath
->GetPathPoly();
499 for(const sal_uInt16 nObjPt
: rPts
)
501 sal_uInt32 nPolyNum
, nPointNum
;
503 if(sdr::PolyPolygonEditor::GetRelativePolyPoint(aPathXPP
, nObjPt
, nPolyNum
, nPointNum
))
505 aPositions
.push_back(aPathXPP
.getB2DPolygon(nPolyNum
).getB2DPoint(nPointNum
));
514 if(!aPositions
.empty())
516 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntryPointGlueDrag(std::move(aPositions
), true)));
520 void SdrDragMethod::createSdrDragEntries_GlueDrag()
522 const SdrMarkList
& rMarkList
= getSdrDragView().GetMarkedObjectList();
523 const size_t nMarkCount(rMarkList
.GetMarkCount());
524 std::vector
< basegfx::B2DPoint
> aPositions
;
526 for(size_t nm
= 0; nm
< nMarkCount
; ++nm
)
528 SdrMark
* pM
= rMarkList
.GetMark(nm
);
530 if(pM
->GetPageView() == getSdrDragView().GetSdrPageView())
532 const SdrUShortCont
& rPts
= pM
->GetMarkedGluePoints();
536 const SdrObject
* pObj
= pM
->GetMarkedSdrObj();
537 const SdrGluePointList
* pGPL
= pObj
->GetGluePointList();
541 for(const sal_uInt16 nObjPt
: rPts
)
543 const sal_uInt16
nGlueNum(pGPL
->FindGluePoint(nObjPt
));
545 if(SDRGLUEPOINT_NOTFOUND
!= nGlueNum
)
547 const Point
aPoint((*pGPL
)[nGlueNum
].GetAbsolutePos(*pObj
));
548 aPositions
.emplace_back(aPoint
.X(), aPoint
.Y());
556 if(!aPositions
.empty())
558 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntryPointGlueDrag(std::move(aPositions
), false)));
562 OUString
SdrDragMethod::ImpGetDescriptionStr(TranslateId pStrCacheID
) const
564 ImpGetDescriptionOptions nOpt
=ImpGetDescriptionOptions::NONE
;
565 if (IsDraggingPoints()) {
566 nOpt
=ImpGetDescriptionOptions::POINTS
;
567 } else if (IsDraggingGluePoints()) {
568 nOpt
=ImpGetDescriptionOptions::GLUEPOINTS
;
570 return getSdrDragView().ImpGetDescriptionString(pStrCacheID
, nOpt
);
573 SdrObject
* SdrDragMethod::GetDragObj() const
575 SdrObject
* pObj
=nullptr;
576 if (getSdrDragView().mpDragHdl
!=nullptr) pObj
=getSdrDragView().mpDragHdl
->GetObj();
577 if (pObj
==nullptr) pObj
=getSdrDragView().mpMarkedObj
;
581 SdrPageView
* SdrDragMethod::GetDragPV() const
583 SdrPageView
* pPV
=nullptr;
584 if (getSdrDragView().mpDragHdl
!=nullptr) pPV
=getSdrDragView().mpDragHdl
->GetPageView();
585 if (pPV
==nullptr) pPV
=getSdrDragView().mpMarkedPV
;
589 void SdrDragMethod::applyCurrentTransformationToSdrObject(SdrObject
& rTarget
)
591 // the original applies the transformation using TRGetBaseGeometry/TRSetBaseGeometry.
592 // Later this should be the only needed one for linear transforms (not for SdrDragCrook and
593 // SdrDragDistort, those are NOT linear). Currently, this can not yet be used since the
594 // special handling of rotate/mirror due to the not-being-able to handle it in the old
595 // drawinglayer stuff. Text would currently not correctly be mirrored in the preview.
596 basegfx::B2DHomMatrix aObjectTransform
;
597 basegfx::B2DPolyPolygon aObjectPolyPolygon
;
598 bool bPolyUsed(rTarget
.TRGetBaseGeometry(aObjectTransform
, aObjectPolyPolygon
));
600 // apply transform to object transform
601 aObjectTransform
*= getCurrentTransformation();
605 // do something special since the object size is in the polygon
606 // break up matrix to get the scale
607 const basegfx::utils::B2DHomMatrixBufferedDecompose
aTmpDecomp(aObjectTransform
);
609 // get polygon's position and size
610 const basegfx::B2DRange
aPolyRange(aObjectPolyPolygon
.getB2DRange());
612 // get the scaling factors (do not mirror, this is in the object transformation)
613 const double fScaleX(fabs(aTmpDecomp
.getScale().getX()) / (basegfx::fTools::equalZero(aPolyRange
.getWidth()) ? 1.0 : aPolyRange
.getWidth()));
614 const double fScaleY(fabs(aTmpDecomp
.getScale().getY()) / (basegfx::fTools::equalZero(aPolyRange
.getHeight()) ? 1.0 : aPolyRange
.getHeight()));
616 // prepare transform matrix for polygon
617 basegfx::B2DHomMatrix
aPolyTransform(
618 basegfx::utils::createTranslateB2DHomMatrix(
619 -aPolyRange
.getMinX(),
620 -aPolyRange
.getMinY()));
621 aPolyTransform
.scale(fScaleX
, fScaleY
);
623 // transform the polygon
624 aObjectPolyPolygon
.transform(aPolyTransform
);
627 rTarget
.TRSetBaseGeometry(getCurrentTransformation() * aObjectTransform
, aObjectPolyPolygon
);
630 void SdrDragMethod::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon
& rTarget
)
632 // original uses CurrentTransformation
633 rTarget
.transform(getCurrentTransformation());
636 SdrDragMethod::SdrDragMethod(SdrDragView
& rNewView
)
637 : mrSdrDragView(rNewView
),
639 mbSolidDraggingActive(getSdrDragView().IsSolidDragging()),
640 mbShiftPressed(false)
642 if(mbSolidDraggingActive
&& Application::GetSettings().GetStyleSettings().GetHighContrastMode())
644 // fallback to wireframe when high contrast is used
645 mbSolidDraggingActive
= false;
649 SdrDragMethod::~SdrDragMethod()
651 clearSdrDragEntries();
654 void SdrDragMethod::Show(bool IsValidSize
)
656 getSdrDragView().ShowDragObj(IsValidSize
);
659 void SdrDragMethod::Hide()
661 getSdrDragView().HideDragObj();
664 basegfx::B2DHomMatrix
SdrDragMethod::getCurrentTransformation() const
666 return basegfx::B2DHomMatrix();
669 void SdrDragMethod::CancelSdrDrag()
674 typedef std::map
< const SdrObject
*, SdrObject
* > SdrObjectAndCloneMap
;
676 void SdrDragMethod::CreateOverlayGeometry(
677 sdr::overlay::OverlayManager
& rOverlayManager
,
678 const sdr::contact::ObjectContact
& rObjectContact
, bool bIsGeometrySizeValid
)
680 // We do client-side object manipulation with the Kit API
681 if (comphelper::LibreOfficeKit::isActive())
684 // create SdrDragEntries on demand
685 if(maSdrDragEntries
.empty())
687 createSdrDragEntries();
690 // if there are entries, derive OverlayObjects from the entries, including
691 // modification from current interactive state
692 if(!maSdrDragEntries
.empty())
694 // #i54102# SdrDragEntrySdrObject creates clones of SdrObjects as base for creating the needed
695 // primitives, holding the original and the clone. If connectors (Edges) are involved,
696 // the cloned connectors need to be connected to the cloned SdrObjects (after cloning
697 // they are connected to the original SdrObjects). To do so, trigger the preparation
698 // steps for SdrDragEntrySdrObject, save an association of (orig, clone) in a helper
699 // and evtl. remember if it was an edge
700 SdrObjectAndCloneMap aOriginalAndClones
;
701 std::vector
< SdrEdgeObj
* > aEdges
;
703 // #i54102# execute prepareCurrentState for all SdrDragEntrySdrObject, register pair of original and
704 // clone, remember edges
705 for(auto const & a
: maSdrDragEntries
)
707 SdrDragEntrySdrObject
* pSdrDragEntrySdrObject
= dynamic_cast< SdrDragEntrySdrObject
*>(a
.get());
709 if(pSdrDragEntrySdrObject
)
711 pSdrDragEntrySdrObject
->prepareCurrentState(*this);
713 SdrEdgeObj
* pSdrEdgeObj
= dynamic_cast< SdrEdgeObj
* >(pSdrDragEntrySdrObject
->getClone());
717 aEdges
.push_back(pSdrEdgeObj
);
720 if(pSdrDragEntrySdrObject
->getClone())
722 aOriginalAndClones
[&pSdrDragEntrySdrObject
->getOriginal()] = pSdrDragEntrySdrObject
->getClone();
727 // #i54102# if there are edges, reconnect their ends to the corresponding clones (if found)
728 for(SdrEdgeObj
* pSdrEdgeObj
: aEdges
)
730 SdrObject
* pConnectedTo
= pSdrEdgeObj
->GetConnectedNode(true);
734 SdrObjectAndCloneMap::iterator aEntry
= aOriginalAndClones
.find(pConnectedTo
);
736 if(aEntry
!= aOriginalAndClones
.end())
738 pSdrEdgeObj
->ConnectToNode(true, aEntry
->second
);
742 pConnectedTo
= pSdrEdgeObj
->GetConnectedNode(false);
746 SdrObjectAndCloneMap::iterator aEntry
= aOriginalAndClones
.find(pConnectedTo
);
748 if(aEntry
!= aOriginalAndClones
.end())
750 pSdrEdgeObj
->ConnectToNode(false, aEntry
->second
);
755 // collect primitives for visualisation
756 drawinglayer::primitive2d::Primitive2DContainer aResult
;
757 drawinglayer::primitive2d::Primitive2DContainer aResultTransparent
;
759 for(auto & pCandidate
: maSdrDragEntries
)
761 const drawinglayer::primitive2d::Primitive2DContainer
aCandidateResult(
762 pCandidate
->createPrimitive2DSequenceInCurrentState(*this, bIsGeometrySizeValid
));
764 if(!aCandidateResult
.empty())
766 if(pCandidate
->getAddToTransparent())
768 aResultTransparent
.append(aCandidateResult
);
772 aResult
.append(aCandidateResult
);
777 if(DoAddConnectorOverlays())
779 drawinglayer::primitive2d::Primitive2DContainer
aConnectorOverlays(AddConnectorOverlays());
781 if(!aConnectorOverlays
.empty())
783 // add connector overlays to transparent part
784 aResultTransparent
.append(std::move(aConnectorOverlays
));
790 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(
791 new sdr::overlay::OverlayPrimitive2DSequenceObject(
792 std::move(aResult
)));
794 insertNewlyCreatedOverlayObjectForSdrDragMethod(
795 std::move(pNewOverlayObject
),
800 if(!aResultTransparent
.empty())
802 aResultTransparent
= drawinglayer::primitive2d::Primitive2DContainer
{
803 new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(std::move(aResultTransparent
), 0.5)
806 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(
807 new sdr::overlay::OverlayPrimitive2DSequenceObject(
808 std::move(aResultTransparent
)));
810 insertNewlyCreatedOverlayObjectForSdrDragMethod(
811 std::move(pNewOverlayObject
),
817 // add DragStripes if necessary (help lines cross the page when dragging)
818 if(!getSdrDragView().IsDragStripes())
821 tools::Rectangle aActionRectangle
;
822 getSdrDragView().TakeActionRect(aActionRectangle
);
824 const basegfx::B2DPoint
aTopLeft(aActionRectangle
.Left(), aActionRectangle
.Top());
825 const basegfx::B2DPoint
aBottomRight(aActionRectangle
.Right(), aActionRectangle
.Bottom());
826 std::unique_ptr
<sdr::overlay::OverlayRollingRectangleStriped
> pNew(
827 new sdr::overlay::OverlayRollingRectangleStriped(
833 insertNewlyCreatedOverlayObjectForSdrDragMethod(
839 void SdrDragMethod::destroyOverlayGeometry()
841 maOverlayObjectList
.clear();
844 bool SdrDragMethod::DoAddConnectorOverlays()
846 // these conditions are translated from SdrDragView::ImpDrawEdgeXor
847 const SdrMarkList
& rMarkedNodes
= getSdrDragView().GetEdgesOfMarkedNodes();
849 if(!rMarkedNodes
.GetMarkCount())
854 if(getSdrDragView().IsDraggingPoints() || getSdrDragView().IsDraggingGluePoints())
859 if(!getMoveOnly() && !(
860 dynamic_cast<const SdrDragMove
*>(this) != nullptr || dynamic_cast<const SdrDragResize
*>(this) != nullptr ||
861 dynamic_cast<const SdrDragRotate
*>(this) != nullptr || dynamic_cast<const SdrDragMirror
*>(this) != nullptr ))
866 // one more migrated from SdrEdgeObj::NspToggleEdgeXor
867 if( dynamic_cast< const SdrDragObjOwn
* >(this) != nullptr || dynamic_cast< const SdrDragMovHdl
* >(this) != nullptr )
875 drawinglayer::primitive2d::Primitive2DContainer
SdrDragMethod::AddConnectorOverlays()
877 drawinglayer::primitive2d::Primitive2DContainer aRetval
;
878 const bool bDetail(getMoveOnly());
879 const SdrMarkList
& rMarkedNodes
= getSdrDragView().GetEdgesOfMarkedNodes();
881 for(size_t a
= 0; a
< rMarkedNodes
.GetMarkCount(); ++a
)
883 SdrMark
* pEM
= rMarkedNodes
.GetMark(a
);
885 if(pEM
&& pEM
->GetMarkedSdrObj())
887 SdrEdgeObj
* pEdge
= dynamic_cast< SdrEdgeObj
* >(pEM
->GetMarkedSdrObj());
891 basegfx::B2DPolygon
aEdgePolygon(pEdge
->ImplAddConnectorOverlay(*this, pEM
->IsCon1(), pEM
->IsCon2(), bDetail
));
893 if(aEdgePolygon
.count())
895 // this polygon is a temporary calculated connector path, so it is not possible to fetch
896 // the needed primitives directly from the pEdge object which does not get changed. If full
897 // drag is on, use the SdrObjects ItemSet to create an adequate representation
898 bool bUseSolidDragging(getSolidDraggingActive());
900 if(bUseSolidDragging
)
902 // switch off solid dragging if connector is not visible
903 if(!pEdge
->HasLineStyle())
905 bUseSolidDragging
= false;
909 if(bUseSolidDragging
)
911 const SfxItemSet
& rItemSet
= pEdge
->GetMergedItemSet();
912 const drawinglayer::attribute::SdrLineAttribute
aLine(
913 drawinglayer::primitive2d::createNewSdrLineAttribute(rItemSet
));
915 if(!aLine
.isDefault())
917 const drawinglayer::attribute::SdrLineStartEndAttribute
aLineStartEnd(
918 drawinglayer::primitive2d::createNewSdrLineStartEndAttribute(
922 aRetval
.push_back(drawinglayer::primitive2d::createPolygonLinePrimitive(
930 basegfx::BColor
aColA(SvtOptionsDrawinglayer::GetStripeColorA().getBColor());
931 basegfx::BColor
aColB(SvtOptionsDrawinglayer::GetStripeColorB().getBColor());
932 const double fStripeLength(officecfg::Office::Common::Drawinglayer::StripeLength::get());
934 if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
936 aColA
= aColB
= Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
940 drawinglayer::primitive2d::Primitive2DReference
aPolyPolygonMarkerPrimitive2D(
941 new drawinglayer::primitive2d::PolygonMarkerPrimitive2D(
942 std::move(aEdgePolygon
), aColA
, aColB
, fStripeLength
));
943 aRetval
.push_back(aPolyPolygonMarkerPrimitive2D
);
954 SdrDragMovHdl::SdrDragMovHdl(SdrDragView
& rNewView
)
955 : SdrDragMethod(rNewView
)
959 void SdrDragMovHdl::createSdrDragEntries()
961 // SdrDragMovHdl does not use the default drags,
962 // but creates nothing
965 OUString
SdrDragMovHdl::GetSdrDragComment() const
967 OUString aStr
=SvxResId(STR_DragMethMovHdl
);
968 if (getSdrDragView().IsDragWithCopy()) aStr
+=SvxResId(STR_EditWithCopy
);
972 bool SdrDragMovHdl::BeginSdrDrag()
977 DragStat().SetRef1(GetDragHdl()->GetPos());
978 DragStat().SetShown(!DragStat().IsShown());
979 SdrHdlKind eKind
=GetDragHdl()->GetKind();
980 SdrHdl
* pH1
=GetHdlList().GetHdl(SdrHdlKind::Ref1
);
981 SdrHdl
* pH2
=GetHdlList().GetHdl(SdrHdlKind::Ref2
);
983 if (eKind
==SdrHdlKind::MirrorAxis
)
985 if (pH1
==nullptr || pH2
==nullptr)
987 OSL_FAIL("SdrDragMovHdl::BeginSdrDrag(): Moving the axis of reflection: reference handles not found.");
991 DragStat().SetActionRect(tools::Rectangle(pH1
->GetPos(),pH2
->GetPos()));
995 Point
aPt(GetDragHdl()->GetPos());
996 DragStat().SetActionRect(tools::Rectangle(aPt
,aPt
));
1002 void SdrDragMovHdl::MoveSdrDrag(const Point
& rNoSnapPnt
)
1004 Point
aPnt(rNoSnapPnt
);
1006 if ( !(GetDragHdl() && DragStat().CheckMinMoved(rNoSnapPnt
)))
1009 if (GetDragHdl()->GetKind()==SdrHdlKind::MirrorAxis
)
1011 SdrHdl
* pH1
=GetHdlList().GetHdl(SdrHdlKind::Ref1
);
1012 SdrHdl
* pH2
=GetHdlList().GetHdl(SdrHdlKind::Ref2
);
1014 if (pH1
==nullptr || pH2
==nullptr)
1017 if (!DragStat().IsNoSnap())
1019 tools::Long nBestXSnap
=0;
1020 tools::Long nBestYSnap
=0;
1021 bool bXSnapped
=false;
1022 bool bYSnapped
=false;
1023 Point
aDif(aPnt
-DragStat().GetStart());
1024 getSdrDragView().CheckSnap(Ref1()+aDif
,nBestXSnap
,nBestYSnap
,bXSnapped
,bYSnapped
);
1025 getSdrDragView().CheckSnap(Ref2()+aDif
,nBestXSnap
,nBestYSnap
,bXSnapped
,bYSnapped
);
1026 aPnt
.AdjustX(nBestXSnap
);
1027 aPnt
.AdjustY(nBestYSnap
);
1030 if (aPnt
!=DragStat().GetNow())
1033 DragStat().NextMove(aPnt
);
1034 Point
aDif(DragStat().GetNow()-DragStat().GetStart());
1035 pH1
->SetPos(Ref1()+aDif
);
1036 pH2
->SetPos(Ref2()+aDif
);
1038 SdrHdl
* pHM
= GetHdlList().GetHdl(SdrHdlKind::MirrorAxis
);
1044 DragStat().SetActionRect(tools::Rectangle(pH1
->GetPos(),pH2
->GetPos()));
1049 if (!DragStat().IsNoSnap()) SnapPos(aPnt
);
1052 if (getSdrDragView().IsAngleSnapEnabled())
1053 nSA
=getSdrDragView().GetSnapAngle();
1055 if (getSdrDragView().IsMirrorAllowed(true,true))
1057 if (!getSdrDragView().IsMirrorAllowed()) nSA
=4500_deg100
;
1058 if (!getSdrDragView().IsMirrorAllowed(true)) nSA
=9000_deg100
;
1061 if (getSdrDragView().IsOrtho() && nSA
!=9000_deg100
)
1066 SdrHdlKind eRef
=SdrHdlKind::Ref1
;
1068 if (GetDragHdl()->GetKind()==SdrHdlKind::Ref1
)
1069 eRef
=SdrHdlKind::Ref2
;
1071 SdrHdl
* pH
=GetHdlList().GetHdl(eRef
);
1075 Point
aRef(pH
->GetPos());
1076 Degree100 nAngle
=NormAngle36000(GetAngle(aPnt
-aRef
));
1077 Degree100 nNewAngle
=nAngle
;
1078 nNewAngle
+=nSA
/2_deg100
;
1081 nNewAngle
=NormAngle36000(nNewAngle
);
1082 double a
=toRadians(nNewAngle
-nAngle
);
1085 RotatePoint(aPnt
,aRef
,nSin
,nCos
);
1087 // eliminate rounding errors for certain values
1088 if (nSA
==9000_deg100
)
1090 if (nNewAngle
==0_deg100
|| nNewAngle
==18000_deg100
) aPnt
.setY(aRef
.Y() );
1091 if (nNewAngle
==9000_deg100
|| nNewAngle
==27000_deg100
) aPnt
.setX(aRef
.X() );
1094 if (nSA
==4500_deg100
)
1095 OrthoDistance8(aRef
,aPnt
,true);
1099 if (aPnt
!=DragStat().GetNow())
1102 DragStat().NextMove(aPnt
);
1103 GetDragHdl()->SetPos(DragStat().GetNow());
1104 SdrHdl
* pHM
= GetHdlList().GetHdl(SdrHdlKind::MirrorAxis
);
1110 DragStat().SetActionRect(tools::Rectangle(aPnt
,aPnt
));
1115 bool SdrDragMovHdl::EndSdrDrag(bool /*bCopy*/)
1119 switch (GetDragHdl()->GetKind())
1121 case SdrHdlKind::Ref1
:
1122 Ref1()=DragStat().GetNow();
1125 case SdrHdlKind::Ref2
:
1126 Ref2()=DragStat().GetNow();
1129 case SdrHdlKind::MirrorAxis
:
1130 Ref1()+=DragStat().GetNow()-DragStat().GetStart();
1131 Ref2()+=DragStat().GetNow()-DragStat().GetStart();
1141 void SdrDragMovHdl::CancelSdrDrag()
1145 SdrHdl
* pHdl
= GetDragHdl();
1147 pHdl
->SetPos(DragStat().GetRef1());
1149 SdrHdl
* pHM
= GetHdlList().GetHdl(SdrHdlKind::MirrorAxis
);
1155 PointerStyle
SdrDragMovHdl::GetSdrDragPointer() const
1157 const SdrHdl
* pHdl
= GetDragHdl();
1161 return pHdl
->GetPointer();
1164 return PointerStyle::RefHand
;
1168 SdrDragObjOwn::SdrDragObjOwn(SdrDragView
& rNewView
)
1169 : SdrDragMethod(rNewView
)
1171 const SdrObject
* pObj
= GetDragObj();
1175 // suppress full drag for some object types
1176 setSolidDraggingActive(pObj
->supportsFullDrag());
1180 SdrDragObjOwn::~SdrDragObjOwn()
1184 void SdrDragObjOwn::createSdrDragEntries()
1189 basegfx::B2DPolyPolygon aDragPolyPolygon
;
1190 bool bAddWireframe(true);
1192 if(getSolidDraggingActive())
1194 SdrPageView
* pPV
= getSdrDragView().GetSdrPageView();
1196 if(pPV
&& pPV
->PageWindowCount())
1198 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntrySdrObject(*mxClone
, false)));
1200 // potentially no wireframe needed, full drag works
1201 bAddWireframe
= false;
1207 // check for extra conditions for wireframe, e.g. no border at
1209 if(!mxClone
->HasLineStyle())
1211 bAddWireframe
= true;
1217 // use wireframe poly when full drag is off or did not work
1218 aDragPolyPolygon
= mxClone
->TakeXorPoly();
1221 // add evtl. extra DragPolyPolygon
1222 const basegfx::B2DPolyPolygon
aSpecialDragPolyPolygon(mxClone
->getSpecialDragPoly(DragStat()));
1224 if(aSpecialDragPolyPolygon
.count())
1226 aDragPolyPolygon
.append(aSpecialDragPolyPolygon
);
1229 if(aDragPolyPolygon
.count())
1231 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntryPolyPolygon(std::move(aDragPolyPolygon
))));
1235 OUString
SdrDragObjOwn::GetSdrDragComment() const
1238 // #i103058# get info string from the clone preferred, the original will
1239 // not be changed. For security, use original as fallback
1242 aStr
= mxClone
->getSpecialDragComment(DragStat());
1246 const SdrObject
* pObj
= GetDragObj();
1250 aStr
= pObj
->getSpecialDragComment(DragStat());
1256 bool SdrDragObjOwn::BeginSdrDrag()
1260 const SdrObject
* pObj
= GetDragObj();
1262 if(pObj
&& !pObj
->IsResizeProtect())
1264 if(pObj
->beginSpecialDrag(DragStat()))
1266 // create initial clone to have a start visualization
1267 mxClone
= pObj
->getFullDragClone();
1268 mxClone
->applySpecialDrag(DragStat());
1278 void SdrDragObjOwn::MoveSdrDrag(const Point
& rNoSnapPnt
)
1280 const SdrObject
* pObj
= GetDragObj();
1283 // No object to drag. Bail out.
1286 Point
aPnt(rNoSnapPnt
);
1287 SdrPageView
* pPV
= GetDragPV();
1290 // No page view available. Bail out.
1293 if(!DragStat().IsNoSnap())
1297 if(getSdrDragView().IsOrtho())
1299 if (DragStat().IsOrtho8Possible())
1301 OrthoDistance8(DragStat().GetStart(),aPnt
,getSdrDragView().IsBigOrtho());
1303 else if (DragStat().IsOrtho4Possible())
1305 OrthoDistance4(DragStat().GetStart(),aPnt
,getSdrDragView().IsBigOrtho());
1309 if (!DragStat().CheckMinMoved(rNoSnapPnt
))
1310 // Not moved by the minimum threshold. Nothing to do.
1314 DragStat().NextMove(aPnt
);
1316 // since SdrDragObjOwn currently supports no transformation of
1317 // existing SdrDragEntries but only their recreation, a recreation
1318 // after every move is needed in this mode. Delete existing
1319 // SdrDragEntries here to force their recreation in the following Show().
1320 clearSdrDragEntries();
1322 // delete current clone (after the last reference to it is deleted above)
1325 // create a new clone and modify to current drag state
1326 mxClone
= pObj
->getFullDragClone();
1327 mxClone
->applySpecialDrag(DragStat());
1329 // AutoGrowWidth may change for SdrTextObj due to the automatism used
1330 // with bDisableAutoWidthOnDragging, so not only geometry changes but
1331 // also this (pretty indirect) property change is possible. If it gets
1332 // changed, it needs to be copied to the original since nothing will
1333 // happen when it only changes in the drag clone
1334 const bool bOldAutoGrowWidth(pObj
->GetMergedItem(SDRATTR_TEXT_AUTOGROWWIDTH
).GetValue());
1335 const bool bNewAutoGrowWidth(mxClone
->GetMergedItem(SDRATTR_TEXT_AUTOGROWWIDTH
).GetValue());
1337 if (bOldAutoGrowWidth
!= bNewAutoGrowWidth
)
1339 GetDragObj()->SetMergedItem(makeSdrTextAutoGrowWidthItem(bNewAutoGrowWidth
));
1345 bool SdrDragObjOwn::EndSdrDrag(bool /*bCopy*/)
1348 std::vector
< std::unique_ptr
<SdrUndoAction
> > vConnectorUndoActions
;
1350 SdrObject
* pObj
= GetDragObj();
1354 std::unique_ptr
<SdrUndoAction
> pUndo
;
1355 std::unique_ptr
<SdrUndoAction
> pUndo2
;
1356 const bool bUndo
= getSdrDragView().IsUndoEnabled();
1360 getSdrDragView().EndTextEditCurrentView();
1361 if(!getSdrDragView().IsInsObjPoint() && pObj
->IsInserted() )
1363 if (DragStat().IsEndDragChangesAttributes())
1365 pUndo
=getSdrDragView().GetModel().GetSdrUndoFactory().CreateUndoAttrObject(*pObj
);
1367 if (DragStat().IsEndDragChangesGeoAndAttributes())
1369 vConnectorUndoActions
= getSdrDragView().CreateConnectorUndo( *pObj
);
1370 pUndo2
= getSdrDragView().GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pObj
);
1375 vConnectorUndoActions
= getSdrDragView().CreateConnectorUndo( *pObj
);
1376 pUndo
= getSdrDragView().GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pObj
);
1382 getSdrDragView().BegUndo( pUndo
->GetComment() );
1386 getSdrDragView().BegUndo();
1390 // Maybe use operator = for setting changed object data (do not change selection in
1391 // view, this will destroy the interactor). This is possible since a clone is now
1392 // directly modified by the modifiers. Only SdrTableObj is adding own UNDOs
1393 // in its SdrTableObj::endSpecialDrag, so currently not possible. OTOH it uses
1394 // a CreateUndoGeoObject(), so maybe setting SetEndDragChangesAttributes is okay. I
1395 // will test this now
1396 tools::Rectangle aBoundRect0
;
1398 if(pObj
->GetUserCall())
1400 aBoundRect0
= pObj
->GetLastBoundRect();
1403 bRet
= pObj
->applySpecialDrag(DragStat());
1404 if (DragStat().IsEndDragChangesLayout())
1406 auto pGeoUndo
= dynamic_cast<SdrUndoGeoObj
*>(pUndo
.get());
1408 pGeoUndo
->SetSkipChangeLayout(true);
1414 pObj
->BroadcastObjectChange();
1415 pObj
->SendUserCall( SdrUserCallType::Resize
, aBoundRect0
);
1420 getSdrDragView().AddUndoActions( std::move(vConnectorUndoActions
) );
1424 getSdrDragView().AddUndo(std::move(pUndo
));
1429 getSdrDragView().AddUndo(std::move(pUndo2
));
1434 getSdrDragView().EndUndo();
1440 PointerStyle
SdrDragObjOwn::GetSdrDragPointer() const
1442 const SdrHdl
* pHdl
=GetDragHdl();
1446 return pHdl
->GetPointer();
1449 return PointerStyle::Move
;
1453 void SdrDragMove::createSdrDragEntryForSdrObject(const SdrObject
& rOriginal
)
1455 // use the view-independent primitive representation (without
1456 // evtl. GridOffset, that may be applied to the DragEntry individually)
1457 drawinglayer::primitive2d::Primitive2DContainer xRetval
;
1458 rOriginal
.GetViewContact().getViewIndependentPrimitive2DContainer(xRetval
);
1460 std::unique_ptr
<SdrDragEntry
>(
1461 new SdrDragEntryPrimitive2DSequence(
1462 std::move(xRetval
))));
1466 void SdrDragMove::applyCurrentTransformationToSdrObject(SdrObject
& rTarget
)
1468 rTarget
.Move(Size(DragStat().GetDX(), DragStat().GetDY()));
1471 SdrDragMove::SdrDragMove(SdrDragView
& rNewView
)
1472 : SdrDragMethod(rNewView
)
1475 , m_bXSnapped(false)
1476 , m_bYSnapped(false)
1481 OUString
SdrDragMove::GetSdrDragComment() const
1483 OUString aStr
= ImpGetDescriptionStr(STR_DragMethMove
)
1485 + getSdrDragView().GetModel().GetMetricString(DragStat().GetDX())
1487 + getSdrDragView().GetModel().GetMetricString(DragStat().GetDY())
1490 if(getSdrDragView().IsDragWithCopy())
1492 if(!getSdrDragView().IsInsObjPoint() && !getSdrDragView().IsInsGluePoint())
1494 aStr
+= SvxResId(STR_EditWithCopy
);
1500 bool SdrDragMove::BeginSdrDrag()
1502 DragStat().SetActionRect(GetMarkedRect());
1508 basegfx::B2DHomMatrix
SdrDragMove::getCurrentTransformation() const
1510 return basegfx::utils::createTranslateB2DHomMatrix(DragStat().GetDX(), DragStat().GetDY());
1513 void SdrDragMove::ImpCheckSnap(const Point
& rPt
)
1516 SdrSnap nRet
=SnapPos(aPt
);
1519 if (nRet
& SdrSnap::XSNAPPED
)
1523 if (std::abs(aPt
.X())<std::abs(m_nBestXSnap
))
1525 m_nBestXSnap
=aPt
.X();
1530 m_nBestXSnap
=aPt
.X();
1535 if (!(nRet
& SdrSnap::YSNAPPED
))
1540 if (std::abs(aPt
.Y())<std::abs(m_nBestYSnap
))
1542 m_nBestYSnap
=aPt
.Y();
1547 m_nBestYSnap
=aPt
.Y();
1552 void SdrDragMove::MoveSdrDrag(const Point
& rNoSnapPnt_
)
1558 Point
aNoSnapPnt(rNoSnapPnt_
);
1559 const tools::Rectangle
& aSR
=GetMarkedRect();
1560 tools::Long nMovedx
=aNoSnapPnt
.X()-DragStat().GetStart().X();
1561 tools::Long nMovedy
=aNoSnapPnt
.Y()-DragStat().GetStart().Y();
1562 Point
aLO(aSR
.TopLeft()); aLO
.AdjustX(nMovedx
); aLO
.AdjustY(nMovedy
);
1563 Point
aRU(aSR
.BottomRight()); aRU
.AdjustX(nMovedx
); aRU
.AdjustY(nMovedy
);
1564 Point
aLU(aLO
.X(),aRU
.Y());
1565 Point
aRO(aRU
.X(),aLO
.Y());
1568 if (!getSdrDragView().IsMoveSnapOnlyTopLeft())
1575 Point
aPnt(aNoSnapPnt
.X()+m_nBestXSnap
,aNoSnapPnt
.Y()+m_nBestYSnap
);
1576 bool bOrtho
=getSdrDragView().IsOrtho();
1579 OrthoDistance8(DragStat().GetStart(),aPnt
,getSdrDragView().IsBigOrtho());
1581 if (!DragStat().CheckMinMoved(aNoSnapPnt
))
1585 tools::Rectangle
aLR(getSdrDragView().GetWorkArea());
1586 bool bWorkArea
=!aLR
.IsEmpty();
1587 bool bDragLimit
=IsDragLimit();
1589 if (bDragLimit
|| bWorkArea
)
1591 tools::Rectangle
aSR2(GetMarkedRect());
1592 Point
aD(aPt1
-DragStat().GetStart());
1596 tools::Rectangle
aR2(GetDragLimitRect());
1599 aLR
.Intersection(aR2
);
1604 if (aSR2
.Left()>aLR
.Left() || aSR2
.Right()<aLR
.Right())
1605 { // any space to move to?
1606 aSR2
.Move(aD
.X(),0);
1608 if (aSR2
.Left()<aLR
.Left())
1610 aPt1
.AdjustX( -(aSR2
.Left()-aLR
.Left()) );
1612 else if (aSR2
.Right()>aLR
.Right())
1614 aPt1
.AdjustX( -(aSR2
.Right()-aLR
.Right()) );
1618 aPt1
.setX(DragStat().GetStart().X() ); // no space to move to
1620 if (aSR2
.Top()>aLR
.Top() || aSR2
.Bottom()<aLR
.Bottom())
1621 { // any space to move to?
1622 aSR2
.Move(0,aD
.Y());
1624 if (aSR2
.Top()<aLR
.Top())
1626 aPt1
.AdjustY( -(aSR2
.Top()-aLR
.Top()) );
1628 else if (aSR2
.Bottom()>aLR
.Bottom())
1630 aPt1
.AdjustY( -(aSR2
.Bottom()-aLR
.Bottom()) );
1634 aPt1
.setY(DragStat().GetStart().Y() ); // no space to move to
1637 if (getSdrDragView().IsDraggingGluePoints())
1638 { // restrict gluepoints to the BoundRect of the Obj
1639 aPt1
-=DragStat().GetStart();
1640 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
1641 const size_t nMarkCount
= rMarkList
.GetMarkCount();
1643 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
; ++nMarkNum
)
1645 const SdrMark
* pM
= rMarkList
.GetMark(nMarkNum
);
1646 const SdrUShortCont
& rPts
= pM
->GetMarkedGluePoints();
1650 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
1651 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
1652 tools::Rectangle
aBound(pObj
->GetCurrentBoundRect());
1654 for (sal_uInt16 nId
: rPts
)
1656 sal_uInt16 nGlueNum
=pGPL
->FindGluePoint(nId
);
1658 if (nGlueNum
!=SDRGLUEPOINT_NOTFOUND
)
1660 Point
aPt((*pGPL
)[nGlueNum
].GetAbsolutePos(*pObj
));
1661 aPt
+=aPt1
; // move by this much
1662 if (aPt
.X()<aBound
.Left() ) aPt1
.AdjustX( -(aPt
.X()-aBound
.Left()) ) ;
1663 if (aPt
.X()>aBound
.Right() ) aPt1
.AdjustX( -(aPt
.X()-aBound
.Right()) ) ;
1664 if (aPt
.Y()<aBound
.Top() ) aPt1
.AdjustY( -(aPt
.Y()-aBound
.Top()) ) ;
1665 if (aPt
.Y()>aBound
.Bottom()) aPt1
.AdjustY( -(aPt
.Y()-aBound
.Bottom()) );
1671 aPt1
+=DragStat().GetStart();
1675 OrthoDistance8(DragStat().GetStart(),aPt1
,false);
1677 if (aPt1
!=DragStat().GetNow())
1680 DragStat().NextMove(aPt1
);
1681 tools::Rectangle
aAction(GetMarkedRect());
1682 aAction
.Move(DragStat().GetDX(),DragStat().GetDY());
1683 DragStat().SetActionRect(aAction
);
1688 bool SdrDragMove::EndSdrDrag(bool bCopy
)
1692 if (getSdrDragView().IsInsObjPoint() || getSdrDragView().IsInsGluePoint())
1695 if (IsDraggingPoints())
1697 getSdrDragView().MoveMarkedPoints(Size(DragStat().GetDX(),DragStat().GetDY()));
1699 else if (IsDraggingGluePoints())
1701 getSdrDragView().MoveMarkedGluePoints(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy
);
1705 getSdrDragView().MoveMarkedObj(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy
);
1711 PointerStyle
SdrDragMove::GetSdrDragPointer() const
1713 if (IsDraggingPoints() || IsDraggingGluePoints())
1715 return PointerStyle::MovePoint
;
1719 return PointerStyle::Move
;
1724 SdrDragResize::SdrDragResize(SdrDragView
& rNewView
)
1725 : SdrDragMethod(rNewView
),
1731 OUString
SdrDragResize::GetSdrDragComment() const
1733 OUString aStr
= ImpGetDescriptionStr(STR_DragMethResize
);
1734 Fraction
aFact1(1,1);
1735 Point
aStart(DragStat().GetStart());
1736 Point
aRef(DragStat().GetRef1());
1737 sal_Int32
nXDiv(aStart
.X() - aRef
.X());
1742 sal_Int32
nYDiv(aStart
.Y() - aRef
.Y());
1747 bool bX(m_aXFact
!= aFact1
&& std::abs(nXDiv
) > 1);
1748 bool bY(m_aYFact
!= aFact1
&& std::abs(nYDiv
) > 1);
1754 bool bEqual(m_aXFact
== m_aYFact
);
1760 aStr
+= SdrModel::GetPercentString(m_aXFact
);
1768 aStr
+= "y=" + SdrModel::GetPercentString(m_aYFact
);
1774 if(getSdrDragView().IsDragWithCopy())
1775 aStr
+= SvxResId(STR_EditWithCopy
);
1779 bool SdrDragResize::BeginSdrDrag()
1781 SdrHdlKind eRefHdl
=SdrHdlKind::Move
;
1782 SdrHdl
* pRefHdl
=nullptr;
1784 switch (GetDragHdlKind())
1786 case SdrHdlKind::UpperLeft
: eRefHdl
=SdrHdlKind::LowerRight
; break;
1787 case SdrHdlKind::Upper
: eRefHdl
=SdrHdlKind::Lower
; DragStat().SetHorFixed(true); break;
1788 case SdrHdlKind::UpperRight
: eRefHdl
=SdrHdlKind::LowerLeft
; break;
1789 case SdrHdlKind::Left
: eRefHdl
=SdrHdlKind::Right
; DragStat().SetVerFixed(true); break;
1790 case SdrHdlKind::Right
: eRefHdl
=SdrHdlKind::Left
; DragStat().SetVerFixed(true); break;
1791 case SdrHdlKind::LowerLeft
: eRefHdl
=SdrHdlKind::UpperRight
; break;
1792 case SdrHdlKind::Lower
: eRefHdl
=SdrHdlKind::Upper
; DragStat().SetHorFixed(true); break;
1793 case SdrHdlKind::LowerRight
: eRefHdl
=SdrHdlKind::UpperLeft
; break;
1797 if (eRefHdl
!=SdrHdlKind::Move
)
1798 pRefHdl
=GetHdlList().GetHdl(eRefHdl
);
1800 if (pRefHdl
!=nullptr && !getSdrDragView().IsResizeAtCenter())
1802 DragStat().SetRef1(pRefHdl
->GetPos());
1806 SdrHdl
* pRef1
=GetHdlList().GetHdl(SdrHdlKind::UpperLeft
);
1807 SdrHdl
* pRef2
=GetHdlList().GetHdl(SdrHdlKind::LowerRight
);
1809 if (pRef1
!=nullptr && pRef2
!=nullptr)
1811 DragStat().SetRef1(tools::Rectangle(pRef1
->GetPos(),pRef2
->GetPos()).Center());
1815 DragStat().SetRef1(GetMarkedRect().Center());
1824 basegfx::B2DHomMatrix
SdrDragResize::getCurrentTransformation() const
1826 basegfx::B2DHomMatrix
aRetval(basegfx::utils::createTranslateB2DHomMatrix(
1827 -DragStat().GetRef1().X(), -DragStat().GetRef1().Y()));
1828 aRetval
.scale(double(m_aXFact
), double(m_aYFact
));
1829 aRetval
.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y());
1834 void SdrDragResize::MoveSdrDrag(const Point
& rNoSnapPnt
)
1836 Point
aPnt(GetSnapPos(rNoSnapPnt
));
1837 Point
aStart(DragStat().GetStart());
1838 Point
aRef(DragStat().GetRef1());
1839 Fraction
aMaxFact(0x7FFFFFFF,1);
1840 tools::Rectangle
aLR(getSdrDragView().GetWorkArea());
1841 bool bWorkArea
=!aLR
.IsEmpty();
1842 bool bDragLimit
=IsDragLimit();
1844 if (bDragLimit
|| bWorkArea
)
1846 tools::Rectangle
aSR(GetMarkedRect());
1850 tools::Rectangle
aR2(GetDragLimitRect());
1853 aLR
.Intersection(aR2
);
1858 if (aPnt
.X()<aLR
.Left())
1859 aPnt
.setX(aLR
.Left() );
1860 else if (aPnt
.X()>aLR
.Right())
1861 aPnt
.setX(aLR
.Right() );
1863 if (aPnt
.Y()<aLR
.Top())
1864 aPnt
.setY(aLR
.Top() );
1865 else if (aPnt
.Y()>aLR
.Bottom())
1866 aPnt
.setY(aLR
.Bottom() );
1868 if (aRef
.X()>aSR
.Left())
1870 Fraction
aMax(aRef
.X()-aLR
.Left(),aRef
.X()-aSR
.Left());
1876 if (aRef
.X()<aSR
.Right())
1878 Fraction
aMax(aLR
.Right()-aRef
.X(),aSR
.Right()-aRef
.X());
1884 if (aRef
.Y()>aSR
.Top())
1886 Fraction
aMax(aRef
.Y()-aLR
.Top(),aRef
.Y()-aSR
.Top());
1892 if (aRef
.Y()<aSR
.Bottom())
1894 Fraction
aMax(aLR
.Bottom()-aRef
.Y(),aSR
.Bottom()-aRef
.Y());
1901 tools::Long nXDiv
=aStart
.X()-aRef
.X(); if (nXDiv
==0) nXDiv
=1;
1902 tools::Long nYDiv
=aStart
.Y()-aRef
.Y(); if (nYDiv
==0) nYDiv
=1;
1903 tools::Long nXMul
=aPnt
.X()-aRef
.X();
1904 tools::Long nYMul
=aPnt
.Y()-aRef
.Y();
1918 bool bXNeg
=nXMul
<0; if (bXNeg
) nXMul
=-nXMul
;
1919 bool bYNeg
=nYMul
<0; if (bYNeg
) nYMul
=-nYMul
;
1920 bool bOrtho
=getSdrDragView().IsOrtho() || !getSdrDragView().IsResizeAllowed();
1922 if (!DragStat().IsHorFixed() && !DragStat().IsVerFixed())
1924 if (std::abs(nXDiv
)<=1 || std::abs(nYDiv
)<=1)
1929 if ((Fraction(nXMul
,nXDiv
)>Fraction(nYMul
,nYDiv
)) !=getSdrDragView().IsBigOrtho())
1945 if (DragStat().IsHorFixed())
1952 if (DragStat().IsVerFixed())
1961 if (DragStat().IsHorFixed())
1968 if (DragStat().IsVerFixed())
1977 Fraction
aNewXFact(nXMul
,nXDiv
);
1978 Fraction
aNewYFact(nYMul
,nYDiv
);
1982 if (aNewXFact
>aMaxFact
)
1988 if (aNewYFact
>aMaxFact
)
1996 aNewXFact
=Fraction(-aNewXFact
.GetNumerator(),aNewXFact
.GetDenominator());
1999 aNewYFact
=Fraction(-aNewYFact
.GetNumerator(),aNewYFact
.GetDenominator());
2001 if (DragStat().CheckMinMoved(aPnt
))
2003 if ((!DragStat().IsHorFixed() && aPnt
.X()!=DragStat().GetNow().X()) ||
2004 (!DragStat().IsVerFixed() && aPnt
.Y()!=DragStat().GetNow().Y()))
2007 DragStat().NextMove(aPnt
);
2011 aNewXFact
= double(aNewXFact
) > 0 ? aNewXFact
: Fraction(1, 1);
2012 aNewYFact
= double(aNewYFact
) > 0 ? aNewYFact
: Fraction(1, 1);
2014 GetMarkedRect().GetSize().scale(aNewXFact
.GetNumerator(), aNewXFact
.GetDenominator(),
2015 aNewYFact
.GetNumerator(), aNewYFact
.GetDenominator()));
2016 Show(getSdrDragView().IsMarkedObjSizeValid(aTargetSize
));
2021 void SdrDragResize::applyCurrentTransformationToSdrObject(SdrObject
& rTarget
)
2023 rTarget
.Resize(DragStat().GetRef1(),m_aXFact
,m_aYFact
);
2026 bool SdrDragResize::EndSdrDrag(bool bCopy
)
2030 if (IsDraggingPoints())
2032 getSdrDragView().ResizeMarkedPoints(DragStat().GetRef1(),m_aXFact
,m_aYFact
);
2034 else if (IsDraggingGluePoints())
2036 getSdrDragView().ResizeMarkedGluePoints(DragStat().GetRef1(),m_aXFact
,m_aYFact
,bCopy
);
2040 getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),m_aXFact
,m_aYFact
,bCopy
);
2046 PointerStyle
SdrDragResize::GetSdrDragPointer() const
2048 const SdrHdl
* pHdl
=GetDragHdl();
2052 return pHdl
->GetPointer();
2055 return PointerStyle::Move
;
2059 void SdrDragRotate::applyCurrentTransformationToSdrObject(SdrObject
& rTarget
)
2061 rTarget
.Rotate(DragStat().GetRef1(), nAngle
, nSin
, nCos
);
2064 SdrDragRotate::SdrDragRotate(SdrDragView
& rNewView
)
2065 : SdrDragMethod(rNewView
),
2074 OUString
SdrDragRotate::GetSdrDragComment() const
2076 OUString aStr
= ImpGetDescriptionStr(STR_DragMethRotate
) +
2078 Degree100
nTmpAngle(NormAngle36000(nAngle
));
2080 if(bRight
&& nAngle
)
2082 nTmpAngle
-= 36000_deg100
;
2085 aStr
+= SdrModel::GetAngleString(nTmpAngle
) + ")";
2087 if(getSdrDragView().IsDragWithCopy())
2088 aStr
+= SvxResId(STR_EditWithCopy
);
2092 bool SdrDragRotate::BeginSdrDrag()
2094 SdrHdl
* pH
=GetHdlList().GetHdl(SdrHdlKind::Ref1
);
2099 DragStat().SetRef1(pH
->GetPos());
2100 nAngle0
=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
2104 // RotGrfFlyFrame: Support rotation around center *without* Ref1 (normally
2105 // the rotation point)
2106 const tools::Rectangle
aLocalMarkRect(getSdrDragView().GetMarkedObjRect());
2108 if(!aLocalMarkRect
.IsEmpty())
2111 DragStat().SetRef1(aLocalMarkRect
.Center());
2112 nAngle0
=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
2116 OSL_FAIL("SdrDragRotate::BeginSdrDrag(): No reference point handle found.");
2120 basegfx::B2DHomMatrix
SdrDragRotate::getCurrentTransformation() const
2122 return basegfx::utils::createRotateAroundPoint(
2123 DragStat().GetRef1().X(), DragStat().GetRef1().Y(),
2124 -atan2(nSin
, nCos
));
2127 void SdrDragRotate::MoveSdrDrag(const Point
& rPnt_
)
2130 if (!DragStat().CheckMinMoved(aPnt
))
2133 Degree100 nNewAngle
=NormAngle36000(GetAngle(aPnt
-DragStat().GetRef1())-nAngle0
);
2136 if (getSdrDragView().IsAngleSnapEnabled())
2137 nSA
=getSdrDragView().GetSnapAngle();
2139 if (!getSdrDragView().IsRotateAllowed())
2144 nNewAngle
+= nSA
/ 2_deg100
;
2149 nNewAngle
=NormAngle18000(nNewAngle
);
2151 if (nAngle
==nNewAngle
)
2154 sal_uInt16 nSekt0
=GetAngleSector(nAngle
);
2155 sal_uInt16 nSekt1
=GetAngleSector(nNewAngle
);
2157 if (nSekt0
==0 && nSekt1
==3)
2160 if (nSekt0
==3 && nSekt1
==0)
2164 double a
= toRadians(nAngle
);
2165 double nSin1
=sin(a
); // calculate now, so as little time as possible
2166 double nCos1
=cos(a
); // passes between Hide() and Show()
2170 DragStat().NextMove(aPnt
);
2174 bool SdrDragRotate::EndSdrDrag(bool bCopy
)
2178 if (nAngle
!=0_deg100
)
2180 if (IsDraggingPoints())
2182 getSdrDragView().RotateMarkedPoints(DragStat().GetRef1(),nAngle
);
2184 else if (IsDraggingGluePoints())
2186 getSdrDragView().RotateMarkedGluePoints(DragStat().GetRef1(),nAngle
,bCopy
);
2190 getSdrDragView().RotateMarkedObj(DragStat().GetRef1(),nAngle
,bCopy
);
2196 PointerStyle
SdrDragRotate::GetSdrDragPointer() const
2198 return PointerStyle::Rotate
;
2202 SdrDragShear::SdrDragShear(SdrDragView
& rNewView
, bool bSlant1
)
2203 : SdrDragMethod(rNewView
),
2215 OUString
SdrDragShear::GetSdrDragComment() const
2217 OUString aStr
= ImpGetDescriptionStr(STR_DragMethShear
) +
2220 Degree100
nTmpAngle(nAngle
);
2223 nTmpAngle
+= 18000_deg100
;
2225 nTmpAngle
= NormAngle18000(nTmpAngle
);
2227 aStr
+= SdrModel::GetAngleString(nTmpAngle
) + ")";
2229 if(getSdrDragView().IsDragWithCopy())
2230 aStr
+= SvxResId(STR_EditWithCopy
);
2234 bool SdrDragShear::BeginSdrDrag()
2236 SdrHdlKind eRefHdl
=SdrHdlKind::Move
;
2237 SdrHdl
* pRefHdl
=nullptr;
2239 switch (GetDragHdlKind())
2241 case SdrHdlKind::Upper
: eRefHdl
=SdrHdlKind::Lower
; break;
2242 case SdrHdlKind::Lower
: eRefHdl
=SdrHdlKind::Upper
; break;
2243 case SdrHdlKind::Left
: eRefHdl
=SdrHdlKind::Right
; bVertical
=true; break;
2244 case SdrHdlKind::Right
: eRefHdl
=SdrHdlKind::Left
; bVertical
=true; break;
2248 if (eRefHdl
!=SdrHdlKind::Move
)
2249 pRefHdl
=GetHdlList().GetHdl(eRefHdl
);
2251 if (pRefHdl
!=nullptr)
2253 DragStat().SetRef1(pRefHdl
->GetPos());
2254 nAngle0
=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
2258 OSL_FAIL("SdrDragShear::BeginSdrDrag(): No reference point handle for shearing found.");
2266 basegfx::B2DHomMatrix
SdrDragShear::getCurrentTransformation() const
2268 basegfx::B2DHomMatrix
aRetval(basegfx::utils::createTranslateB2DHomMatrix(
2269 -DragStat().GetRef1().X(), -DragStat().GetRef1().Y()));
2275 aRetval
.scale(double(aFact
), 1.0);
2276 aRetval
.shearY(-nTan
);
2280 aRetval
.scale(1.0, double(aFact
));
2281 aRetval
.shearX(-nTan
);
2285 aRetval
.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y());
2290 void SdrDragShear::MoveSdrDrag(const Point
& rPnt
)
2292 if (!DragStat().CheckMinMoved(rPnt
))
2295 bResize
=!getSdrDragView().IsOrtho();
2298 if (getSdrDragView().IsAngleSnapEnabled())
2299 nSA
=getSdrDragView().GetSnapAngle();
2301 Point
aP0(DragStat().GetStart());
2303 Fraction
aNewFract(1,1);
2305 // if angle snapping not activated, snap to raster (except when using slant)
2306 if (nSA
==0_deg100
&& !bSlant
)
2307 aPnt
=GetSnapPos(aPnt
);
2309 if (!bSlant
&& !bResize
)
2310 { // shear, but no resize
2312 aPnt
.setX(aP0
.X() );
2314 aPnt
.setY(aP0
.Y() );
2317 Point
aRef(DragStat().GetRef1());
2318 Point
aDif(aPnt
-aRef
);
2320 Degree100
nNewAngle(0);
2324 nNewAngle
=NormAngle18000(-(GetAngle(aDif
)-nAngle0
));
2327 nNewAngle
=NormAngle18000(-nNewAngle
);
2332 nNewAngle
=NormAngle18000(GetAngle(aDif
));
2334 nNewAngle
=NormAngle18000(-(GetAngle(aDif
)-9000_deg100
));
2336 if (nNewAngle
<Degree100(-9000) || nNewAngle
>9000_deg100
)
2337 nNewAngle
=NormAngle18000(nNewAngle
+18000_deg100
);
2344 aPt2
=GetSnapPos(aPnt
); // snap this one in any case
2348 aNewFract
=Fraction(aPt2
.X()-aRef
.X(),aP0
.X()-aRef
.X());
2352 aNewFract
=Fraction(aPt2
.Y()-aRef
.Y(),aP0
.Y()-aRef
.Y());
2357 bool bNeg
=nNewAngle
<0_deg100
;
2360 nNewAngle
=-nNewAngle
;
2364 nNewAngle
+= nSA
/ 2_deg100
;
2369 nNewAngle
=NormAngle36000(nNewAngle
);
2370 bUpSideDown
=nNewAngle
>9000_deg100
&& nNewAngle
<27000_deg100
;
2373 { // calculate resize for slant
2374 // when angle snapping is activated, disable 89 degree limit
2375 Degree100 nTmpAngle
=nNewAngle
;
2376 if (bUpSideDown
) nNewAngle
-= 18000_deg100
;
2377 if (bNeg
) nTmpAngle
=-nTmpAngle
;
2379 aNewFract
= cos(toRadians(nTmpAngle
));
2380 aFact
.ReduceInaccurate(10); // three decimals should be enough
2383 if (nNewAngle
> 8900_deg100
)
2384 nNewAngle
= 8900_deg100
;
2387 nNewAngle
=-nNewAngle
;
2389 if (nAngle
!=nNewAngle
|| aFact
!=aNewFract
)
2393 double a
= toRadians(nAngle
);
2394 double nTan1
=tan(a
); // calculate now, so as little time as possible passes between Hide() and Show()
2397 DragStat().NextMove(rPnt
);
2402 void SdrDragShear::applyCurrentTransformationToSdrObject(SdrObject
& rTarget
)
2408 rTarget
.Resize(DragStat().GetRef1(),aFact
,Fraction(1,1));
2412 rTarget
.Resize(DragStat().GetRef1(),Fraction(1,1),aFact
);
2418 rTarget
.Shear(DragStat().GetRef1(), nAngle
, nTan
, bVertical
);
2422 bool SdrDragShear::EndSdrDrag(bool bCopy
)
2426 if (bResize
&& aFact
==Fraction(1,1))
2429 if (nAngle
|| bResize
)
2431 if (nAngle
&& bResize
)
2433 OUString aStr
= ImpGetDescriptionStr(STR_EditShear
);
2436 aStr
+= SvxResId(STR_EditWithCopy
);
2438 getSdrDragView().BegUndo(aStr
);
2445 getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),aFact
,Fraction(1,1),bCopy
);
2449 getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),Fraction(1,1),aFact
,bCopy
);
2457 getSdrDragView().ShearMarkedObj(DragStat().GetRef1(),nAngle
,bVertical
,bCopy
);
2460 if (nAngle
&& bResize
)
2461 getSdrDragView().EndUndo();
2469 PointerStyle
SdrDragShear::GetSdrDragPointer() const
2472 return PointerStyle::VShear
;
2474 return PointerStyle::HShear
;
2478 void SdrDragMirror::applyCurrentTransformationToSdrObject(SdrObject
& rTarget
)
2482 rTarget
.Mirror(DragStat().GetRef1(), DragStat().GetRef2());
2486 SdrDragMirror::SdrDragMirror(SdrDragView
& rNewView
)
2487 : SdrDragMethod(rNewView
),
2494 bool SdrDragMirror::ImpCheckSide(const Point
& rPnt
) const
2496 Degree100 nAngle1
=GetAngle(rPnt
-DragStat().GetRef1());
2498 nAngle1
=NormAngle36000(nAngle1
);
2500 return nAngle1
<18000_deg100
;
2503 OUString
SdrDragMirror::GetSdrDragComment() const
2507 aStr
= ImpGetDescriptionStr(STR_DragMethMirrorHori
);
2508 else if (aDif
.Y()==0)
2509 aStr
= ImpGetDescriptionStr(STR_DragMethMirrorVert
);
2510 else if (std::abs(aDif
.X()) == std::abs(aDif
.Y()))
2511 aStr
= ImpGetDescriptionStr(STR_DragMethMirrorDiag
);
2513 aStr
= ImpGetDescriptionStr(STR_DragMethMirrorFree
);
2515 if (getSdrDragView().IsDragWithCopy())
2516 aStr
+=SvxResId(STR_EditWithCopy
);
2520 bool SdrDragMirror::BeginSdrDrag()
2522 SdrHdl
* pH1
=GetHdlList().GetHdl(SdrHdlKind::Ref1
);
2523 SdrHdl
* pH2
=GetHdlList().GetHdl(SdrHdlKind::Ref2
);
2525 if (pH1
!=nullptr && pH2
!=nullptr)
2527 DragStat().SetRef1(pH1
->GetPos());
2528 DragStat().SetRef2(pH2
->GetPos());
2529 Ref1()=pH1
->GetPos();
2530 Ref2()=pH2
->GetPos();
2531 aDif
=pH2
->GetPos()-pH1
->GetPos();
2532 bool b90
=(aDif
.X()==0) || aDif
.Y()==0;
2533 bool b45
=b90
|| (std::abs(aDif
.X()) == std::abs(aDif
.Y()));
2534 nAngle
=NormAngle36000(GetAngle(aDif
));
2536 if (!getSdrDragView().IsMirrorAllowed() && !b45
)
2537 return false; // free choice of axis angle not allowed
2539 if (!getSdrDragView().IsMirrorAllowed() && !b90
)
2540 return false; // 45 degrees not allowed either
2542 bSide0
=ImpCheckSide(DragStat().GetStart());
2548 OSL_FAIL("SdrDragMirror::BeginSdrDrag(): Axis of reflection not found.");
2553 basegfx::B2DHomMatrix
SdrDragMirror::getCurrentTransformation() const
2555 basegfx::B2DHomMatrix aRetval
;
2559 const double fDeltaX(DragStat().GetRef2().X() - DragStat().GetRef1().X());
2560 const double fDeltaY(DragStat().GetRef2().Y() - DragStat().GetRef1().Y());
2561 const double fRotation(atan2(fDeltaY
, fDeltaX
));
2563 aRetval
= basegfx::utils::createTranslateB2DHomMatrix(-DragStat().GetRef1().X(), -DragStat().GetRef1().Y());
2564 aRetval
.rotate(-fRotation
);
2565 aRetval
.scale(1.0, -1.0);
2566 aRetval
.rotate(fRotation
);
2567 aRetval
.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y());
2573 void SdrDragMirror::MoveSdrDrag(const Point
& rPnt
)
2575 if (!DragStat().CheckMinMoved(rPnt
))
2578 bool bNewSide
=ImpCheckSide(rPnt
);
2579 bool bNewMirrored
=bSide0
!=bNewSide
;
2581 if (bMirrored
!=bNewMirrored
)
2584 bMirrored
=bNewMirrored
;
2585 DragStat().NextMove(rPnt
);
2590 bool SdrDragMirror::EndSdrDrag(bool bCopy
)
2596 getSdrDragView().MirrorMarkedObj(DragStat().GetRef1(),DragStat().GetRef2(),bCopy
);
2602 PointerStyle
SdrDragMirror::GetSdrDragPointer() const
2604 return PointerStyle::Mirror
;
2608 SdrDragGradient::SdrDragGradient(SdrDragView
& rNewView
, bool bGrad
)
2609 : SdrDragMethod(rNewView
),
2610 pIAOHandle(nullptr),
2615 OUString
SdrDragGradient::GetSdrDragComment() const
2618 return ImpGetDescriptionStr(STR_DragMethGradient
);
2620 return ImpGetDescriptionStr(STR_DragMethTransparence
);
2623 bool SdrDragGradient::BeginSdrDrag()
2625 bool bRetval(false);
2627 pIAOHandle
= static_cast<SdrHdlGradient
*>(GetHdlList().GetHdl(IsGradient() ? SdrHdlKind::Gradient
: SdrHdlKind::Transparence
));
2632 DragStat().SetRef1( pIAOHandle
->GetPos() );
2633 DragStat().SetRef2( pIAOHandle
->Get2ndPos() );
2637 SdrHdlColor
* pColHdl
= pIAOHandle
->GetColorHdl1();
2639 // init handling flags
2640 pIAOHandle
->SetMoveSingleHandle(false);
2641 pIAOHandle
->SetMoveFirstHandle(false);
2643 // test first color handle
2646 basegfx::B2DPoint
aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2648 if(pColHdl
->getOverlayObjectList().isHitLogic(aPosition
))
2651 pIAOHandle
->SetMoveSingleHandle(true);
2652 pIAOHandle
->SetMoveFirstHandle(true);
2656 // test second color handle
2657 pColHdl
= pIAOHandle
->GetColorHdl2();
2659 if(!bHit
&& pColHdl
)
2661 basegfx::B2DPoint
aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2663 if(pColHdl
->getOverlayObjectList().isHitLogic(aPosition
))
2666 pIAOHandle
->SetMoveSingleHandle(true);
2670 // test gradient handle itself
2673 basegfx::B2DPoint
aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2675 if(pIAOHandle
->getOverlayObjectList().isHitLogic(aPosition
))
2681 // everything up and running :o}
2686 OSL_FAIL("SdrDragGradient::BeginSdrDrag(): IAOGradient not found.");
2692 void SdrDragGradient::MoveSdrDrag(const Point
& rPnt
)
2694 if(!(pIAOHandle
&& DragStat().CheckMinMoved(rPnt
)))
2697 DragStat().NextMove(rPnt
);
2699 // Do the Move here!!! DragStat().GetStart()
2700 Point aMoveDiff
= rPnt
- DragStat().GetStart();
2702 if(pIAOHandle
->IsMoveSingleHandle())
2704 if(pIAOHandle
->IsMoveFirstHandle())
2706 pIAOHandle
->SetPos(DragStat().GetRef1() + aMoveDiff
);
2707 if(pIAOHandle
->GetColorHdl1())
2708 pIAOHandle
->GetColorHdl1()->SetPos(DragStat().GetRef1() + aMoveDiff
);
2712 pIAOHandle
->Set2ndPos(DragStat().GetRef2() + aMoveDiff
);
2713 if(pIAOHandle
->GetColorHdl2())
2714 pIAOHandle
->GetColorHdl2()->SetPos(DragStat().GetRef2() + aMoveDiff
);
2719 pIAOHandle
->SetPos(DragStat().GetRef1() + aMoveDiff
);
2720 pIAOHandle
->Set2ndPos(DragStat().GetRef2() + aMoveDiff
);
2722 if(pIAOHandle
->GetColorHdl1())
2723 pIAOHandle
->GetColorHdl1()->SetPos(DragStat().GetRef1() + aMoveDiff
);
2725 if(pIAOHandle
->GetColorHdl2())
2726 pIAOHandle
->GetColorHdl2()->SetPos(DragStat().GetRef2() + aMoveDiff
);
2730 const SdrMarkList
& rMarkList
= getSdrDragView().GetMarkedObjectList();
2731 pIAOHandle
->FromIAOToItem(rMarkList
.GetMark(0)->GetMarkedSdrObj(), false, false);
2734 bool SdrDragGradient::EndSdrDrag(bool /*bCopy*/)
2736 Ref1() = pIAOHandle
->GetPos();
2737 Ref2() = pIAOHandle
->Get2ndPos();
2740 const SdrMarkList
& rMarkList
= getSdrDragView().GetMarkedObjectList();
2741 pIAOHandle
->FromIAOToItem(rMarkList
.GetMark(0)->GetMarkedSdrObj(), true, true);
2746 void SdrDragGradient::CancelSdrDrag()
2748 // restore old values
2749 pIAOHandle
->SetPos(DragStat().GetRef1());
2750 pIAOHandle
->Set2ndPos(DragStat().GetRef2());
2752 if(pIAOHandle
->GetColorHdl1())
2753 pIAOHandle
->GetColorHdl1()->SetPos(DragStat().GetRef1());
2755 if(pIAOHandle
->GetColorHdl2())
2756 pIAOHandle
->GetColorHdl2()->SetPos(DragStat().GetRef2());
2759 const SdrMarkList
& rMarkList
= getSdrDragView().GetMarkedObjectList();
2760 pIAOHandle
->FromIAOToItem(rMarkList
.GetMark(0)->GetMarkedSdrObj(), true, false);
2763 PointerStyle
SdrDragGradient::GetSdrDragPointer() const
2765 return PointerStyle::RefHand
;
2769 SdrDragCrook::SdrDragCrook(SdrDragView
& rNewView
)
2770 : SdrDragMethod(rNewView
),
2772 bContortionAllowed(false),
2773 bNoContortionAllowed(false),
2775 bResizeAllowed(false),
2777 bRotateAllowed(false),
2788 eMode(SdrCrookMode::Rotate
)
2792 OUString
SdrDragCrook::GetSdrDragComment() const
2794 OUString aStr
= ImpGetDescriptionStr(!bContortion
? STR_DragMethCrook
: STR_DragMethCrookContortion
);
2800 sal_Int32
nVal(nAngle
);
2805 nVal
= std::abs(nVal
);
2806 aStr
+= SdrModel::GetAngleString(Degree100(nVal
)) + ")";
2809 if(getSdrDragView().IsDragWithCopy())
2810 aStr
+= SvxResId(STR_EditWithCopy
);
2814 // These defines parametrize the created raster
2816 #define DRAG_CROOK_RASTER_MINIMUM (4)
2817 #define DRAG_CROOK_RASTER_MAXIMUM (15)
2818 #define DRAG_CROOK_RASTER_DISTANCE (30)
2820 static basegfx::B2DPolyPolygon
impCreateDragRaster(SdrPageView
const & rPageView
, const tools::Rectangle
& rMarkRect
)
2822 basegfx::B2DPolyPolygon aRetval
;
2824 if(rPageView
.PageWindowCount())
2826 OutputDevice
& rOut
= rPageView
.GetPageWindow(0)->GetPaintWindow().GetOutputDevice();
2827 tools::Rectangle aPixelSize
= rOut
.LogicToPixel(rMarkRect
);
2828 sal_uInt32
nHorDiv(aPixelSize
.GetWidth() / DRAG_CROOK_RASTER_DISTANCE
);
2829 sal_uInt32
nVerDiv(aPixelSize
.GetHeight() / DRAG_CROOK_RASTER_DISTANCE
);
2831 if(nHorDiv
> DRAG_CROOK_RASTER_MAXIMUM
)
2832 nHorDiv
= DRAG_CROOK_RASTER_MAXIMUM
;
2833 if(nHorDiv
< DRAG_CROOK_RASTER_MINIMUM
)
2834 nHorDiv
= DRAG_CROOK_RASTER_MINIMUM
;
2836 if(nVerDiv
> DRAG_CROOK_RASTER_MAXIMUM
)
2837 nVerDiv
= DRAG_CROOK_RASTER_MAXIMUM
;
2838 if(nVerDiv
< DRAG_CROOK_RASTER_MINIMUM
)
2839 nVerDiv
= DRAG_CROOK_RASTER_MINIMUM
;
2841 const double fXLen(rMarkRect
.GetWidth() / static_cast<double>(nHorDiv
));
2842 const double fYLen(rMarkRect
.GetHeight() / static_cast<double>(nVerDiv
));
2843 double fYPos(rMarkRect
.Top());
2846 for(a
= 0; a
<= nVerDiv
; a
++)
2849 for(b
= 0; b
< nHorDiv
; b
++)
2851 basegfx::B2DPolygon aHorLineSegment
;
2853 const double fNewX(rMarkRect
.Left() + (b
* fXLen
));
2854 aHorLineSegment
.append(basegfx::B2DPoint(fNewX
, fYPos
));
2855 aHorLineSegment
.appendBezierSegment(
2856 basegfx::B2DPoint(fNewX
+ (fXLen
* (1.0 / 3.0)), fYPos
),
2857 basegfx::B2DPoint(fNewX
+ (fXLen
* (2.0 / 3.0)), fYPos
),
2858 basegfx::B2DPoint(fNewX
+ fXLen
, fYPos
));
2859 aRetval
.append(aHorLineSegment
);
2866 double fXPos(rMarkRect
.Left());
2868 for(a
= 0; a
<= nHorDiv
; a
++)
2871 for(b
= 0; b
< nVerDiv
; b
++)
2873 basegfx::B2DPolygon aVerLineSegment
;
2875 const double fNewY(rMarkRect
.Top() + (b
* fYLen
));
2876 aVerLineSegment
.append(basegfx::B2DPoint(fXPos
, fNewY
));
2877 aVerLineSegment
.appendBezierSegment(
2878 basegfx::B2DPoint(fXPos
, fNewY
+ (fYLen
* (1.0 / 3.0))),
2879 basegfx::B2DPoint(fXPos
, fNewY
+ (fYLen
* (2.0 / 3.0))),
2880 basegfx::B2DPoint(fXPos
, fNewY
+ fYLen
));
2881 aRetval
.append(aVerLineSegment
);
2892 void SdrDragCrook::createSdrDragEntries()
2894 // Add extended frame raster first, so it will be behind objects
2895 if(getSdrDragView().GetSdrPageView())
2897 const basegfx::B2DPolyPolygon
aDragRaster(impCreateDragRaster(*getSdrDragView().GetSdrPageView(), GetMarkedRect()));
2899 if(aDragRaster
.count())
2901 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntryPolyPolygon(aDragRaster
)));
2906 SdrDragMethod::createSdrDragEntries();
2909 bool SdrDragCrook::BeginSdrDrag()
2911 bContortionAllowed
=getSdrDragView().IsCrookAllowed();
2912 bNoContortionAllowed
=getSdrDragView().IsCrookAllowed(true);
2913 bResizeAllowed
=getSdrDragView().IsResizeAllowed();
2914 bRotateAllowed
=getSdrDragView().IsRotateAllowed();
2916 if (bContortionAllowed
|| bNoContortionAllowed
)
2918 bVertical
=(GetDragHdlKind()==SdrHdlKind::Lower
|| GetDragHdlKind()==SdrHdlKind::Upper
);
2919 aMarkRect
=GetMarkedRect();
2920 aMarkCenter
=aMarkRect
.Center();
2921 nMarkSize
=bVertical
? (aMarkRect
.GetHeight()-1) : (aMarkRect
.GetWidth()-1);
2922 aCenter
=aMarkCenter
;
2923 aStart
=DragStat().GetStart();
2933 void SdrDragCrook::MovAllPoints(basegfx::B2DPolyPolygon
& rTarget
)
2935 SdrPageView
* pPV
= getSdrDragView().GetSdrPageView();
2940 XPolyPolygon
aTempPolyPoly(rTarget
);
2942 if (pPV
->HasMarkedObjPageView())
2944 sal_uInt16 nPolyCount
=aTempPolyPoly
.Count();
2946 if (!bContortion
&& !getSdrDragView().IsNoDragXorPolys())
2948 sal_uInt16 n1st
=0,nLast
=0;
2951 while (n1st
<nPolyCount
)
2954 while (nLast
<nPolyCount
&& aTempPolyPoly
[nLast
].GetPointCount()!=0) nLast
++;
2955 tools::Rectangle
aBound(aTempPolyPoly
[n1st
].GetBoundRect());
2958 for (i
=n1st
+1; i
<nLast
; i
++)
2960 aBound
.Union(aTempPolyPoly
[n1st
].GetBoundRect());
2963 Point
aCtr0(aBound
.Center());
2968 Fraction
aFact1(1,1);
2972 ResizePoint(aCtr1
,aC
,aFact1
,aFact
);
2976 ResizePoint(aCtr1
,aC
,aFact
,aFact1
);
2981 double nSin
=0,nCos
=0;
2983 if (aRad
.X()!=0 && aRad
.Y()!=0)
2989 case SdrCrookMode::Rotate
: CrookRotateXPoint (aCtr1
,nullptr,nullptr,aC
,aRad
,nSin
,nCos
,bVertical
); break;
2990 case SdrCrookMode::Slant
: CrookSlantXPoint (aCtr1
,nullptr,nullptr,aC
,aRad
,nSin
,nCos
,bVertical
); break;
2991 case SdrCrookMode::Stretch
: CrookStretchXPoint(aCtr1
,nullptr,nullptr,aC
,aRad
,nSin
,nCos
,bVertical
,aMarkRect
); break;
2997 for (i
=n1st
; i
<nLast
; i
++)
3001 RotateXPoly(aTempPolyPoly
[i
],aCtr0
,nSin
,nCos
);
3004 aTempPolyPoly
[i
].Move(aCtr1
.X(),aCtr1
.Y());
3014 for (j
=0; j
<nPolyCount
; j
++)
3016 XPolygon
& aPol
=aTempPolyPoly
[j
];
3017 sal_uInt16 nPointCount
=aPol
.GetPointCount();
3020 while (i
<nPointCount
)
3022 Point
* pPnt
=&aPol
[i
];
3026 if (i
+1<nPointCount
&& aPol
.IsControl(i
))
3027 { // control point on the left
3035 if (i
<nPointCount
&& aPol
.IsControl(i
))
3036 { // control point on the right
3041 MovCrookPoint(*pPnt
,pC1
,pC2
);
3047 rTarget
= aTempPolyPoly
.getB2DPolyPolygon();
3050 void SdrDragCrook::MovCrookPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
)
3052 bool bVert
=bVertical
;
3053 bool bC1
=pC1
!=nullptr;
3054 bool bC2
=pC2
!=nullptr;
3059 Fraction
aFact1(1,1);
3063 ResizePoint(rPnt
,aC
,aFact1
,aFact
);
3066 ResizePoint(*pC1
,aC
,aFact1
,aFact
);
3069 ResizePoint(*pC2
,aC
,aFact1
,aFact
);
3073 ResizePoint(rPnt
,aC
,aFact
,aFact1
);
3076 ResizePoint(*pC1
,aC
,aFact
,aFact1
);
3079 ResizePoint(*pC2
,aC
,aFact
,aFact1
);
3083 if (aRad
.X()!=0 && aRad
.Y()!=0)
3089 case SdrCrookMode::Rotate
: CrookRotateXPoint (rPnt
,pC1
,pC2
,aC
,aRad
,nSin
,nCos
,bVert
); break;
3090 case SdrCrookMode::Slant
: CrookSlantXPoint (rPnt
,pC1
,pC2
,aC
,aRad
,nSin
,nCos
,bVert
); break;
3091 case SdrCrookMode::Stretch
: CrookStretchXPoint(rPnt
,pC1
,pC2
,aC
,aRad
,nSin
,nCos
,bVert
,aMarkRect
); break;
3096 void SdrDragCrook::MoveSdrDrag(const Point
& rPnt
)
3098 if (!DragStat().CheckMinMoved(rPnt
))
3101 bool bNewMoveOnly
=getSdrDragView().IsMoveOnlyDragging();
3103 SdrCrookMode eNewMode
=getSdrDragView().GetCrookMode();
3104 bool bNewContortion
=!bNewMoveOnly
&& ((bContortionAllowed
&& !getSdrDragView().IsCrookNoContortion()) || !bNoContortionAllowed
);
3105 bResize
=!getSdrDragView().IsOrtho() && bResizeAllowed
&& !bNewMoveOnly
;
3106 bool bNewRotate
=bRotateAllowed
&& !bNewContortion
&& !bNewMoveOnly
&& eNewMode
==SdrCrookMode::Rotate
;
3108 Point
aPnt(GetSnapPos(rPnt
));
3110 Point
aNewCenter(aMarkCenter
.X(),aStart
.Y());
3114 aNewCenter
.setX(aStart
.X() );
3115 aNewCenter
.setY(aMarkCenter
.Y() );
3118 if (!getSdrDragView().IsCrookAtCenter())
3120 switch (GetDragHdlKind())
3122 case SdrHdlKind::UpperLeft
: aNewCenter
.setX(aMarkRect
.Right() ); bLft
=true; break;
3123 case SdrHdlKind::Upper
: aNewCenter
.setY(aMarkRect
.Bottom() ); bUpr
=true; break;
3124 case SdrHdlKind::UpperRight
: aNewCenter
.setX(aMarkRect
.Left() ); bRgt
=true; break;
3125 case SdrHdlKind::Left
: aNewCenter
.setX(aMarkRect
.Right() ); bLft
=true; break;
3126 case SdrHdlKind::Right
: aNewCenter
.setX(aMarkRect
.Left() ); bRgt
=true; break;
3127 case SdrHdlKind::LowerLeft
: aNewCenter
.setX(aMarkRect
.Right() ); bLft
=true; break;
3128 case SdrHdlKind::Lower
: aNewCenter
.setY(aMarkRect
.Top() ); bLwr
=true; break;
3129 case SdrHdlKind::LowerRight
: aNewCenter
.setX(aMarkRect
.Left() ); bRgt
=true; break;
3130 default: bAtCenter
=true;
3136 Fraction
aNewFract(1,1);
3137 tools::Long dx1
=aPnt
.X()-aNewCenter
.X();
3138 tools::Long dy1
=aPnt
.Y()-aNewCenter
.Y();
3139 bValid
=bVertical
? dx1
!=0 : dy1
!=0;
3144 bValid
= std::abs(dx1
)*100>std::abs(dy1
);
3146 bValid
= std::abs(dy1
)*100>std::abs(dx1
);
3149 tools::Long nNewRad
=0;
3154 double a
=0; // slope of the radius
3155 Degree100
nPntAngle(0);
3159 a
=static_cast<double>(dy1
)/static_cast<double>(dx1
); // slope of the radius
3160 nNewRad
=(static_cast<tools::Long
>(dy1
*a
)+dx1
) /2;
3161 aNewCenter
.AdjustX(nNewRad
);
3162 nPntAngle
=GetAngle(aPnt
-aNewCenter
);
3166 a
=static_cast<double>(dx1
)/static_cast<double>(dy1
); // slope of the radius
3167 nNewRad
=(static_cast<tools::Long
>(dx1
*a
)+dy1
) /2;
3168 aNewCenter
.AdjustY(nNewRad
);
3169 nPntAngle
=GetAngle(aPnt
-aNewCenter
)-9000_deg100
;
3176 if (bRgt
) nPntAngle
+= 18000_deg100
;
3177 if (bLft
) nPntAngle
= 18000_deg100
- nPntAngle
;
3178 if (bLwr
) nPntAngle
=- nPntAngle
;
3182 if (bRgt
) nPntAngle
= -nPntAngle
;
3183 if (bUpr
) nPntAngle
= 18000_deg100
- nPntAngle
;
3184 if (bLwr
) nPntAngle
+= 18000_deg100
;
3187 nPntAngle
=NormAngle36000(nPntAngle
);
3191 if (nNewRad
<0) nPntAngle
+= 18000_deg100
;
3192 if (bVertical
) nPntAngle
= 18000_deg100
- nPntAngle
;
3193 nPntAngle
= NormAngle18000(nPntAngle
);
3194 nPntAngle
= abs(nPntAngle
);
3197 double nCircumference
= 2 * std::abs(nNewRad
) * M_PI
;
3201 tools::Long nMul
=static_cast<tools::Long
>(nCircumference
* NormAngle36000(nPntAngle
).get() / 36000.0);
3206 aNewFract
=Fraction(nMul
,nMarkSize
);
3211 nAngle
= Degree100(static_cast<tools::Long
>((nMarkSize
*360/nCircumference
)*100)/2);
3213 if (nAngle
==0_deg100
)
3218 if (nAngle
==0_deg100
|| nNewRad
==0)
3224 if (!bValid
&& bResize
)
3226 tools::Long nMul
=bVertical
? dy1
: dx1
;
3231 tools::Long nDiv
=nMarkSize
;
3236 nMul
= std::abs(nMul
);
3239 aNewFract
=Fraction(nMul
,nDiv
);
3242 if (aNewCenter
==aCenter
&& bNewContortion
==bContortion
&& aNewFract
==aFact
&&
3243 bNewMoveOnly
== getMoveOnly() && bNewRotate
==bRotate
&& eNewMode
==eMode
)
3247 setMoveOnly(bNewMoveOnly
);
3250 bContortion
=bNewContortion
;
3253 aRad
=Point(nNewRad
,nNewRad
);
3254 bResize
=aFact
!=Fraction(1,1) && aFact
.GetDenominator()!=0 && aFact
.IsValid();
3255 DragStat().NextMove(aPnt
);
3259 void SdrDragCrook::applyCurrentTransformationToSdrObject(SdrObject
& rTarget
)
3261 const bool bDoResize(aFact
!=Fraction(1,1));
3262 const bool bDoCrook(aCenter
!=aMarkCenter
&& aRad
.X()!=0 && aRad
.Y()!=0);
3264 if (!(bDoCrook
|| bDoResize
))
3269 Fraction
aFact1(1,1);
3275 rTarget
.Resize(aCenter
,aFact1
,aFact
);
3279 rTarget
.Resize(aCenter
,aFact
,aFact1
);
3284 Point
aCtr0(rTarget
.GetSnapRect().Center());
3289 ResizePoint(aCtr1
,aCenter
,aFact1
,aFact
);
3293 ResizePoint(aCtr1
,aCenter
,aFact
,aFact1
);
3296 Size
aSiz(aCtr1
.X()-aCtr0
.X(),aCtr1
.Y()-aCtr0
.Y());
3304 const tools::Rectangle
aLocalMarkRect(getSdrDragView().GetMarkedObjRect());
3305 const bool bLocalRotate(!bContortion
&& eMode
== SdrCrookMode::Rotate
&& getSdrDragView().IsRotateAllowed());
3307 SdrEditView::ImpCrookObj(&rTarget
,aCenter
,aRad
,eMode
,bVertical
,!bContortion
,bLocalRotate
,aLocalMarkRect
);
3311 void SdrDragCrook::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon
& rTarget
)
3313 // use helper derived from old stuff
3314 MovAllPoints(rTarget
);
3317 bool SdrDragCrook::EndSdrDrag(bool bCopy
)
3321 if (bResize
&& aFact
==Fraction(1,1))
3324 const bool bUndo
= getSdrDragView().IsUndoEnabled();
3326 bool bDoCrook
=aCenter
!=aMarkCenter
&& aRad
.X()!=0 && aRad
.Y()!=0;
3328 if (bDoCrook
|| bResize
)
3330 if (bResize
&& bUndo
)
3332 OUString aStr
= ImpGetDescriptionStr(!bContortion
?STR_EditCrook
:STR_EditCrookContortion
);
3335 aStr
+= SvxResId(STR_EditWithCopy
);
3337 getSdrDragView().BegUndo(aStr
);
3342 Fraction
aFact1(1,1);
3347 getSdrDragView().ResizeMarkedObj(aCenter
,aFact1
,aFact
,bCopy
);
3349 getSdrDragView().ResizeMarkedObj(aCenter
,aFact
,aFact1
,bCopy
);
3354 getSdrDragView().CopyMarkedObj();
3356 const SdrMarkList
& rMarkList
= getSdrDragView().GetMarkedObjectList();
3357 const size_t nMarkCount
=rMarkList
.GetMarkCount();
3359 for (size_t nm
=0; nm
<nMarkCount
; ++nm
)
3361 SdrMark
* pM
=rMarkList
.GetMark(nm
);
3362 SdrObject
* pO
=pM
->GetMarkedSdrObj();
3363 Point
aCtr0(pO
->GetSnapRect().Center());
3367 ResizePoint(aCtr1
,aCenter
,aFact1
,aFact
);
3369 ResizePoint(aCtr1
,aCenter
,aFact
,aFact1
);
3371 Size
aSiz(aCtr1
.X()-aCtr0
.X(),aCtr1
.Y()-aCtr0
.Y());
3373 AddUndo(getSdrDragView().GetModel().GetSdrUndoFactory().CreateUndoMoveObject(*pO
,aSiz
));
3383 getSdrDragView().CrookMarkedObj(aCenter
,aRad
,eMode
,bVertical
,!bContortion
,bCopy
);
3386 if (bResize
&& bUndo
)
3387 getSdrDragView().EndUndo();
3395 PointerStyle
SdrDragCrook::GetSdrDragPointer() const
3397 return PointerStyle::Crook
;
3401 SdrDragDistort::SdrDragDistort(SdrDragView
& rNewView
)
3402 : SdrDragMethod(rNewView
),
3404 bContortionAllowed(false),
3405 bNoContortionAllowed(false),
3410 OUString
SdrDragDistort::GetSdrDragComment() const
3412 OUString aStr
= ImpGetDescriptionStr(STR_DragMethDistort
)
3414 + getSdrDragView().GetModel().GetMetricString(DragStat().GetDX())
3416 + getSdrDragView().GetModel().GetMetricString(DragStat().GetDY())
3419 if(getSdrDragView().IsDragWithCopy())
3420 aStr
+= SvxResId(STR_EditWithCopy
);
3424 void SdrDragDistort::createSdrDragEntries()
3426 // Add extended frame raster first, so it will be behind objects
3427 if(getSdrDragView().GetSdrPageView())
3429 const basegfx::B2DPolyPolygon
aDragRaster(impCreateDragRaster(*getSdrDragView().GetSdrPageView(), GetMarkedRect()));
3431 if(aDragRaster
.count())
3433 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntryPolyPolygon(aDragRaster
)));
3438 SdrDragMethod::createSdrDragEntries();
3441 bool SdrDragDistort::BeginSdrDrag()
3443 bContortionAllowed
=getSdrDragView().IsDistortAllowed();
3444 bNoContortionAllowed
=getSdrDragView().IsDistortAllowed(true);
3446 if (bContortionAllowed
|| bNoContortionAllowed
)
3448 SdrHdlKind eKind
=GetDragHdlKind();
3451 if (eKind
==SdrHdlKind::UpperLeft
) nPolyPt
=0;
3452 if (eKind
==SdrHdlKind::UpperRight
) nPolyPt
=1;
3453 if (eKind
==SdrHdlKind::LowerRight
) nPolyPt
=2;
3454 if (eKind
==SdrHdlKind::LowerLeft
) nPolyPt
=3;
3455 if (nPolyPt
>3) return false;
3457 aMarkRect
=GetMarkedRect();
3458 aDistortedRect
=XPolygon(aMarkRect
);
3468 void SdrDragDistort::MovAllPoints(basegfx::B2DPolyPolygon
& rTarget
)
3473 SdrPageView
* pPV
= getSdrDragView().GetSdrPageView();
3475 if(pPV
&& pPV
->HasMarkedObjPageView())
3477 basegfx::B2DPolyPolygon
aDragPolygon(rTarget
);
3478 const basegfx::B2DRange aOriginalRange
= vcl::unotools::b2DRectangleFromRectangle(aMarkRect
);
3479 const basegfx::B2DPoint
aTopLeft(aDistortedRect
[0].X(), aDistortedRect
[0].Y());
3480 const basegfx::B2DPoint
aTopRight(aDistortedRect
[1].X(), aDistortedRect
[1].Y());
3481 const basegfx::B2DPoint
aBottomLeft(aDistortedRect
[3].X(), aDistortedRect
[3].Y());
3482 const basegfx::B2DPoint
aBottomRight(aDistortedRect
[2].X(), aDistortedRect
[2].Y());
3484 rTarget
= basegfx::utils::distort(aDragPolygon
, aOriginalRange
, aTopLeft
, aTopRight
, aBottomLeft
, aBottomRight
);
3488 void SdrDragDistort::MoveSdrDrag(const Point
& rPnt
)
3490 if (!DragStat().CheckMinMoved(rPnt
))
3493 Point
aPnt(GetSnapPos(rPnt
));
3495 if (getSdrDragView().IsOrtho())
3496 OrthoDistance8(DragStat().GetStart(),aPnt
,getSdrDragView().IsBigOrtho());
3498 bool bNewContortion
=(bContortionAllowed
&& !getSdrDragView().IsCrookNoContortion()) || !bNoContortionAllowed
;
3500 if (bNewContortion
!=bContortion
|| aDistortedRect
[nPolyPt
]!=aPnt
)
3503 aDistortedRect
[nPolyPt
]=aPnt
;
3504 bContortion
=bNewContortion
;
3505 DragStat().NextMove(aPnt
);
3510 bool SdrDragDistort::EndSdrDrag(bool bCopy
)
3513 bool bDoDistort
=DragStat().GetDX()!=0 || DragStat().GetDY()!=0;
3517 getSdrDragView().DistortMarkedObj(aMarkRect
,aDistortedRect
,!bContortion
,bCopy
);
3524 PointerStyle
SdrDragDistort::GetSdrDragPointer() const
3526 return PointerStyle::RefHand
;
3529 void SdrDragDistort::applyCurrentTransformationToSdrObject(SdrObject
& rTarget
)
3531 const bool bDoDistort(DragStat().GetDX()!=0 || DragStat().GetDY()!=0);
3535 SdrEditView::ImpDistortObj(&rTarget
, aMarkRect
, aDistortedRect
, !bContortion
);
3539 void SdrDragDistort::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon
& rTarget
)
3541 // use helper derived from old stuff
3542 MovAllPoints(rTarget
);
3546 SdrDragCrop::SdrDragCrop(SdrDragView
& rNewView
)
3547 : SdrDragObjOwn(rNewView
)
3549 // switch off solid dragging for crop; it just makes no sense since showing
3550 // a 50% transparent object above the original will not be visible
3551 setSolidDraggingActive(false);
3554 OUString
SdrDragCrop::GetSdrDragComment() const
3556 OUString aStr
= ImpGetDescriptionStr(STR_DragMethCrop
)
3558 + getSdrDragView().GetModel().GetMetricString(DragStat().GetDX())
3560 + getSdrDragView().GetModel().GetMetricString(DragStat().GetDY())
3563 if(getSdrDragView().IsDragWithCopy())
3564 aStr
+= SvxResId(STR_EditWithCopy
);
3568 bool SdrDragCrop::BeginSdrDrag()
3571 bool bRetval(SdrDragObjOwn::BeginSdrDrag());
3575 // we need the DragHdl, break if not there
3582 bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/)
3586 if(0 == DragStat().GetDX() && 0 == DragStat().GetDY())
3592 const SdrMarkList
& rMarkList
= getSdrDragView().GetMarkedObjectList();
3594 if(1 != rMarkList
.GetMarkCount())
3596 // Crop only with single Object selected
3600 // prepare for SdrGrafObj or others. This code has to work with usual
3601 // SdrGrafObj's from Draw/Impress/Calc, but also with SdrObjects from
3602 // Writer. It would be better to handle this in Writer directly, but
3603 // there are currently no easy mechanisms to plug an alternative interaction
3605 SdrObject
* pSdrObject
= rMarkList
.GetMark(0)->GetMarkedSdrObj();
3606 rtl::Reference
<SdrObject
> pFullDragClone
;
3607 bool bExternal(false);
3608 SdrObject
* pExternalSdrObject(nullptr);
3610 // RotGrfFlyFrame: Crop decision for DrawingLayer/Writer now
3611 // locally, no two-in-one methods any more
3612 if (nullptr != pSdrObject
&& dynamic_cast< const SdrGrafObj
* >(pSdrObject
) == nullptr)
3614 // If Writer, get the already offered for interaction SdrGrafObj
3615 // and set up for using that replacement object that contains the
3616 // real transformation. That SdrObject is owned and has to be deleted,
3617 // so use a std::unique_ptr with special handling for the protected
3618 // SDrObject destructor
3619 pFullDragClone
= pSdrObject
->getFullDragClone();
3621 if(dynamic_cast< SdrGrafObj
* >(pFullDragClone
.get()))
3624 pExternalSdrObject
= pSdrObject
;
3625 pSdrObject
= pFullDragClone
.get();
3629 // get and check for SdrGrafObj now
3630 SdrGrafObj
* pObj
= dynamic_cast<SdrGrafObj
*>( pSdrObject
);
3637 // no undo for external needed, done there
3638 const bool bUndo(!bExternal
&& getSdrDragView().IsUndoEnabled());
3642 OUString aUndoStr
= ImpGetDescriptionStr(STR_DragMethCrop
);
3644 getSdrDragView().BegUndo( aUndoStr
);
3645 getSdrDragView().AddUndo(getSdrDragView().GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pObj
));
3646 // also need attr undo, the SdrGrafCropItem will be changed
3647 getSdrDragView().AddUndo(getSdrDragView().GetModel().GetSdrUndoFactory().CreateUndoAttrObject(*pObj
));
3650 // get the original objects transformation
3651 basegfx::B2DHomMatrix aOriginalMatrix
;
3652 basegfx::B2DPolyPolygon aPolyPolygon
;
3653 bool bShearCorrected(false);
3654 pObj
->TRGetBaseGeometry(aOriginalMatrix
, aPolyPolygon
);
3656 { // correct shear, it comes currently mirrored from TRGetBaseGeometry, can be removed with aw080
3657 const basegfx::utils::B2DHomMatrixBufferedDecompose
aTmpDecomp(aOriginalMatrix
);
3659 if(!basegfx::fTools::equalZero(aTmpDecomp
.getShearX()))
3661 bShearCorrected
= true;
3662 aOriginalMatrix
= basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
3663 aTmpDecomp
.getScale(),
3664 -aTmpDecomp
.getShearX(),
3665 aTmpDecomp
.getRotate(),
3666 aTmpDecomp
.getTranslate());
3670 // generate start point of original drag vector in unit coordinates (the
3671 // vis-a-vis of the drag point)
3672 basegfx::B2DPoint
aLocalStart(0.0, 0.0);
3673 bool bOnAxis(false);
3675 switch(GetDragHdlKind())
3677 case SdrHdlKind::UpperLeft
: aLocalStart
.setX(1.0); aLocalStart
.setY(1.0); break;
3678 case SdrHdlKind::Upper
: aLocalStart
.setX(0.5); aLocalStart
.setY(1.0); bOnAxis
= true; break;
3679 case SdrHdlKind::UpperRight
: aLocalStart
.setX(0.0); aLocalStart
.setY(1.0); break;
3680 case SdrHdlKind::Left
: aLocalStart
.setX(1.0); aLocalStart
.setY(0.5); bOnAxis
= true; break;
3681 case SdrHdlKind::Right
: aLocalStart
.setX(0.0); aLocalStart
.setY(0.5); bOnAxis
= true; break;
3682 case SdrHdlKind::LowerLeft
: aLocalStart
.setX(1.0); aLocalStart
.setY(0.0); break;
3683 case SdrHdlKind::Lower
: aLocalStart
.setX(0.5); aLocalStart
.setY(0.0); bOnAxis
= true; break;
3684 case SdrHdlKind::LowerRight
: aLocalStart
.setX(0.0); aLocalStart
.setY(0.0); break;
3688 // create the current drag position in unit coordinates. To get there,
3689 // transform back the DragPoint to UnitCoordinates
3690 basegfx::B2DHomMatrix
aInverse(aOriginalMatrix
);
3692 basegfx::B2DPoint
aLocalCurrent(aInverse
* basegfx::B2DPoint(DragStat().GetNow().X(), DragStat().GetNow().Y()));
3694 // if one of the edge handles is used, limit to X or Y drag only
3697 if(basegfx::fTools::equal(aLocalStart
.getX(), 0.5))
3699 aLocalCurrent
.setX(aLocalStart
.getX());
3703 aLocalCurrent
.setY(aLocalStart
.getY());
3707 // create internal change in unit coordinates
3708 basegfx::B2DHomMatrix aDiscreteChangeMatrix
;
3710 if(!basegfx::fTools::equal(aLocalCurrent
.getX(), aLocalStart
.getX()))
3712 if(aLocalStart
.getX() < 0.5)
3714 aDiscreteChangeMatrix
.scale(aLocalCurrent
.getX(), 1.0);
3718 aDiscreteChangeMatrix
.scale(1.0 - aLocalCurrent
.getX(), 1.0);
3719 aDiscreteChangeMatrix
.translate(aLocalCurrent
.getX(), 0.0);
3723 if(!basegfx::fTools::equal(aLocalCurrent
.getY(), aLocalStart
.getY()))
3725 if(aLocalStart
.getY() < 0.5)
3727 aDiscreteChangeMatrix
.scale(1.0, aLocalCurrent
.getY());
3731 aDiscreteChangeMatrix
.scale(1.0, 1.0 - aLocalCurrent
.getY());
3732 aDiscreteChangeMatrix
.translate(0.0, aLocalCurrent
.getY());
3736 // We now have the whole executed Crop in UnitCoordinates in
3737 // aDiscreteChangeMatrix, go to concrete sizes now.
3738 // Create the unrotated original rectangle and the unrotated modified
3739 // rectangle as Ranges
3740 const basegfx::utils::B2DHomMatrixBufferedDecompose
aOriginalMatrixDecomp(aOriginalMatrix
);
3742 // prepare unsheared/unrotated versions of the old and new transformation
3743 const basegfx::B2DHomMatrix
aOriginalMatrixNoShearNoRotate(
3744 basegfx::utils::createScaleTranslateB2DHomMatrix(
3745 basegfx::absolute(aOriginalMatrixDecomp
.getScale()),
3746 aOriginalMatrixDecomp
.getTranslate()));
3748 // create the ranges for these
3749 basegfx::B2DRange
aRangeOriginalNoShearNoRotate(0.0, 0.0, 1.0, 1.0);
3750 basegfx::B2DRange
aRangeNewNoShearNoRotate(0.0, 0.0, 1.0, 1.0);
3751 aRangeOriginalNoShearNoRotate
.transform(aOriginalMatrixNoShearNoRotate
);
3752 aRangeNewNoShearNoRotate
.transform(aOriginalMatrixNoShearNoRotate
* aDiscreteChangeMatrix
);
3756 // With aLocalStart point (opposed to dragged point), X scale and Y scale,
3757 // we call crop (virtual method) on pSdrObject which calls VirtFlyDrawObj
3758 // crop. Use aLocalStart unchanged, so being relative to the Crop-Action,
3759 // the called instance knows best how to use it
3760 const double fScaleX(aRangeNewNoShearNoRotate
.getWidth() / aRangeOriginalNoShearNoRotate
.getWidth());
3761 const double fScaleY(aRangeNewNoShearNoRotate
.getHeight() / aRangeOriginalNoShearNoRotate
.getHeight());
3763 pExternalSdrObject
->Crop(
3770 // prepare matrix to apply to object; evtl. back-correct shear
3771 basegfx::B2DHomMatrix
aNewObjectMatrix(aOriginalMatrix
* aDiscreteChangeMatrix
);
3775 // back-correct shear
3776 const basegfx::utils::B2DHomMatrixBufferedDecompose
aTmpDecomp(aNewObjectMatrix
);
3778 aNewObjectMatrix
= basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
3779 aTmpDecomp
.getScale(),
3780 -aTmpDecomp
.getShearX(),
3781 aTmpDecomp
.getRotate(),
3782 aTmpDecomp
.getTranslate());
3785 // apply change to object by applying the unit coordinate change followed
3786 // by the original change
3787 pObj
->TRSetBaseGeometry(aNewObjectMatrix
, aPolyPolygon
);
3789 // extract the old Rectangle structures
3790 tools::Rectangle
aOldRect(
3791 basegfx::fround
<tools::Long
>(aRangeOriginalNoShearNoRotate
.getMinX()),
3792 basegfx::fround
<tools::Long
>(aRangeOriginalNoShearNoRotate
.getMinY()),
3793 basegfx::fround
<tools::Long
>(aRangeOriginalNoShearNoRotate
.getMaxX()),
3794 basegfx::fround
<tools::Long
>(aRangeOriginalNoShearNoRotate
.getMaxY()));
3795 tools::Rectangle
aNewRect(
3796 basegfx::fround
<tools::Long
>(aRangeNewNoShearNoRotate
.getMinX()),
3797 basegfx::fround
<tools::Long
>(aRangeNewNoShearNoRotate
.getMinY()),
3798 basegfx::fround
<tools::Long
>(aRangeNewNoShearNoRotate
.getMaxX()),
3799 basegfx::fround
<tools::Long
>(aRangeNewNoShearNoRotate
.getMaxY()));
3801 // continue with the old original stuff
3802 if (!aOldRect
.GetWidth() || !aOldRect
.GetHeight())
3804 throw o3tl::divide_by_zero();
3807 if((pObj
->GetGraphicType() == GraphicType::NONE
) || (pObj
->GetGraphicType() == GraphicType::Default
))
3812 const GraphicObject
& rGraphicObject(pObj
->GetGraphicObject());
3813 // tdf#117145 Usually Writer will go the bExternal path (see above), but more correct for
3814 // the future is to use the MapMode from the SdrModel/SfxItemPool if the Writer's current
3815 // special handling should be unified to this path in the future. Usually it *should* be
3816 // MapUnit::Map100thMM, but better do not mix up Units.
3817 // Checked now what SwVirtFlyDrawObj::NbcCrop is doing - it calculates everything forced
3818 // to MapUnit::Map100thMM, but extracts/packs Twips to the used SdrGrafCropItem in Writer.
3819 const MapMode
aMapModePool(pObj
->getSdrModelFromSdrObject().GetItemPool().GetMetric(0));
3820 Size
aGraphicSize(rGraphicObject
.GetPrefSize());
3822 if(MapUnit::MapPixel
== rGraphicObject
.GetPrefMapMode().GetMapUnit())
3824 aGraphicSize
= Application::GetDefaultDevice()->PixelToLogic(aGraphicSize
, aMapModePool
);
3828 aGraphicSize
= OutputDevice::LogicToLogic(aGraphicSize
, rGraphicObject
.GetPrefMapMode(), aMapModePool
);
3831 if(0 == aGraphicSize
.Width() || 0 == aGraphicSize
.Height())
3836 const SdrGrafCropItem
& rOldCrop
= pObj
->GetMergedItem(SDRATTR_GRAFCROP
);
3837 double fScaleX
= ( aGraphicSize
.Width() - rOldCrop
.GetLeft() - rOldCrop
.GetRight() ) / static_cast<double>(aOldRect
.GetWidth());
3838 double fScaleY
= ( aGraphicSize
.Height() - rOldCrop
.GetTop() - rOldCrop
.GetBottom() ) / static_cast<double>(aOldRect
.GetHeight());
3840 sal_Int32 nDiffLeft
= aNewRect
.Left() - aOldRect
.Left();
3841 sal_Int32 nDiffTop
= aNewRect
.Top() - aOldRect
.Top();
3842 sal_Int32 nDiffRight
= aNewRect
.Right() - aOldRect
.Right();
3843 sal_Int32 nDiffBottom
= aNewRect
.Bottom() - aOldRect
.Bottom();
3845 if(pObj
->IsMirrored())
3847 // mirrored X or Y, for old stuff, exchange X
3849 sal_Int32
nTmp(nDiffLeft
);
3850 nDiffLeft
= -nDiffRight
;
3854 sal_Int32 nLeftCrop
= static_cast<sal_Int32
>( rOldCrop
.GetLeft() + nDiffLeft
* fScaleX
);
3855 sal_Int32 nTopCrop
= static_cast<sal_Int32
>( rOldCrop
.GetTop() + nDiffTop
* fScaleY
);
3856 sal_Int32 nRightCrop
= static_cast<sal_Int32
>( rOldCrop
.GetRight() - nDiffRight
* fScaleX
);
3857 sal_Int32 nBottomCrop
= static_cast<sal_Int32
>( rOldCrop
.GetBottom() - nDiffBottom
* fScaleY
);
3859 SfxItemPool
& rPool
= getSdrDragView().GetModel().GetItemPool();
3860 SfxItemSetFixed
<SDRATTR_GRAFCROP
, SDRATTR_GRAFCROP
> aSet( rPool
);
3861 aSet
.Put( SdrGrafCropItem( nLeftCrop
, nTopCrop
, nRightCrop
, nBottomCrop
) );
3862 getSdrDragView().SetAttributes( aSet
, false );
3867 getSdrDragView().EndUndo();
3873 PointerStyle
SdrDragCrop::GetSdrDragPointer() const
3875 return PointerStyle::Crop
;
3878 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */