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 <vcl/canvastools.hxx>
25 #include <vcl/svapp.hxx>
26 #include <vcl/settings.hxx>
27 #include <vcl/ptrstyle.hxx>
28 #include <svx/xpoly.hxx>
29 #include <svx/svdtrans.hxx>
30 #include <svx/svdundo.hxx>
31 #include <svx/svdmark.hxx>
32 #include <svx/svdpagv.hxx>
33 #include <svx/svddrgv.hxx>
34 #include <svx/svdograf.hxx>
35 #include <svx/strings.hrc>
36 #include <svx/dialmgr.hxx>
37 #include <svx/sdgcpitm.hxx>
38 #include <svx/sdooitm.hxx>
39 #include <svx/sdtagitm.hxx>
40 #include <basegfx/polygon/b2dpolygon.hxx>
41 #include <basegfx/polygon/b2dpolygontools.hxx>
42 #include <svx/sdr/overlay/overlaymanager.hxx>
43 #include <sdr/overlay/overlayrollingrectangle.hxx>
44 #include <svx/sdrpagewindow.hxx>
45 #include <svx/sdrpaintwindow.hxx>
46 #include <basegfx/matrix/b2dhommatrix.hxx>
47 #include <basegfx/polygon/b2dpolypolygontools.hxx>
48 #include <svx/sdr/contact/viewcontact.hxx>
49 #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
50 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
51 #include <svx/sdr/contact/objectcontact.hxx>
52 #include <svx/svditer.hxx>
53 #include <svx/svdopath.hxx>
54 #include <svx/polypolygoneditor.hxx>
55 #include <drawinglayer/primitive2d/PolyPolygonSelectionPrimitive2D.hxx>
56 #include <drawinglayer/primitive2d/PolyPolygonMarkerPrimitive2D.hxx>
57 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
58 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
59 #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
60 #include <sdr/primitive2d/sdrattributecreator.hxx>
61 #include <sdr/primitive2d/sdrdecompositiontools.hxx>
62 #include <sdr/primitive2d/sdrprimitivetools.hxx>
63 #include <basegfx/matrix/b2dhommatrixtools.hxx>
64 #include <drawinglayer/attribute/sdrlineattribute.hxx>
65 #include <drawinglayer/attribute/sdrlinestartendattribute.hxx>
66 #include <svl/itempool.hxx>
67 #include <comphelper/lok.hxx>
72 SdrDragEntry::SdrDragEntry()
73 : mbAddToTransparent(false)
77 SdrDragEntry::~SdrDragEntry()
82 SdrDragEntryPolyPolygon::SdrDragEntryPolyPolygon(const basegfx::B2DPolyPolygon
& rOriginalPolyPolygon
)
84 maOriginalPolyPolygon(rOriginalPolyPolygon
)
88 SdrDragEntryPolyPolygon::~SdrDragEntryPolyPolygon()
92 drawinglayer::primitive2d::Primitive2DContainer
SdrDragEntryPolyPolygon::createPrimitive2DSequenceInCurrentState(SdrDragMethod
& rDragMethod
)
94 drawinglayer::primitive2d::Primitive2DContainer aRetval
;
96 if(maOriginalPolyPolygon
.count())
98 basegfx::B2DPolyPolygon
aCopy(maOriginalPolyPolygon
);
99 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer
;
101 rDragMethod
.applyCurrentTransformationToPolyPolygon(aCopy
);
102 basegfx::BColor
aColA(aSvtOptionsDrawinglayer
.GetStripeColorA().getBColor());
103 basegfx::BColor
aColB(aSvtOptionsDrawinglayer
.GetStripeColorB().getBColor());
104 const double fStripeLength(aSvtOptionsDrawinglayer
.GetStripeLength());
106 if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
108 aColA
= aColB
= Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
113 aRetval
[0] = new drawinglayer::primitive2d::PolyPolygonMarkerPrimitive2D(
119 const basegfx::BColor
aHilightColor(aSvtOptionsDrawinglayer
.getHilightColor().getBColor());
120 const double fTransparence(aSvtOptionsDrawinglayer
.GetTransparentSelectionPercent() * 0.01);
122 aRetval
[1] = new drawinglayer::primitive2d::PolyPolygonSelectionPrimitive2D(
134 SdrDragEntrySdrObject::SdrDragEntrySdrObject(
135 const SdrObject
& rOriginal
,
138 maOriginal(rOriginal
),
141 // add SdrObject parts to transparent overlay stuff
142 setAddToTransparent(true);
145 SdrDragEntrySdrObject::~SdrDragEntrySdrObject()
149 void SdrDragEntrySdrObject::prepareCurrentState(SdrDragMethod
& rDragMethod
)
151 // for the moment, i need to re-create the clone in all cases. I need to figure
152 // out when clone and original have the same class, so that i can use operator=
159 mxClone
= maOriginal
.getFullDragClone();
161 // apply original transformation, implemented at the DragMethods
162 rDragMethod
.applyCurrentTransformationToSdrObject(*mxClone
);
166 drawinglayer::primitive2d::Primitive2DContainer
SdrDragEntrySdrObject::createPrimitive2DSequenceInCurrentState(SdrDragMethod
&)
168 const SdrObject
* pSource
= &maOriginal
;
170 if(mbModify
&& mxClone
)
172 // choose source for geometry data
173 pSource
= mxClone
.get();
176 // use the view-independent primitive representation (without
177 // evtl. GridOffset, that may be applied to the DragEntry individually)
178 return pSource
->GetViewContact().getViewIndependentPrimitive2DContainer();
182 SdrDragEntryPrimitive2DSequence::SdrDragEntryPrimitive2DSequence(
183 const drawinglayer::primitive2d::Primitive2DContainer
& rSequence
)
185 maPrimitive2DSequence(rSequence
)
187 // add parts to transparent overlay stuff if necessary
188 setAddToTransparent(true);
191 SdrDragEntryPrimitive2DSequence::~SdrDragEntryPrimitive2DSequence()
195 drawinglayer::primitive2d::Primitive2DContainer
SdrDragEntryPrimitive2DSequence::createPrimitive2DSequenceInCurrentState(SdrDragMethod
& rDragMethod
)
197 drawinglayer::primitive2d::Primitive2DReference
aTransformPrimitive2D(
198 new drawinglayer::primitive2d::TransformPrimitive2D(
199 rDragMethod
.getCurrentTransformation(),
200 maPrimitive2DSequence
));
202 return drawinglayer::primitive2d::Primitive2DContainer
{ aTransformPrimitive2D
};
206 SdrDragEntryPointGlueDrag::SdrDragEntryPointGlueDrag(const std::vector
< basegfx::B2DPoint
>& rPositions
, bool bIsPointDrag
)
207 : maPositions(rPositions
),
208 mbIsPointDrag(bIsPointDrag
)
210 // add SdrObject parts to transparent overlay stuff
211 setAddToTransparent(true);
214 SdrDragEntryPointGlueDrag::~SdrDragEntryPointGlueDrag()
218 drawinglayer::primitive2d::Primitive2DContainer
SdrDragEntryPointGlueDrag::createPrimitive2DSequenceInCurrentState(SdrDragMethod
& rDragMethod
)
220 drawinglayer::primitive2d::Primitive2DContainer aRetval
;
222 if(!maPositions
.empty())
224 basegfx::B2DPolygon aPolygon
;
226 for(auto const & a
: maPositions
)
231 basegfx::B2DPolyPolygon
aPolyPolygon(aPolygon
);
233 rDragMethod
.applyCurrentTransformationToPolyPolygon(aPolyPolygon
);
235 const basegfx::B2DPolygon
aTransformed(aPolyPolygon
.getB2DPolygon(0));
236 std::vector
< basegfx::B2DPoint
> aTransformedPositions
;
238 aTransformedPositions
.reserve(aTransformed
.count());
240 for(sal_uInt32 a
= 0; a
< aTransformed
.count(); a
++)
242 aTransformedPositions
.push_back(aTransformed
.getB2DPoint(a
));
247 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer
;
248 basegfx::BColor
aColor(aSvtOptionsDrawinglayer
.GetStripeColorA().getBColor());
250 if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
252 aColor
= Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
255 drawinglayer::primitive2d::Primitive2DReference
aMarkerArrayPrimitive2D(
256 new drawinglayer::primitive2d::MarkerArrayPrimitive2D(aTransformedPositions
,
257 drawinglayer::primitive2d::createDefaultCross_3x3(aColor
)));
259 aRetval
= drawinglayer::primitive2d::Primitive2DContainer
{ aMarkerArrayPrimitive2D
};
263 drawinglayer::primitive2d::Primitive2DReference
aMarkerArrayPrimitive2D(
264 new drawinglayer::primitive2d::MarkerArrayPrimitive2D(aTransformedPositions
,
265 SdrHdl::createGluePointBitmap()));
266 aRetval
= drawinglayer::primitive2d::Primitive2DContainer
{ aMarkerArrayPrimitive2D
};
274 void SdrDragMethod::resetSdrDragEntries()
276 // clear entries; creation is on demand
277 clearSdrDragEntries();
280 basegfx::B2DRange
SdrDragMethod::getCurrentRange() const
282 return maOverlayObjectList
.getBaseRange();
285 void SdrDragMethod::clearSdrDragEntries()
287 maSdrDragEntries
.clear();
290 void SdrDragMethod::addSdrDragEntry(std::unique_ptr
<SdrDragEntry
> pNew
)
293 maSdrDragEntries
.push_back(std::move(pNew
));
296 void SdrDragMethod::createSdrDragEntries()
298 if(!(getSdrDragView().GetSdrPageView() && getSdrDragView().GetSdrPageView()->HasMarkedObjPageView()))
301 if(getSdrDragView().IsDraggingPoints())
303 createSdrDragEntries_PointDrag();
305 else if(getSdrDragView().IsDraggingGluePoints())
307 createSdrDragEntries_GlueDrag();
311 if(getSolidDraggingActive())
313 createSdrDragEntries_SolidDrag();
317 createSdrDragEntries_PolygonDrag();
322 void SdrDragMethod::createSdrDragEntryForSdrObject(const SdrObject
& rOriginal
)
324 // add full object drag; Clone() at the object has to work
326 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntrySdrObject(rOriginal
, true/*bModify*/)));
329 void SdrDragMethod::insertNewlyCreatedOverlayObjectForSdrDragMethod(
330 std::unique_ptr
<sdr::overlay::OverlayObject
> pOverlayObject
,
331 const sdr::contact::ObjectContact
& rObjectContact
,
332 sdr::overlay::OverlayManager
& rOverlayManager
)
334 // check if we have an OverlayObject
340 // add to OverlayManager
341 rOverlayManager
.add(*pOverlayObject
);
343 // Add GridOffset for non-linear ViewToDevice transformation (calc)
344 if(rObjectContact
.supportsGridOffsets())
346 const basegfx::B2DRange
& rNewRange(pOverlayObject
->getBaseRange());
348 if(!rNewRange
.isEmpty())
350 basegfx::B2DVector
aOffset(0.0, 0.0);
351 rObjectContact
.calculateGridOffsetForB2DRange(aOffset
, rNewRange
);
353 if(!aOffset
.equalZero())
355 pOverlayObject
->setOffset(aOffset
);
360 // add to local OverlayObjectList - ownership change (!)
361 maOverlayObjectList
.append(std::move(pOverlayObject
));
364 void SdrDragMethod::createSdrDragEntries_SolidDrag()
366 const size_t nMarkCount(getSdrDragView().GetMarkedObjectCount());
367 SdrPageView
* pPV
= getSdrDragView().GetSdrPageView();
372 for(size_t a
= 0; a
< nMarkCount
; ++a
)
374 SdrMark
* pM
= getSdrDragView().GetSdrMarkByIndex(a
);
376 if(pM
->GetPageView() == pPV
)
378 const SdrObject
* pObject
= pM
->GetMarkedSdrObj();
382 if(pPV
->PageWindowCount())
384 SdrObjListIter
aIter(*pObject
);
386 while(aIter
.IsMore())
388 SdrObject
* pCandidate
= aIter
.Next();
392 const bool bSuppressFullDrag(!pCandidate
->supportsFullDrag());
393 bool bAddWireframe(bSuppressFullDrag
);
395 if(!bAddWireframe
&& !pCandidate
->HasLineStyle())
397 // add wireframe for objects without outline
398 bAddWireframe
= true;
401 if(!bSuppressFullDrag
)
403 // add full object drag; Clone() at the object has to work
405 createSdrDragEntryForSdrObject(*pCandidate
);
410 // when dragging a 50% transparent copy of a filled or not filled object without
411 // outline, this is normally hard to see. Add extra wireframe in that case. This
412 // works nice e.g. with text frames etc.
413 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntryPolyPolygon(pCandidate
->TakeXorPoly())));
423 void SdrDragMethod::createSdrDragEntries_PolygonDrag()
425 const size_t nMarkCount(getSdrDragView().GetMarkedObjectCount());
426 bool bNoPolygons(getSdrDragView().IsNoDragXorPolys() || nMarkCount
> SdrDragView::GetDragXorPolyLimit());
427 basegfx::B2DPolyPolygon aResult
;
428 sal_uInt32
nPointCount(0);
430 for(size_t a
= 0; !bNoPolygons
&& a
< nMarkCount
; ++a
)
432 SdrMark
* pM
= getSdrDragView().GetSdrMarkByIndex(a
);
434 if(pM
->GetPageView() == getSdrDragView().GetSdrPageView())
436 const basegfx::B2DPolyPolygon
aNewPolyPolygon(pM
->GetMarkedSdrObj()->TakeXorPoly());
438 for(auto const& rPolygon
: aNewPolyPolygon
)
440 nPointCount
+= rPolygon
.count();
443 if(nPointCount
> SdrDragView::GetDragXorPointLimit())
450 aResult
.append(aNewPolyPolygon
);
457 const tools::Rectangle
aR(getSdrDragView().GetSdrPageView()->MarkSnap());
458 const basegfx::B2DRange aNewRectangle
= vcl::unotools::b2DRectangleFromRectangle(aR
);
459 basegfx::B2DPolygon
aNewPolygon(basegfx::utils::createPolygonFromRect(aNewRectangle
));
461 aResult
= basegfx::B2DPolyPolygon(basegfx::utils::expandToCurve(aNewPolygon
));
466 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntryPolyPolygon(aResult
)));
470 void SdrDragMethod::createSdrDragEntries_PointDrag()
472 const size_t nMarkCount(getSdrDragView().GetMarkedObjectCount());
473 std::vector
< basegfx::B2DPoint
> aPositions
;
475 for(size_t nm
= 0; nm
< nMarkCount
; ++nm
)
477 SdrMark
* pM
= getSdrDragView().GetSdrMarkByIndex(nm
);
479 if(pM
->GetPageView() == getSdrDragView().GetSdrPageView())
481 const SdrUShortCont
& rPts
= pM
->GetMarkedPoints();
485 const SdrObject
* pObj
= pM
->GetMarkedSdrObj();
486 const SdrPathObj
* pPath
= dynamic_cast< const SdrPathObj
* >(pObj
);
490 const basegfx::B2DPolyPolygon
& aPathXPP
= pPath
->GetPathPoly();
494 for(const sal_uInt16 nObjPt
: rPts
)
496 sal_uInt32 nPolyNum
, nPointNum
;
498 if(sdr::PolyPolygonEditor::GetRelativePolyPoint(aPathXPP
, nObjPt
, nPolyNum
, nPointNum
))
500 aPositions
.push_back(aPathXPP
.getB2DPolygon(nPolyNum
).getB2DPoint(nPointNum
));
509 if(!aPositions
.empty())
511 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntryPointGlueDrag(aPositions
, true)));
515 void SdrDragMethod::createSdrDragEntries_GlueDrag()
517 const size_t nMarkCount(getSdrDragView().GetMarkedObjectCount());
518 std::vector
< basegfx::B2DPoint
> aPositions
;
520 for(size_t nm
= 0; nm
< nMarkCount
; ++nm
)
522 SdrMark
* pM
= getSdrDragView().GetSdrMarkByIndex(nm
);
524 if(pM
->GetPageView() == getSdrDragView().GetSdrPageView())
526 const SdrUShortCont
& rPts
= pM
->GetMarkedGluePoints();
530 const SdrObject
* pObj
= pM
->GetMarkedSdrObj();
531 const SdrGluePointList
* pGPL
= pObj
->GetGluePointList();
535 for(const sal_uInt16 nObjPt
: rPts
)
537 const sal_uInt16
nGlueNum(pGPL
->FindGluePoint(nObjPt
));
539 if(SDRGLUEPOINT_NOTFOUND
!= nGlueNum
)
541 const Point
aPoint((*pGPL
)[nGlueNum
].GetAbsolutePos(*pObj
));
542 aPositions
.emplace_back(aPoint
.X(), aPoint
.Y());
550 if(!aPositions
.empty())
552 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntryPointGlueDrag(aPositions
, false)));
556 OUString
SdrDragMethod::ImpGetDescriptionStr(const char* pStrCacheID
) const
558 ImpGetDescriptionOptions nOpt
=ImpGetDescriptionOptions::NONE
;
559 if (IsDraggingPoints()) {
560 nOpt
=ImpGetDescriptionOptions::POINTS
;
561 } else if (IsDraggingGluePoints()) {
562 nOpt
=ImpGetDescriptionOptions::GLUEPOINTS
;
564 return getSdrDragView().ImpGetDescriptionString(pStrCacheID
, nOpt
);
567 SdrObject
* SdrDragMethod::GetDragObj() const
569 SdrObject
* pObj
=nullptr;
570 if (getSdrDragView().mpDragHdl
!=nullptr) pObj
=getSdrDragView().mpDragHdl
->GetObj();
571 if (pObj
==nullptr) pObj
=getSdrDragView().mpMarkedObj
;
575 SdrPageView
* SdrDragMethod::GetDragPV() const
577 SdrPageView
* pPV
=nullptr;
578 if (getSdrDragView().mpDragHdl
!=nullptr) pPV
=getSdrDragView().mpDragHdl
->GetPageView();
579 if (pPV
==nullptr) pPV
=getSdrDragView().mpMarkedPV
;
583 void SdrDragMethod::applyCurrentTransformationToSdrObject(SdrObject
& rTarget
)
585 // the original applies the transformation using TRGetBaseGeometry/TRSetBaseGeometry.
586 // Later this should be the only needed one for linear transforms (not for SdrDragCrook and
587 // SdrDragDistort, those are NOT linear). Currently, this can not yet be used since the
588 // special handling of rotate/mirror due to the not-being-able to handle it in the old
589 // drawinglayer stuff. Text would currently not correctly be mirrored in the preview.
590 basegfx::B2DHomMatrix aObjectTransform
;
591 basegfx::B2DPolyPolygon aObjectPolyPolygon
;
592 bool bPolyUsed(rTarget
.TRGetBaseGeometry(aObjectTransform
, aObjectPolyPolygon
));
594 // apply transform to object transform
595 aObjectTransform
*= getCurrentTransformation();
599 // do something special since the object size is in the polygon
600 // break up matrix to get the scale
601 const basegfx::utils::B2DHomMatrixBufferedDecompose
aTmpDecomp(aObjectTransform
);
603 // get polygon's position and size
604 const basegfx::B2DRange
aPolyRange(aObjectPolyPolygon
.getB2DRange());
606 // get the scaling factors (do not mirror, this is in the object transformation)
607 const double fScaleX(fabs(aTmpDecomp
.getScale().getX()) / (basegfx::fTools::equalZero(aPolyRange
.getWidth()) ? 1.0 : aPolyRange
.getWidth()));
608 const double fScaleY(fabs(aTmpDecomp
.getScale().getY()) / (basegfx::fTools::equalZero(aPolyRange
.getHeight()) ? 1.0 : aPolyRange
.getHeight()));
610 // prepare transform matrix for polygon
611 basegfx::B2DHomMatrix
aPolyTransform(
612 basegfx::utils::createTranslateB2DHomMatrix(
613 -aPolyRange
.getMinX(),
614 -aPolyRange
.getMinY()));
615 aPolyTransform
.scale(fScaleX
, fScaleY
);
617 // transform the polygon
618 aObjectPolyPolygon
.transform(aPolyTransform
);
621 rTarget
.TRSetBaseGeometry(getCurrentTransformation() * aObjectTransform
, aObjectPolyPolygon
);
624 void SdrDragMethod::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon
& rTarget
)
626 // original uses CurrentTransformation
627 rTarget
.transform(getCurrentTransformation());
630 SdrDragMethod::SdrDragMethod(SdrDragView
& rNewView
)
631 : maSdrDragEntries(),
632 maOverlayObjectList(),
633 mrSdrDragView(rNewView
),
635 mbSolidDraggingActive(getSdrDragView().IsSolidDragging()),
636 mbShiftPressed(false)
638 if(mbSolidDraggingActive
&& Application::GetSettings().GetStyleSettings().GetHighContrastMode())
640 // fallback to wireframe when high contrast is used
641 mbSolidDraggingActive
= false;
645 SdrDragMethod::~SdrDragMethod()
647 clearSdrDragEntries();
650 void SdrDragMethod::Show()
652 getSdrDragView().ShowDragObj();
655 void SdrDragMethod::Hide()
657 getSdrDragView().HideDragObj();
660 basegfx::B2DHomMatrix
SdrDragMethod::getCurrentTransformation()
662 return basegfx::B2DHomMatrix();
665 void SdrDragMethod::CancelSdrDrag()
670 typedef std::map
< const SdrObject
*, SdrObject
* > SdrObjectAndCloneMap
;
672 void SdrDragMethod::CreateOverlayGeometry(
673 sdr::overlay::OverlayManager
& rOverlayManager
,
674 const sdr::contact::ObjectContact
& rObjectContact
)
676 // We do client-side object manipulation with the Kit API
677 if (comphelper::LibreOfficeKit::isActive())
680 // create SdrDragEntries on demand
681 if(maSdrDragEntries
.empty())
683 createSdrDragEntries();
686 // if there are entries, derive OverlayObjects from the entries, including
687 // modification from current interactive state
688 if(!maSdrDragEntries
.empty())
690 // #i54102# SdrDragEntrySdrObject creates clones of SdrObjects as base for creating the needed
691 // primitives, holding the original and the clone. If connectors (Edges) are involved,
692 // the cloned connectors need to be connected to the cloned SdrObjects (after cloning
693 // they are connected to the original SdrObjects). To do so, trigger the preparation
694 // steps for SdrDragEntrySdrObject, save an association of (orig, clone) in a helper
695 // and evtl. remember if it was an edge
696 SdrObjectAndCloneMap aOriginalAndClones
;
697 std::vector
< SdrEdgeObj
* > aEdges
;
699 // #i54102# execute prepareCurrentState for all SdrDragEntrySdrObject, register pair of original and
700 // clone, remember edges
701 for(auto const & a
: maSdrDragEntries
)
703 SdrDragEntrySdrObject
* pSdrDragEntrySdrObject
= dynamic_cast< SdrDragEntrySdrObject
*>(a
.get());
705 if(pSdrDragEntrySdrObject
)
707 pSdrDragEntrySdrObject
->prepareCurrentState(*this);
709 SdrEdgeObj
* pSdrEdgeObj
= dynamic_cast< SdrEdgeObj
* >(pSdrDragEntrySdrObject
->getClone());
713 aEdges
.push_back(pSdrEdgeObj
);
716 if(pSdrDragEntrySdrObject
->getClone())
718 aOriginalAndClones
[&pSdrDragEntrySdrObject
->getOriginal()] = pSdrDragEntrySdrObject
->getClone();
723 // #i54102# if there are edges, reconnect their ends to the corresponding clones (if found)
724 for(SdrEdgeObj
* pSdrEdgeObj
: aEdges
)
726 SdrObject
* pConnectedTo
= pSdrEdgeObj
->GetConnectedNode(true);
730 SdrObjectAndCloneMap::iterator aEntry
= aOriginalAndClones
.find(pConnectedTo
);
732 if(aEntry
!= aOriginalAndClones
.end())
734 pSdrEdgeObj
->ConnectToNode(true, aEntry
->second
);
738 pConnectedTo
= pSdrEdgeObj
->GetConnectedNode(false);
742 SdrObjectAndCloneMap::iterator aEntry
= aOriginalAndClones
.find(pConnectedTo
);
744 if(aEntry
!= aOriginalAndClones
.end())
746 pSdrEdgeObj
->ConnectToNode(false, aEntry
->second
);
751 // collect primitives for visualisation
752 drawinglayer::primitive2d::Primitive2DContainer aResult
;
753 drawinglayer::primitive2d::Primitive2DContainer aResultTransparent
;
755 for(auto & pCandidate
: maSdrDragEntries
)
757 const drawinglayer::primitive2d::Primitive2DContainer
aCandidateResult(pCandidate
->createPrimitive2DSequenceInCurrentState(*this));
759 if(!aCandidateResult
.empty())
761 if(pCandidate
->getAddToTransparent())
763 aResultTransparent
.append(aCandidateResult
);
767 aResult
.append(aCandidateResult
);
772 if(DoAddConnectorOverlays())
774 const drawinglayer::primitive2d::Primitive2DContainer
aConnectorOverlays(AddConnectorOverlays());
776 if(!aConnectorOverlays
.empty())
778 // add connector overlays to transparent part
779 aResultTransparent
.append(aConnectorOverlays
);
785 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(
786 new sdr::overlay::OverlayPrimitive2DSequenceObject(
789 insertNewlyCreatedOverlayObjectForSdrDragMethod(
790 std::move(pNewOverlayObject
),
795 if(!aResultTransparent
.empty())
797 drawinglayer::primitive2d::Primitive2DReference
aUnifiedTransparencePrimitive2D(new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(aResultTransparent
, 0.5));
798 aResultTransparent
= drawinglayer::primitive2d::Primitive2DContainer
{ aUnifiedTransparencePrimitive2D
};
800 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(
801 new sdr::overlay::OverlayPrimitive2DSequenceObject(
802 aResultTransparent
));
804 insertNewlyCreatedOverlayObjectForSdrDragMethod(
805 std::move(pNewOverlayObject
),
811 // add DragStripes if necessary (help lines cross the page when dragging)
812 if(!getSdrDragView().IsDragStripes())
815 tools::Rectangle aActionRectangle
;
816 getSdrDragView().TakeActionRect(aActionRectangle
);
818 const basegfx::B2DPoint
aTopLeft(aActionRectangle
.Left(), aActionRectangle
.Top());
819 const basegfx::B2DPoint
aBottomRight(aActionRectangle
.Right(), aActionRectangle
.Bottom());
820 std::unique_ptr
<sdr::overlay::OverlayRollingRectangleStriped
> pNew(
821 new sdr::overlay::OverlayRollingRectangleStriped(
827 insertNewlyCreatedOverlayObjectForSdrDragMethod(
833 void SdrDragMethod::destroyOverlayGeometry()
835 maOverlayObjectList
.clear();
838 bool SdrDragMethod::DoAddConnectorOverlays()
840 // these conditions are translated from SdrDragView::ImpDrawEdgeXor
841 const SdrMarkList
& rMarkedNodes
= getSdrDragView().GetEdgesOfMarkedNodes();
843 if(!rMarkedNodes
.GetMarkCount())
848 if(getSdrDragView().IsDraggingPoints() || getSdrDragView().IsDraggingGluePoints())
853 if(!getMoveOnly() && !(
854 dynamic_cast<const SdrDragMove
*>(this) != nullptr || dynamic_cast<const SdrDragResize
*>(this) != nullptr ||
855 dynamic_cast<const SdrDragRotate
*>(this) != nullptr || dynamic_cast<const SdrDragMirror
*>(this) != nullptr ))
860 // one more migrated from SdrEdgeObj::NspToggleEdgeXor
861 if( dynamic_cast< const SdrDragObjOwn
* >(this) != nullptr || dynamic_cast< const SdrDragMovHdl
* >(this) != nullptr )
869 drawinglayer::primitive2d::Primitive2DContainer
SdrDragMethod::AddConnectorOverlays()
871 drawinglayer::primitive2d::Primitive2DContainer aRetval
;
872 const bool bDetail(getMoveOnly());
873 const SdrMarkList
& rMarkedNodes
= getSdrDragView().GetEdgesOfMarkedNodes();
875 for(size_t a
= 0; a
< rMarkedNodes
.GetMarkCount(); ++a
)
877 SdrMark
* pEM
= rMarkedNodes
.GetMark(a
);
879 if(pEM
&& pEM
->GetMarkedSdrObj())
881 SdrEdgeObj
* pEdge
= dynamic_cast< SdrEdgeObj
* >(pEM
->GetMarkedSdrObj());
885 const basegfx::B2DPolygon
aEdgePolygon(pEdge
->ImplAddConnectorOverlay(*this, pEM
->IsCon1(), pEM
->IsCon2(), bDetail
));
887 if(aEdgePolygon
.count())
889 // this polygon is a temporary calculated connector path, so it is not possible to fetch
890 // the needed primitives directly from the pEdge object which does not get changed. If full
891 // drag is on, use the SdrObjects ItemSet to create an adequate representation
892 bool bUseSolidDragging(getSolidDraggingActive());
894 if(bUseSolidDragging
)
896 // switch off solid dragging if connector is not visible
897 if(!pEdge
->HasLineStyle())
899 bUseSolidDragging
= false;
903 if(bUseSolidDragging
)
905 const SfxItemSet
& rItemSet
= pEdge
->GetMergedItemSet();
906 const drawinglayer::attribute::SdrLineAttribute
aLine(
907 drawinglayer::primitive2d::createNewSdrLineAttribute(rItemSet
));
909 if(!aLine
.isDefault())
911 const drawinglayer::attribute::SdrLineStartEndAttribute
aLineStartEnd(
912 drawinglayer::primitive2d::createNewSdrLineStartEndAttribute(
916 aRetval
.push_back(drawinglayer::primitive2d::createPolygonLinePrimitive(
924 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer
;
925 basegfx::BColor
aColA(aSvtOptionsDrawinglayer
.GetStripeColorA().getBColor());
926 basegfx::BColor
aColB(aSvtOptionsDrawinglayer
.GetStripeColorB().getBColor());
927 const double fStripeLength(aSvtOptionsDrawinglayer
.GetStripeLength());
929 if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
931 aColA
= aColB
= Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
935 drawinglayer::primitive2d::Primitive2DReference
aPolyPolygonMarkerPrimitive2D(
936 new drawinglayer::primitive2d::PolygonMarkerPrimitive2D(
937 aEdgePolygon
, aColA
, aColB
, fStripeLength
));
938 aRetval
.push_back(aPolyPolygonMarkerPrimitive2D
);
949 SdrDragMovHdl::SdrDragMovHdl(SdrDragView
& rNewView
)
950 : SdrDragMethod(rNewView
)
954 void SdrDragMovHdl::createSdrDragEntries()
956 // SdrDragMovHdl does not use the default drags,
957 // but creates nothing
960 OUString
SdrDragMovHdl::GetSdrDragComment() const
962 OUString aStr
=SvxResId(STR_DragMethMovHdl
);
963 if (getSdrDragView().IsDragWithCopy()) aStr
+=SvxResId(STR_EditWithCopy
);
967 bool SdrDragMovHdl::BeginSdrDrag()
972 DragStat().SetRef1(GetDragHdl()->GetPos());
973 DragStat().SetShown(!DragStat().IsShown());
974 SdrHdlKind eKind
=GetDragHdl()->GetKind();
975 SdrHdl
* pH1
=GetHdlList().GetHdl(SdrHdlKind::Ref1
);
976 SdrHdl
* pH2
=GetHdlList().GetHdl(SdrHdlKind::Ref2
);
978 if (eKind
==SdrHdlKind::MirrorAxis
)
980 if (pH1
==nullptr || pH2
==nullptr)
982 OSL_FAIL("SdrDragMovHdl::BeginSdrDrag(): Moving the axis of reflection: reference handles not found.");
986 DragStat().SetActionRect(tools::Rectangle(pH1
->GetPos(),pH2
->GetPos()));
990 Point
aPt(GetDragHdl()->GetPos());
991 DragStat().SetActionRect(tools::Rectangle(aPt
,aPt
));
997 void SdrDragMovHdl::MoveSdrDrag(const Point
& rNoSnapPnt
)
999 Point
aPnt(rNoSnapPnt
);
1001 if ( !(GetDragHdl() && DragStat().CheckMinMoved(rNoSnapPnt
)))
1004 if (GetDragHdl()->GetKind()==SdrHdlKind::MirrorAxis
)
1006 SdrHdl
* pH1
=GetHdlList().GetHdl(SdrHdlKind::Ref1
);
1007 SdrHdl
* pH2
=GetHdlList().GetHdl(SdrHdlKind::Ref2
);
1009 if (pH1
==nullptr || pH2
==nullptr)
1012 if (!DragStat().IsNoSnap())
1014 tools::Long nBestXSnap
=0;
1015 tools::Long nBestYSnap
=0;
1016 bool bXSnapped
=false;
1017 bool bYSnapped
=false;
1018 Point
aDif(aPnt
-DragStat().GetStart());
1019 getSdrDragView().CheckSnap(Ref1()+aDif
,nBestXSnap
,nBestYSnap
,bXSnapped
,bYSnapped
);
1020 getSdrDragView().CheckSnap(Ref2()+aDif
,nBestXSnap
,nBestYSnap
,bXSnapped
,bYSnapped
);
1021 aPnt
.AdjustX(nBestXSnap
);
1022 aPnt
.AdjustY(nBestYSnap
);
1025 if (aPnt
!=DragStat().GetNow())
1028 DragStat().NextMove(aPnt
);
1029 Point
aDif(DragStat().GetNow()-DragStat().GetStart());
1030 pH1
->SetPos(Ref1()+aDif
);
1031 pH2
->SetPos(Ref2()+aDif
);
1033 SdrHdl
* pHM
= GetHdlList().GetHdl(SdrHdlKind::MirrorAxis
);
1039 DragStat().SetActionRect(tools::Rectangle(pH1
->GetPos(),pH2
->GetPos()));
1044 if (!DragStat().IsNoSnap()) SnapPos(aPnt
);
1047 if (getSdrDragView().IsAngleSnapEnabled())
1048 nSA
=getSdrDragView().GetSnapAngle();
1050 if (getSdrDragView().IsMirrorAllowed(true,true))
1052 if (!getSdrDragView().IsMirrorAllowed()) nSA
=4500;
1053 if (!getSdrDragView().IsMirrorAllowed(true)) nSA
=9000;
1056 if (getSdrDragView().IsOrtho() && nSA
!=9000)
1061 SdrHdlKind eRef
=SdrHdlKind::Ref1
;
1063 if (GetDragHdl()->GetKind()==SdrHdlKind::Ref1
)
1064 eRef
=SdrHdlKind::Ref2
;
1066 SdrHdl
* pH
=GetHdlList().GetHdl(eRef
);
1070 Point
aRef(pH
->GetPos());
1071 tools::Long nAngle
=NormAngle36000(GetAngle(aPnt
-aRef
));
1072 tools::Long nNewAngle
=nAngle
;
1076 nNewAngle
=NormAngle36000(nNewAngle
);
1077 double a
=(nNewAngle
-nAngle
)*F_PI18000
;
1080 RotatePoint(aPnt
,aRef
,nSin
,nCos
);
1082 // eliminate rounding errors for certain values
1085 if (nNewAngle
==0 || nNewAngle
==18000) aPnt
.setY(aRef
.Y() );
1086 if (nNewAngle
==9000 || nNewAngle
==27000) aPnt
.setX(aRef
.X() );
1090 OrthoDistance8(aRef
,aPnt
,true);
1094 if (aPnt
!=DragStat().GetNow())
1097 DragStat().NextMove(aPnt
);
1098 GetDragHdl()->SetPos(DragStat().GetNow());
1099 SdrHdl
* pHM
= GetHdlList().GetHdl(SdrHdlKind::MirrorAxis
);
1105 DragStat().SetActionRect(tools::Rectangle(aPnt
,aPnt
));
1110 bool SdrDragMovHdl::EndSdrDrag(bool /*bCopy*/)
1114 switch (GetDragHdl()->GetKind())
1116 case SdrHdlKind::Ref1
:
1117 Ref1()=DragStat().GetNow();
1120 case SdrHdlKind::Ref2
:
1121 Ref2()=DragStat().GetNow();
1124 case SdrHdlKind::MirrorAxis
:
1125 Ref1()+=DragStat().GetNow()-DragStat().GetStart();
1126 Ref2()+=DragStat().GetNow()-DragStat().GetStart();
1136 void SdrDragMovHdl::CancelSdrDrag()
1140 SdrHdl
* pHdl
= GetDragHdl();
1142 pHdl
->SetPos(DragStat().GetRef1());
1144 SdrHdl
* pHM
= GetHdlList().GetHdl(SdrHdlKind::MirrorAxis
);
1150 PointerStyle
SdrDragMovHdl::GetSdrDragPointer() const
1152 const SdrHdl
* pHdl
= GetDragHdl();
1156 return pHdl
->GetPointer();
1159 return PointerStyle::RefHand
;
1163 SdrDragObjOwn::SdrDragObjOwn(SdrDragView
& rNewView
)
1164 : SdrDragMethod(rNewView
)
1166 const SdrObject
* pObj
= GetDragObj();
1170 // suppress full drag for some object types
1171 setSolidDraggingActive(pObj
->supportsFullDrag());
1175 SdrDragObjOwn::~SdrDragObjOwn()
1179 void SdrDragObjOwn::createSdrDragEntries()
1184 basegfx::B2DPolyPolygon aDragPolyPolygon
;
1185 bool bAddWireframe(true);
1187 if(getSolidDraggingActive())
1189 SdrPageView
* pPV
= getSdrDragView().GetSdrPageView();
1191 if(pPV
&& pPV
->PageWindowCount())
1193 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntrySdrObject(*mxClone
, false)));
1195 // potentially no wireframe needed, full drag works
1196 bAddWireframe
= false;
1202 // check for extra conditions for wireframe, e.g. no border at
1204 if(!mxClone
->HasLineStyle())
1206 bAddWireframe
= true;
1212 // use wireframe poly when full drag is off or did not work
1213 aDragPolyPolygon
= mxClone
->TakeXorPoly();
1216 // add evtl. extra DragPolyPolygon
1217 const basegfx::B2DPolyPolygon
aSpecialDragPolyPolygon(mxClone
->getSpecialDragPoly(DragStat()));
1219 if(aSpecialDragPolyPolygon
.count())
1221 aDragPolyPolygon
.append(aSpecialDragPolyPolygon
);
1224 if(aDragPolyPolygon
.count())
1226 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntryPolyPolygon(aDragPolyPolygon
)));
1230 OUString
SdrDragObjOwn::GetSdrDragComment() const
1233 // #i103058# get info string from the clone preferred, the original will
1234 // not be changed. For security, use original as fallback
1237 aStr
= mxClone
->getSpecialDragComment(DragStat());
1241 const SdrObject
* pObj
= GetDragObj();
1245 aStr
= pObj
->getSpecialDragComment(DragStat());
1251 bool SdrDragObjOwn::BeginSdrDrag()
1255 const SdrObject
* pObj
= GetDragObj();
1257 if(pObj
&& !pObj
->IsResizeProtect())
1259 if(pObj
->beginSpecialDrag(DragStat()))
1261 // create initial clone to have a start visualization
1262 mxClone
= pObj
->getFullDragClone();
1263 mxClone
->applySpecialDrag(DragStat());
1273 void SdrDragObjOwn::MoveSdrDrag(const Point
& rNoSnapPnt
)
1275 const SdrObject
* pObj
= GetDragObj();
1278 // No object to drag. Bail out.
1281 Point
aPnt(rNoSnapPnt
);
1282 SdrPageView
* pPV
= GetDragPV();
1285 // No page view available. Bail out.
1288 if(!DragStat().IsNoSnap())
1292 if(getSdrDragView().IsOrtho())
1294 if (DragStat().IsOrtho8Possible())
1296 OrthoDistance8(DragStat().GetStart(),aPnt
,getSdrDragView().IsBigOrtho());
1298 else if (DragStat().IsOrtho4Possible())
1300 OrthoDistance4(DragStat().GetStart(),aPnt
,getSdrDragView().IsBigOrtho());
1304 if (!DragStat().CheckMinMoved(rNoSnapPnt
))
1305 // Not moved by the minimum threshold. Nothing to do.
1309 DragStat().NextMove(aPnt
);
1311 // since SdrDragObjOwn currently supports no transformation of
1312 // existing SdrDragEntries but only their recreation, a recreation
1313 // after every move is needed in this mode. Delete existing
1314 // SdrDragEntries here to force their recreation in the following Show().
1315 clearSdrDragEntries();
1317 // delete current clone (after the last reference to it is deleted above)
1320 // create a new clone and modify to current drag state
1321 mxClone
= pObj
->getFullDragClone();
1322 mxClone
->applySpecialDrag(DragStat());
1324 // AutoGrowWidth may change for SdrTextObj due to the automatism used
1325 // with bDisableAutoWidthOnDragging, so not only geometry changes but
1326 // also this (pretty indirect) property change is possible. If it gets
1327 // changed, it needs to be copied to the original since nothing will
1328 // happen when it only changes in the drag clone
1329 const bool bOldAutoGrowWidth(pObj
->GetMergedItem(SDRATTR_TEXT_AUTOGROWWIDTH
).GetValue());
1330 const bool bNewAutoGrowWidth(mxClone
->GetMergedItem(SDRATTR_TEXT_AUTOGROWWIDTH
).GetValue());
1332 if (bOldAutoGrowWidth
!= bNewAutoGrowWidth
)
1334 GetDragObj()->SetMergedItem(makeSdrTextAutoGrowWidthItem(bNewAutoGrowWidth
));
1340 bool SdrDragObjOwn::EndSdrDrag(bool /*bCopy*/)
1343 std::vector
< std::unique_ptr
<SdrUndoAction
> > vConnectorUndoActions
;
1345 SdrObject
* pObj
= GetDragObj();
1349 std::unique_ptr
<SdrUndoAction
> pUndo
;
1350 std::unique_ptr
<SdrUndoAction
> pUndo2
;
1351 const bool bUndo
= getSdrDragView().IsUndoEnabled();
1355 getSdrDragView().EndTextEditAllViews();
1356 if(!getSdrDragView().IsInsObjPoint() && pObj
->IsInserted() )
1358 if (DragStat().IsEndDragChangesAttributes())
1360 pUndo
=getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj
);
1362 if (DragStat().IsEndDragChangesGeoAndAttributes())
1364 vConnectorUndoActions
= getSdrDragView().CreateConnectorUndo( *pObj
);
1365 pUndo2
= getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj
);
1370 vConnectorUndoActions
= getSdrDragView().CreateConnectorUndo( *pObj
);
1371 pUndo
= getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj
);
1377 getSdrDragView().BegUndo( pUndo
->GetComment() );
1381 getSdrDragView().BegUndo();
1385 // Maybe use operator = for setting changed object data (do not change selection in
1386 // view, this will destroy the interactor). This is possible since a clone is now
1387 // directly modified by the modifiers. Only SdrTableObj is adding own UNDOs
1388 // in its SdrTableObj::endSpecialDrag, so currently not possible. OTOH it uses
1389 // a CreateUndoGeoObject(), so maybe setting SetEndDragChangesAttributes is okay. I
1390 // will test this now
1391 tools::Rectangle aBoundRect0
;
1393 if(pObj
->GetUserCall())
1395 aBoundRect0
= pObj
->GetLastBoundRect();
1398 bRet
= pObj
->applySpecialDrag(DragStat());
1399 if (DragStat().IsEndDragChangesLayout())
1401 auto pGeoUndo
= dynamic_cast<SdrUndoGeoObj
*>(pUndo
.get());
1403 pGeoUndo
->SetSkipChangeLayout(true);
1409 pObj
->BroadcastObjectChange();
1410 pObj
->SendUserCall( SdrUserCallType::Resize
, aBoundRect0
);
1415 getSdrDragView().AddUndoActions( std::move(vConnectorUndoActions
) );
1419 getSdrDragView().AddUndo(std::move(pUndo
));
1424 getSdrDragView().AddUndo(std::move(pUndo2
));
1429 getSdrDragView().EndUndo();
1435 PointerStyle
SdrDragObjOwn::GetSdrDragPointer() const
1437 const SdrHdl
* pHdl
=GetDragHdl();
1441 return pHdl
->GetPointer();
1444 return PointerStyle::Move
;
1448 void SdrDragMove::createSdrDragEntryForSdrObject(const SdrObject
& rOriginal
)
1450 // use the view-independent primitive representation (without
1451 // evtl. GridOffset, that may be applied to the DragEntry individually)
1453 std::unique_ptr
<SdrDragEntry
>(
1454 new SdrDragEntryPrimitive2DSequence(
1455 rOriginal
.GetViewContact().getViewIndependentPrimitive2DContainer())));
1459 void SdrDragMove::applyCurrentTransformationToSdrObject(SdrObject
& rTarget
)
1461 rTarget
.Move(Size(DragStat().GetDX(), DragStat().GetDY()));
1464 SdrDragMove::SdrDragMove(SdrDragView
& rNewView
)
1465 : SdrDragMethod(rNewView
)
1474 OUString
SdrDragMove::GetSdrDragComment() const
1476 OUString aStr
= ImpGetDescriptionStr(STR_DragMethMove
)
1478 + getSdrDragView().GetModel()->GetMetricString(DragStat().GetDX())
1480 + getSdrDragView().GetModel()->GetMetricString(DragStat().GetDY())
1483 if(getSdrDragView().IsDragWithCopy())
1485 if(!getSdrDragView().IsInsObjPoint() && !getSdrDragView().IsInsGluePoint())
1487 aStr
+= SvxResId(STR_EditWithCopy
);
1493 bool SdrDragMove::BeginSdrDrag()
1495 DragStat().SetActionRect(GetMarkedRect());
1501 basegfx::B2DHomMatrix
SdrDragMove::getCurrentTransformation()
1503 return basegfx::utils::createTranslateB2DHomMatrix(DragStat().GetDX(), DragStat().GetDY());
1506 void SdrDragMove::ImpCheckSnap(const Point
& rPt
)
1509 SdrSnap nRet
=SnapPos(aPt
);
1512 if (nRet
& SdrSnap::XSNAPPED
)
1516 if (std::abs(aPt
.X())<std::abs(nBestXSnap
))
1528 if (!(nRet
& SdrSnap::YSNAPPED
))
1533 if (std::abs(aPt
.Y())<std::abs(nBestYSnap
))
1545 void SdrDragMove::MoveSdrDrag(const Point
& rNoSnapPnt_
)
1551 Point
aNoSnapPnt(rNoSnapPnt_
);
1552 const tools::Rectangle
& aSR
=GetMarkedRect();
1553 tools::Long nMovedx
=aNoSnapPnt
.X()-DragStat().GetStart().X();
1554 tools::Long nMovedy
=aNoSnapPnt
.Y()-DragStat().GetStart().Y();
1555 Point
aLO(aSR
.TopLeft()); aLO
.AdjustX(nMovedx
); aLO
.AdjustY(nMovedy
);
1556 Point
aRU(aSR
.BottomRight()); aRU
.AdjustX(nMovedx
); aRU
.AdjustY(nMovedy
);
1557 Point
aLU(aLO
.X(),aRU
.Y());
1558 Point
aRO(aRU
.X(),aLO
.Y());
1561 if (!getSdrDragView().IsMoveSnapOnlyTopLeft())
1568 Point
aPnt(aNoSnapPnt
.X()+nBestXSnap
,aNoSnapPnt
.Y()+nBestYSnap
);
1569 bool bOrtho
=getSdrDragView().IsOrtho();
1572 OrthoDistance8(DragStat().GetStart(),aPnt
,getSdrDragView().IsBigOrtho());
1574 if (!DragStat().CheckMinMoved(aNoSnapPnt
))
1578 tools::Rectangle
aLR(getSdrDragView().GetWorkArea());
1579 bool bWorkArea
=!aLR
.IsEmpty();
1580 bool bDragLimit
=IsDragLimit();
1582 if (bDragLimit
|| bWorkArea
)
1584 tools::Rectangle
aSR2(GetMarkedRect());
1585 Point
aD(aPt1
-DragStat().GetStart());
1589 tools::Rectangle
aR2(GetDragLimitRect());
1592 aLR
.Intersection(aR2
);
1597 if (aSR2
.Left()>aLR
.Left() || aSR2
.Right()<aLR
.Right())
1598 { // any space to move to?
1599 aSR2
.Move(aD
.X(),0);
1601 if (aSR2
.Left()<aLR
.Left())
1603 aPt1
.AdjustX( -(aSR2
.Left()-aLR
.Left()) );
1605 else if (aSR2
.Right()>aLR
.Right())
1607 aPt1
.AdjustX( -(aSR2
.Right()-aLR
.Right()) );
1611 aPt1
.setX(DragStat().GetStart().X() ); // no space to move to
1613 if (aSR2
.Top()>aLR
.Top() || aSR2
.Bottom()<aLR
.Bottom())
1614 { // any space to move to?
1615 aSR2
.Move(0,aD
.Y());
1617 if (aSR2
.Top()<aLR
.Top())
1619 aPt1
.AdjustY( -(aSR2
.Top()-aLR
.Top()) );
1621 else if (aSR2
.Bottom()>aLR
.Bottom())
1623 aPt1
.AdjustY( -(aSR2
.Bottom()-aLR
.Bottom()) );
1627 aPt1
.setY(DragStat().GetStart().Y() ); // no space to move to
1630 if (getSdrDragView().IsDraggingGluePoints())
1631 { // restrict glue points to the BoundRect of the Obj
1632 aPt1
-=DragStat().GetStart();
1633 const SdrMarkList
& rML
=GetMarkedObjectList();
1634 const size_t nMarkCount
=rML
.GetMarkCount();
1636 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
; ++nMarkNum
)
1638 const SdrMark
* pM
=rML
.GetMark(nMarkNum
);
1639 const SdrUShortCont
& rPts
= pM
->GetMarkedGluePoints();
1643 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
1644 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
1645 tools::Rectangle
aBound(pObj
->GetCurrentBoundRect());
1647 for (sal_uInt16 nId
: rPts
)
1649 sal_uInt16 nGlueNum
=pGPL
->FindGluePoint(nId
);
1651 if (nGlueNum
!=SDRGLUEPOINT_NOTFOUND
)
1653 Point
aPt((*pGPL
)[nGlueNum
].GetAbsolutePos(*pObj
));
1654 aPt
+=aPt1
; // move by this much
1655 if (aPt
.X()<aBound
.Left() ) aPt1
.AdjustX( -(aPt
.X()-aBound
.Left()) ) ;
1656 if (aPt
.X()>aBound
.Right() ) aPt1
.AdjustX( -(aPt
.X()-aBound
.Right()) ) ;
1657 if (aPt
.Y()<aBound
.Top() ) aPt1
.AdjustY( -(aPt
.Y()-aBound
.Top()) ) ;
1658 if (aPt
.Y()>aBound
.Bottom()) aPt1
.AdjustY( -(aPt
.Y()-aBound
.Bottom()) );
1664 aPt1
+=DragStat().GetStart();
1668 OrthoDistance8(DragStat().GetStart(),aPt1
,false);
1670 if (aPt1
!=DragStat().GetNow())
1673 DragStat().NextMove(aPt1
);
1674 tools::Rectangle
aAction(GetMarkedRect());
1675 aAction
.Move(DragStat().GetDX(),DragStat().GetDY());
1676 DragStat().SetActionRect(aAction
);
1681 bool SdrDragMove::EndSdrDrag(bool bCopy
)
1685 if (getSdrDragView().IsInsObjPoint() || getSdrDragView().IsInsGluePoint())
1688 if (IsDraggingPoints())
1690 getSdrDragView().MoveMarkedPoints(Size(DragStat().GetDX(),DragStat().GetDY()));
1692 else if (IsDraggingGluePoints())
1694 getSdrDragView().MoveMarkedGluePoints(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy
);
1698 getSdrDragView().MoveMarkedObj(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy
);
1704 PointerStyle
SdrDragMove::GetSdrDragPointer() const
1706 if (IsDraggingPoints() || IsDraggingGluePoints())
1708 return PointerStyle::MovePoint
;
1712 return PointerStyle::Move
;
1717 SdrDragResize::SdrDragResize(SdrDragView
& rNewView
)
1718 : SdrDragMethod(rNewView
),
1724 OUString
SdrDragResize::GetSdrDragComment() const
1726 OUString aStr
= ImpGetDescriptionStr(STR_DragMethResize
);
1727 Fraction
aFact1(1,1);
1728 Point
aStart(DragStat().GetStart());
1729 Point
aRef(DragStat().GetRef1());
1730 sal_Int32
nXDiv(aStart
.X() - aRef
.X());
1735 sal_Int32
nYDiv(aStart
.Y() - aRef
.Y());
1740 bool bX(aXFact
!= aFact1
&& std::abs(nXDiv
) > 1);
1741 bool bY(aYFact
!= aFact1
&& std::abs(nYDiv
) > 1);
1747 bool bEqual(aXFact
== aYFact
);
1753 aStr
+= SdrModel::GetPercentString(aXFact
);
1761 aStr
+= "y=" + SdrModel::GetPercentString(aYFact
);
1767 if(getSdrDragView().IsDragWithCopy())
1768 aStr
+= SvxResId(STR_EditWithCopy
);
1772 bool SdrDragResize::BeginSdrDrag()
1774 SdrHdlKind eRefHdl
=SdrHdlKind::Move
;
1775 SdrHdl
* pRefHdl
=nullptr;
1777 switch (GetDragHdlKind())
1779 case SdrHdlKind::UpperLeft
: eRefHdl
=SdrHdlKind::LowerRight
; break;
1780 case SdrHdlKind::Upper
: eRefHdl
=SdrHdlKind::Lower
; DragStat().SetHorFixed(true); break;
1781 case SdrHdlKind::UpperRight
: eRefHdl
=SdrHdlKind::LowerLeft
; break;
1782 case SdrHdlKind::Left
: eRefHdl
=SdrHdlKind::Right
; DragStat().SetVerFixed(true); break;
1783 case SdrHdlKind::Right
: eRefHdl
=SdrHdlKind::Left
; DragStat().SetVerFixed(true); break;
1784 case SdrHdlKind::LowerLeft
: eRefHdl
=SdrHdlKind::UpperRight
; break;
1785 case SdrHdlKind::Lower
: eRefHdl
=SdrHdlKind::Upper
; DragStat().SetHorFixed(true); break;
1786 case SdrHdlKind::LowerRight
: eRefHdl
=SdrHdlKind::UpperLeft
; break;
1790 if (eRefHdl
!=SdrHdlKind::Move
)
1791 pRefHdl
=GetHdlList().GetHdl(eRefHdl
);
1793 if (pRefHdl
!=nullptr && !getSdrDragView().IsResizeAtCenter())
1795 DragStat().SetRef1(pRefHdl
->GetPos());
1799 SdrHdl
* pRef1
=GetHdlList().GetHdl(SdrHdlKind::UpperLeft
);
1800 SdrHdl
* pRef2
=GetHdlList().GetHdl(SdrHdlKind::LowerRight
);
1802 if (pRef1
!=nullptr && pRef2
!=nullptr)
1804 DragStat().SetRef1(tools::Rectangle(pRef1
->GetPos(),pRef2
->GetPos()).Center());
1808 DragStat().SetRef1(GetMarkedRect().Center());
1817 basegfx::B2DHomMatrix
SdrDragResize::getCurrentTransformation()
1819 basegfx::B2DHomMatrix
aRetval(basegfx::utils::createTranslateB2DHomMatrix(
1820 -DragStat().GetRef1().X(), -DragStat().GetRef1().Y()));
1821 aRetval
.scale(double(aXFact
), double(aYFact
));
1822 aRetval
.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y());
1827 void SdrDragResize::MoveSdrDrag(const Point
& rNoSnapPnt
)
1829 Point
aPnt(GetSnapPos(rNoSnapPnt
));
1830 Point
aStart(DragStat().GetStart());
1831 Point
aRef(DragStat().GetRef1());
1832 Fraction
aMaxFact(0x7FFFFFFF,1);
1833 tools::Rectangle
aLR(getSdrDragView().GetWorkArea());
1834 bool bWorkArea
=!aLR
.IsEmpty();
1835 bool bDragLimit
=IsDragLimit();
1837 if (bDragLimit
|| bWorkArea
)
1839 tools::Rectangle
aSR(GetMarkedRect());
1843 tools::Rectangle
aR2(GetDragLimitRect());
1846 aLR
.Intersection(aR2
);
1851 if (aPnt
.X()<aLR
.Left())
1852 aPnt
.setX(aLR
.Left() );
1853 else if (aPnt
.X()>aLR
.Right())
1854 aPnt
.setX(aLR
.Right() );
1856 if (aPnt
.Y()<aLR
.Top())
1857 aPnt
.setY(aLR
.Top() );
1858 else if (aPnt
.Y()>aLR
.Bottom())
1859 aPnt
.setY(aLR
.Bottom() );
1861 if (aRef
.X()>aSR
.Left())
1863 Fraction
aMax(aRef
.X()-aLR
.Left(),aRef
.X()-aSR
.Left());
1869 if (aRef
.X()<aSR
.Right())
1871 Fraction
aMax(aLR
.Right()-aRef
.X(),aSR
.Right()-aRef
.X());
1877 if (aRef
.Y()>aSR
.Top())
1879 Fraction
aMax(aRef
.Y()-aLR
.Top(),aRef
.Y()-aSR
.Top());
1885 if (aRef
.Y()<aSR
.Bottom())
1887 Fraction
aMax(aLR
.Bottom()-aRef
.Y(),aSR
.Bottom()-aRef
.Y());
1894 tools::Long nXDiv
=aStart
.X()-aRef
.X(); if (nXDiv
==0) nXDiv
=1;
1895 tools::Long nYDiv
=aStart
.Y()-aRef
.Y(); if (nYDiv
==0) nYDiv
=1;
1896 tools::Long nXMul
=aPnt
.X()-aRef
.X();
1897 tools::Long nYMul
=aPnt
.Y()-aRef
.Y();
1911 bool bXNeg
=nXMul
<0; if (bXNeg
) nXMul
=-nXMul
;
1912 bool bYNeg
=nYMul
<0; if (bYNeg
) nYMul
=-nYMul
;
1913 bool bOrtho
=getSdrDragView().IsOrtho() || !getSdrDragView().IsResizeAllowed();
1915 if (!DragStat().IsHorFixed() && !DragStat().IsVerFixed())
1917 if (std::abs(nXDiv
)<=1 || std::abs(nYDiv
)<=1)
1922 if ((Fraction(nXMul
,nXDiv
)>Fraction(nYMul
,nYDiv
)) !=getSdrDragView().IsBigOrtho())
1938 if (DragStat().IsHorFixed())
1945 if (DragStat().IsVerFixed())
1954 if (DragStat().IsHorFixed())
1961 if (DragStat().IsVerFixed())
1970 Fraction
aNewXFact(nXMul
,nXDiv
);
1971 Fraction
aNewYFact(nYMul
,nYDiv
);
1975 if (aNewXFact
>aMaxFact
)
1981 if (aNewYFact
>aMaxFact
)
1989 aNewXFact
=Fraction(-aNewXFact
.GetNumerator(),aNewXFact
.GetDenominator());
1992 aNewYFact
=Fraction(-aNewYFact
.GetNumerator(),aNewYFact
.GetDenominator());
1994 if (DragStat().CheckMinMoved(aPnt
))
1996 if ((!DragStat().IsHorFixed() && aPnt
.X()!=DragStat().GetNow().X()) ||
1997 (!DragStat().IsVerFixed() && aPnt
.Y()!=DragStat().GetNow().Y()))
2000 DragStat().NextMove(aPnt
);
2008 void SdrDragResize::applyCurrentTransformationToSdrObject(SdrObject
& rTarget
)
2010 rTarget
.Resize(DragStat().GetRef1(),aXFact
,aYFact
);
2013 bool SdrDragResize::EndSdrDrag(bool bCopy
)
2017 if (IsDraggingPoints())
2019 getSdrDragView().ResizeMarkedPoints(DragStat().GetRef1(),aXFact
,aYFact
);
2021 else if (IsDraggingGluePoints())
2023 getSdrDragView().ResizeMarkedGluePoints(DragStat().GetRef1(),aXFact
,aYFact
,bCopy
);
2027 getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),aXFact
,aYFact
,bCopy
);
2033 PointerStyle
SdrDragResize::GetSdrDragPointer() const
2035 const SdrHdl
* pHdl
=GetDragHdl();
2039 return pHdl
->GetPointer();
2042 return PointerStyle::Move
;
2046 void SdrDragRotate::applyCurrentTransformationToSdrObject(SdrObject
& rTarget
)
2048 rTarget
.Rotate(DragStat().GetRef1(), nAngle
, sin(nAngle
* F_PI18000
), cos(nAngle
* F_PI18000
));
2051 SdrDragRotate::SdrDragRotate(SdrDragView
& rNewView
)
2052 : SdrDragMethod(rNewView
),
2061 OUString
SdrDragRotate::GetSdrDragComment() const
2063 OUString aStr
= ImpGetDescriptionStr(STR_DragMethRotate
) +
2065 sal_Int32
nTmpAngle(NormAngle36000(nAngle
));
2067 if(bRight
&& nAngle
)
2072 aStr
+= SdrModel::GetAngleString(nTmpAngle
) + ")";
2074 if(getSdrDragView().IsDragWithCopy())
2075 aStr
+= SvxResId(STR_EditWithCopy
);
2079 bool SdrDragRotate::BeginSdrDrag()
2081 SdrHdl
* pH
=GetHdlList().GetHdl(SdrHdlKind::Ref1
);
2086 DragStat().SetRef1(pH
->GetPos());
2087 nAngle0
=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
2091 // RotGrfFlyFrame: Support rotation around center *without* Ref1 (normally
2092 // the rotation point)
2093 const tools::Rectangle
aLocalMarkRect(getSdrDragView().GetMarkedObjRect());
2095 if(!aLocalMarkRect
.IsEmpty())
2098 DragStat().SetRef1(aLocalMarkRect
.Center());
2099 nAngle0
=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
2103 OSL_FAIL("SdrDragRotate::BeginSdrDrag(): No reference point handle found.");
2107 basegfx::B2DHomMatrix
SdrDragRotate::getCurrentTransformation()
2109 return basegfx::utils::createRotateAroundPoint(
2110 DragStat().GetRef1().X(), DragStat().GetRef1().Y(),
2111 -atan2(nSin
, nCos
));
2114 void SdrDragRotate::MoveSdrDrag(const Point
& rPnt_
)
2117 if (!DragStat().CheckMinMoved(aPnt
))
2120 tools::Long nNewAngle
=NormAngle36000(GetAngle(aPnt
-DragStat().GetRef1())-nAngle0
);
2123 if (getSdrDragView().IsAngleSnapEnabled())
2124 nSA
=getSdrDragView().GetSnapAngle();
2126 if (!getSdrDragView().IsRotateAllowed())
2136 nNewAngle
=NormAngle18000(nNewAngle
);
2138 if (nAngle
==nNewAngle
)
2141 sal_uInt16 nSekt0
=GetAngleSector(nAngle
);
2142 sal_uInt16 nSekt1
=GetAngleSector(nNewAngle
);
2144 if (nSekt0
==0 && nSekt1
==3)
2147 if (nSekt0
==3 && nSekt1
==0)
2151 double a
= nAngle
* F_PI18000
;
2152 double nSin1
=sin(a
); // calculate now, so as little time as possible
2153 double nCos1
=cos(a
); // passes between Hide() and Show()
2157 DragStat().NextMove(aPnt
);
2161 bool SdrDragRotate::EndSdrDrag(bool bCopy
)
2167 if (IsDraggingPoints())
2169 getSdrDragView().RotateMarkedPoints(DragStat().GetRef1(),nAngle
);
2171 else if (IsDraggingGluePoints())
2173 getSdrDragView().RotateMarkedGluePoints(DragStat().GetRef1(),nAngle
,bCopy
);
2177 getSdrDragView().RotateMarkedObj(DragStat().GetRef1(),nAngle
,bCopy
);
2183 PointerStyle
SdrDragRotate::GetSdrDragPointer() const
2185 return PointerStyle::Rotate
;
2189 SdrDragShear::SdrDragShear(SdrDragView
& rNewView
, bool bSlant1
)
2190 : SdrDragMethod(rNewView
),
2202 OUString
SdrDragShear::GetSdrDragComment() const
2204 OUString aStr
= ImpGetDescriptionStr(STR_DragMethShear
) +
2207 sal_Int32
nTmpAngle(nAngle
);
2212 nTmpAngle
= NormAngle18000(nTmpAngle
);
2214 aStr
+= SdrModel::GetAngleString(nTmpAngle
) + ")";
2216 if(getSdrDragView().IsDragWithCopy())
2217 aStr
+= SvxResId(STR_EditWithCopy
);
2221 bool SdrDragShear::BeginSdrDrag()
2223 SdrHdlKind eRefHdl
=SdrHdlKind::Move
;
2224 SdrHdl
* pRefHdl
=nullptr;
2226 switch (GetDragHdlKind())
2228 case SdrHdlKind::Upper
: eRefHdl
=SdrHdlKind::Lower
; break;
2229 case SdrHdlKind::Lower
: eRefHdl
=SdrHdlKind::Upper
; break;
2230 case SdrHdlKind::Left
: eRefHdl
=SdrHdlKind::Right
; bVertical
=true; break;
2231 case SdrHdlKind::Right
: eRefHdl
=SdrHdlKind::Left
; bVertical
=true; break;
2235 if (eRefHdl
!=SdrHdlKind::Move
)
2236 pRefHdl
=GetHdlList().GetHdl(eRefHdl
);
2238 if (pRefHdl
!=nullptr)
2240 DragStat().SetRef1(pRefHdl
->GetPos());
2241 nAngle0
=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
2245 OSL_FAIL("SdrDragShear::BeginSdrDrag(): No reference point handle for shearing found.");
2253 basegfx::B2DHomMatrix
SdrDragShear::getCurrentTransformation()
2255 basegfx::B2DHomMatrix
aRetval(basegfx::utils::createTranslateB2DHomMatrix(
2256 -DragStat().GetRef1().X(), -DragStat().GetRef1().Y()));
2262 aRetval
.scale(double(aFact
), 1.0);
2263 aRetval
.shearY(-nTan
);
2267 aRetval
.scale(1.0, double(aFact
));
2268 aRetval
.shearX(-nTan
);
2272 aRetval
.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y());
2277 void SdrDragShear::MoveSdrDrag(const Point
& rPnt
)
2279 if (!DragStat().CheckMinMoved(rPnt
))
2282 bResize
=!getSdrDragView().IsOrtho();
2285 if (getSdrDragView().IsAngleSnapEnabled())
2286 nSA
=getSdrDragView().GetSnapAngle();
2288 Point
aP0(DragStat().GetStart());
2290 Fraction
aNewFract(1,1);
2292 // if angle snapping not activated, snap to raster (except when using slant)
2293 if (nSA
==0 && !bSlant
)
2294 aPnt
=GetSnapPos(aPnt
);
2296 if (!bSlant
&& !bResize
)
2297 { // shear, but no resize
2299 aPnt
.setX(aP0
.X() );
2301 aPnt
.setY(aP0
.Y() );
2304 Point
aRef(DragStat().GetRef1());
2305 Point
aDif(aPnt
-aRef
);
2307 tools::Long nNewAngle
=0;
2311 nNewAngle
=NormAngle18000(-(GetAngle(aDif
)-nAngle0
));
2314 nNewAngle
=NormAngle18000(-nNewAngle
);
2319 nNewAngle
=NormAngle18000(GetAngle(aDif
));
2321 nNewAngle
=NormAngle18000(-(GetAngle(aDif
)-9000));
2323 if (nNewAngle
<-9000 || nNewAngle
>9000)
2324 nNewAngle
=NormAngle18000(nNewAngle
+18000);
2331 aPt2
=GetSnapPos(aPnt
); // snap this one in any case
2335 aNewFract
=Fraction(aPt2
.X()-aRef
.X(),aP0
.X()-aRef
.X());
2339 aNewFract
=Fraction(aPt2
.Y()-aRef
.Y(),aP0
.Y()-aRef
.Y());
2344 bool bNeg
=nNewAngle
<0;
2347 nNewAngle
=-nNewAngle
;
2356 nNewAngle
=NormAngle36000(nNewAngle
);
2357 bUpSideDown
=nNewAngle
>9000 && nNewAngle
<27000;
2360 { // calculate resize for slant
2361 // when angle snapping is activated, disable 89 degree limit
2362 tools::Long nTmpAngle
=nNewAngle
;
2363 if (bUpSideDown
) nNewAngle
-=18000;
2364 if (bNeg
) nTmpAngle
=-nTmpAngle
;
2366 aNewFract
= cos(nTmpAngle
* F_PI18000
);
2367 aFact
.ReduceInaccurate(10); // three decimals should be enough
2374 nNewAngle
=-nNewAngle
;
2376 if (nAngle
!=nNewAngle
|| aFact
!=aNewFract
)
2380 double a
= nAngle
* F_PI18000
;
2381 double nTan1
=tan(a
); // calculate now, so as little time as possible passes between Hide() and Show()
2384 DragStat().NextMove(rPnt
);
2389 void SdrDragShear::applyCurrentTransformationToSdrObject(SdrObject
& rTarget
)
2395 rTarget
.Resize(DragStat().GetRef1(),aFact
,Fraction(1,1));
2399 rTarget
.Resize(DragStat().GetRef1(),Fraction(1,1),aFact
);
2405 rTarget
.Shear(DragStat().GetRef1(), nAngle
, tan(nAngle
* F_PI18000
), bVertical
);
2409 bool SdrDragShear::EndSdrDrag(bool bCopy
)
2413 if (bResize
&& aFact
==Fraction(1,1))
2416 if (nAngle
!=0 || bResize
)
2418 if (nAngle
!=0 && bResize
)
2420 OUString aStr
= ImpGetDescriptionStr(STR_EditShear
);
2423 aStr
+= SvxResId(STR_EditWithCopy
);
2425 getSdrDragView().BegUndo(aStr
);
2432 getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),aFact
,Fraction(1,1),bCopy
);
2436 getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),Fraction(1,1),aFact
,bCopy
);
2444 getSdrDragView().ShearMarkedObj(DragStat().GetRef1(),nAngle
,bVertical
,bCopy
);
2447 if (nAngle
!=0 && bResize
)
2448 getSdrDragView().EndUndo();
2456 PointerStyle
SdrDragShear::GetSdrDragPointer() const
2459 return PointerStyle::VShear
;
2461 return PointerStyle::HShear
;
2465 void SdrDragMirror::applyCurrentTransformationToSdrObject(SdrObject
& rTarget
)
2469 rTarget
.Mirror(DragStat().GetRef1(), DragStat().GetRef2());
2473 SdrDragMirror::SdrDragMirror(SdrDragView
& rNewView
)
2474 : SdrDragMethod(rNewView
),
2481 bool SdrDragMirror::ImpCheckSide(const Point
& rPnt
) const
2483 tools::Long nAngle1
=GetAngle(rPnt
-DragStat().GetRef1());
2485 nAngle1
=NormAngle36000(nAngle1
);
2487 return nAngle1
<18000;
2490 OUString
SdrDragMirror::GetSdrDragComment() const
2494 aStr
= ImpGetDescriptionStr(STR_DragMethMirrorHori
);
2495 else if (aDif
.Y()==0)
2496 aStr
= ImpGetDescriptionStr(STR_DragMethMirrorVert
);
2497 else if (std::abs(aDif
.X()) == std::abs(aDif
.Y()))
2498 aStr
= ImpGetDescriptionStr(STR_DragMethMirrorDiag
);
2500 aStr
= ImpGetDescriptionStr(STR_DragMethMirrorFree
);
2502 if (getSdrDragView().IsDragWithCopy())
2503 aStr
+=SvxResId(STR_EditWithCopy
);
2507 bool SdrDragMirror::BeginSdrDrag()
2509 SdrHdl
* pH1
=GetHdlList().GetHdl(SdrHdlKind::Ref1
);
2510 SdrHdl
* pH2
=GetHdlList().GetHdl(SdrHdlKind::Ref2
);
2512 if (pH1
!=nullptr && pH2
!=nullptr)
2514 DragStat().SetRef1(pH1
->GetPos());
2515 DragStat().SetRef2(pH2
->GetPos());
2516 Ref1()=pH1
->GetPos();
2517 Ref2()=pH2
->GetPos();
2518 aDif
=pH2
->GetPos()-pH1
->GetPos();
2519 bool b90
=(aDif
.X()==0) || aDif
.Y()==0;
2520 bool b45
=b90
|| (std::abs(aDif
.X()) == std::abs(aDif
.Y()));
2521 nAngle
=NormAngle36000(GetAngle(aDif
));
2523 if (!getSdrDragView().IsMirrorAllowed() && !b45
)
2524 return false; // free choice of axis angle not allowed
2526 if (!getSdrDragView().IsMirrorAllowed() && !b90
)
2527 return false; // 45 degrees not allowed either
2529 bSide0
=ImpCheckSide(DragStat().GetStart());
2535 OSL_FAIL("SdrDragMirror::BeginSdrDrag(): Axis of reflection not found.");
2540 basegfx::B2DHomMatrix
SdrDragMirror::getCurrentTransformation()
2542 basegfx::B2DHomMatrix aRetval
;
2546 const double fDeltaX(DragStat().GetRef2().X() - DragStat().GetRef1().X());
2547 const double fDeltaY(DragStat().GetRef2().Y() - DragStat().GetRef1().Y());
2548 const double fRotation(atan2(fDeltaY
, fDeltaX
));
2550 aRetval
= basegfx::utils::createTranslateB2DHomMatrix(-DragStat().GetRef1().X(), -DragStat().GetRef1().Y());
2551 aRetval
.rotate(-fRotation
);
2552 aRetval
.scale(1.0, -1.0);
2553 aRetval
.rotate(fRotation
);
2554 aRetval
.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y());
2560 void SdrDragMirror::MoveSdrDrag(const Point
& rPnt
)
2562 if (!DragStat().CheckMinMoved(rPnt
))
2565 bool bNewSide
=ImpCheckSide(rPnt
);
2566 bool bNewMirrored
=bSide0
!=bNewSide
;
2568 if (bMirrored
!=bNewMirrored
)
2571 bMirrored
=bNewMirrored
;
2572 DragStat().NextMove(rPnt
);
2577 bool SdrDragMirror::EndSdrDrag(bool bCopy
)
2583 getSdrDragView().MirrorMarkedObj(DragStat().GetRef1(),DragStat().GetRef2(),bCopy
);
2589 PointerStyle
SdrDragMirror::GetSdrDragPointer() const
2591 return PointerStyle::Mirror
;
2595 SdrDragGradient::SdrDragGradient(SdrDragView
& rNewView
, bool bGrad
)
2596 : SdrDragMethod(rNewView
),
2597 pIAOHandle(nullptr),
2602 OUString
SdrDragGradient::GetSdrDragComment() const
2605 return ImpGetDescriptionStr(STR_DragMethGradient
);
2607 return ImpGetDescriptionStr(STR_DragMethTransparence
);
2610 bool SdrDragGradient::BeginSdrDrag()
2612 bool bRetval(false);
2614 pIAOHandle
= static_cast<SdrHdlGradient
*>(GetHdlList().GetHdl(IsGradient() ? SdrHdlKind::Gradient
: SdrHdlKind::Transparence
));
2619 DragStat().SetRef1( pIAOHandle
->GetPos() );
2620 DragStat().SetRef2( pIAOHandle
->Get2ndPos() );
2624 SdrHdlColor
* pColHdl
= pIAOHandle
->GetColorHdl1();
2626 // init handling flags
2627 pIAOHandle
->SetMoveSingleHandle(false);
2628 pIAOHandle
->SetMoveFirstHandle(false);
2630 // test first color handle
2633 basegfx::B2DPoint
aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2635 if(pColHdl
->getOverlayObjectList().isHitLogic(aPosition
))
2638 pIAOHandle
->SetMoveSingleHandle(true);
2639 pIAOHandle
->SetMoveFirstHandle(true);
2643 // test second color handle
2644 pColHdl
= pIAOHandle
->GetColorHdl2();
2646 if(!bHit
&& pColHdl
)
2648 basegfx::B2DPoint
aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2650 if(pColHdl
->getOverlayObjectList().isHitLogic(aPosition
))
2653 pIAOHandle
->SetMoveSingleHandle(true);
2657 // test gradient handle itself
2660 basegfx::B2DPoint
aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2662 if(pIAOHandle
->getOverlayObjectList().isHitLogic(aPosition
))
2668 // everything up and running :o}
2673 OSL_FAIL("SdrDragGradient::BeginSdrDrag(): IAOGradient not found.");
2679 void SdrDragGradient::MoveSdrDrag(const Point
& rPnt
)
2681 if(!(pIAOHandle
&& DragStat().CheckMinMoved(rPnt
)))
2684 DragStat().NextMove(rPnt
);
2686 // Do the Move here!!! DragStat().GetStart()
2687 Point aMoveDiff
= rPnt
- DragStat().GetStart();
2689 if(pIAOHandle
->IsMoveSingleHandle())
2691 if(pIAOHandle
->IsMoveFirstHandle())
2693 pIAOHandle
->SetPos(DragStat().GetRef1() + aMoveDiff
);
2694 if(pIAOHandle
->GetColorHdl1())
2695 pIAOHandle
->GetColorHdl1()->SetPos(DragStat().GetRef1() + aMoveDiff
);
2699 pIAOHandle
->Set2ndPos(DragStat().GetRef2() + aMoveDiff
);
2700 if(pIAOHandle
->GetColorHdl2())
2701 pIAOHandle
->GetColorHdl2()->SetPos(DragStat().GetRef2() + aMoveDiff
);
2706 pIAOHandle
->SetPos(DragStat().GetRef1() + aMoveDiff
);
2707 pIAOHandle
->Set2ndPos(DragStat().GetRef2() + aMoveDiff
);
2709 if(pIAOHandle
->GetColorHdl1())
2710 pIAOHandle
->GetColorHdl1()->SetPos(DragStat().GetRef1() + aMoveDiff
);
2712 if(pIAOHandle
->GetColorHdl2())
2713 pIAOHandle
->GetColorHdl2()->SetPos(DragStat().GetRef2() + aMoveDiff
);
2717 pIAOHandle
->FromIAOToItem(getSdrDragView().GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(), false, false);
2720 bool SdrDragGradient::EndSdrDrag(bool /*bCopy*/)
2722 Ref1() = pIAOHandle
->GetPos();
2723 Ref2() = pIAOHandle
->Get2ndPos();
2726 pIAOHandle
->FromIAOToItem(getSdrDragView().GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(), true, true);
2731 void SdrDragGradient::CancelSdrDrag()
2733 // restore old values
2734 pIAOHandle
->SetPos(DragStat().GetRef1());
2735 pIAOHandle
->Set2ndPos(DragStat().GetRef2());
2737 if(pIAOHandle
->GetColorHdl1())
2738 pIAOHandle
->GetColorHdl1()->SetPos(DragStat().GetRef1());
2740 if(pIAOHandle
->GetColorHdl2())
2741 pIAOHandle
->GetColorHdl2()->SetPos(DragStat().GetRef2());
2744 pIAOHandle
->FromIAOToItem(getSdrDragView().GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(), true, false);
2747 PointerStyle
SdrDragGradient::GetSdrDragPointer() const
2749 return PointerStyle::RefHand
;
2753 SdrDragCrook::SdrDragCrook(SdrDragView
& rNewView
)
2754 : SdrDragMethod(rNewView
),
2756 bContortionAllowed(false),
2757 bNoContortionAllowed(false),
2759 bResizeAllowed(false),
2761 bRotateAllowed(false),
2772 eMode(SdrCrookMode::Rotate
)
2776 OUString
SdrDragCrook::GetSdrDragComment() const
2778 OUString aStr
= ImpGetDescriptionStr(!bContortion
? STR_DragMethCrook
: STR_DragMethCrookContortion
);
2784 sal_Int32
nVal(nAngle
);
2789 nVal
= std::abs(nVal
);
2790 aStr
+= SdrModel::GetAngleString(nVal
) + ")";
2793 if(getSdrDragView().IsDragWithCopy())
2794 aStr
+= SvxResId(STR_EditWithCopy
);
2798 // These defines parametrize the created raster
2800 #define DRAG_CROOK_RASTER_MINIMUM (4)
2801 #define DRAG_CROOK_RASTER_MAXIMUM (15)
2802 #define DRAG_CROOK_RASTER_DISTANCE (30)
2804 static basegfx::B2DPolyPolygon
impCreateDragRaster(SdrPageView
const & rPageView
, const tools::Rectangle
& rMarkRect
)
2806 basegfx::B2DPolyPolygon aRetval
;
2808 if(rPageView
.PageWindowCount())
2810 OutputDevice
& rOut
= rPageView
.GetPageWindow(0)->GetPaintWindow().GetOutputDevice();
2811 tools::Rectangle aPixelSize
= rOut
.LogicToPixel(rMarkRect
);
2812 sal_uInt32
nHorDiv(aPixelSize
.GetWidth() / DRAG_CROOK_RASTER_DISTANCE
);
2813 sal_uInt32
nVerDiv(aPixelSize
.GetHeight() / DRAG_CROOK_RASTER_DISTANCE
);
2815 if(nHorDiv
> DRAG_CROOK_RASTER_MAXIMUM
)
2816 nHorDiv
= DRAG_CROOK_RASTER_MAXIMUM
;
2817 if(nHorDiv
< DRAG_CROOK_RASTER_MINIMUM
)
2818 nHorDiv
= DRAG_CROOK_RASTER_MINIMUM
;
2820 if(nVerDiv
> DRAG_CROOK_RASTER_MAXIMUM
)
2821 nVerDiv
= DRAG_CROOK_RASTER_MAXIMUM
;
2822 if(nVerDiv
< DRAG_CROOK_RASTER_MINIMUM
)
2823 nVerDiv
= DRAG_CROOK_RASTER_MINIMUM
;
2825 const double fXLen(rMarkRect
.GetWidth() / static_cast<double>(nHorDiv
));
2826 const double fYLen(rMarkRect
.GetHeight() / static_cast<double>(nVerDiv
));
2827 double fYPos(rMarkRect
.Top());
2830 for(a
= 0; a
<= nVerDiv
; a
++)
2833 for(b
= 0; b
< nHorDiv
; b
++)
2835 basegfx::B2DPolygon aHorLineSegment
;
2837 const double fNewX(rMarkRect
.Left() + (b
* fXLen
));
2838 aHorLineSegment
.append(basegfx::B2DPoint(fNewX
, fYPos
));
2839 aHorLineSegment
.appendBezierSegment(
2840 basegfx::B2DPoint(fNewX
+ (fXLen
* (1.0 / 3.0)), fYPos
),
2841 basegfx::B2DPoint(fNewX
+ (fXLen
* (2.0 / 3.0)), fYPos
),
2842 basegfx::B2DPoint(fNewX
+ fXLen
, fYPos
));
2843 aRetval
.append(aHorLineSegment
);
2850 double fXPos(rMarkRect
.Left());
2852 for(a
= 0; a
<= nHorDiv
; a
++)
2855 for(b
= 0; b
< nVerDiv
; b
++)
2857 basegfx::B2DPolygon aVerLineSegment
;
2859 const double fNewY(rMarkRect
.Top() + (b
* fYLen
));
2860 aVerLineSegment
.append(basegfx::B2DPoint(fXPos
, fNewY
));
2861 aVerLineSegment
.appendBezierSegment(
2862 basegfx::B2DPoint(fXPos
, fNewY
+ (fYLen
* (1.0 / 3.0))),
2863 basegfx::B2DPoint(fXPos
, fNewY
+ (fYLen
* (2.0 / 3.0))),
2864 basegfx::B2DPoint(fXPos
, fNewY
+ fYLen
));
2865 aRetval
.append(aVerLineSegment
);
2876 void SdrDragCrook::createSdrDragEntries()
2878 // Add extended frame raster first, so it will be behind objects
2879 if(getSdrDragView().GetSdrPageView())
2881 const basegfx::B2DPolyPolygon
aDragRaster(impCreateDragRaster(*getSdrDragView().GetSdrPageView(), GetMarkedRect()));
2883 if(aDragRaster
.count())
2885 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntryPolyPolygon(aDragRaster
)));
2890 SdrDragMethod::createSdrDragEntries();
2893 bool SdrDragCrook::BeginSdrDrag()
2895 bContortionAllowed
=getSdrDragView().IsCrookAllowed();
2896 bNoContortionAllowed
=getSdrDragView().IsCrookAllowed(true);
2897 bResizeAllowed
=getSdrDragView().IsResizeAllowed();
2898 bRotateAllowed
=getSdrDragView().IsRotateAllowed();
2900 if (bContortionAllowed
|| bNoContortionAllowed
)
2902 bVertical
=(GetDragHdlKind()==SdrHdlKind::Lower
|| GetDragHdlKind()==SdrHdlKind::Upper
);
2903 aMarkRect
=GetMarkedRect();
2904 aMarkCenter
=aMarkRect
.Center();
2905 nMarkSize
=bVertical
? (aMarkRect
.GetHeight()-1) : (aMarkRect
.GetWidth()-1);
2906 aCenter
=aMarkCenter
;
2907 aStart
=DragStat().GetStart();
2917 void SdrDragCrook::MovAllPoints(basegfx::B2DPolyPolygon
& rTarget
)
2919 SdrPageView
* pPV
= getSdrDragView().GetSdrPageView();
2924 XPolyPolygon
aTempPolyPoly(rTarget
);
2926 if (pPV
->HasMarkedObjPageView())
2928 sal_uInt16 nPolyCount
=aTempPolyPoly
.Count();
2930 if (!bContortion
&& !getSdrDragView().IsNoDragXorPolys())
2932 sal_uInt16 n1st
=0,nLast
=0;
2935 while (n1st
<nPolyCount
)
2938 while (nLast
<nPolyCount
&& aTempPolyPoly
[nLast
].GetPointCount()!=0) nLast
++;
2939 tools::Rectangle
aBound(aTempPolyPoly
[n1st
].GetBoundRect());
2942 for (i
=n1st
+1; i
<nLast
; i
++)
2944 aBound
.Union(aTempPolyPoly
[n1st
].GetBoundRect());
2947 Point
aCtr0(aBound
.Center());
2952 Fraction
aFact1(1,1);
2956 ResizePoint(aCtr1
,aC
,aFact1
,aFact
);
2960 ResizePoint(aCtr1
,aC
,aFact
,aFact1
);
2965 double nSin
=0,nCos
=0;
2967 if (aRad
.X()!=0 && aRad
.Y()!=0)
2973 case SdrCrookMode::Rotate
: CrookRotateXPoint (aCtr1
,nullptr,nullptr,aC
,aRad
,nSin
,nCos
,bVertical
); break;
2974 case SdrCrookMode::Slant
: CrookSlantXPoint (aCtr1
,nullptr,nullptr,aC
,aRad
,nSin
,nCos
,bVertical
); break;
2975 case SdrCrookMode::Stretch
: CrookStretchXPoint(aCtr1
,nullptr,nullptr,aC
,aRad
,nSin
,nCos
,bVertical
,aMarkRect
); break;
2981 for (i
=n1st
; i
<nLast
; i
++)
2985 RotateXPoly(aTempPolyPoly
[i
],aCtr0
,nSin
,nCos
);
2988 aTempPolyPoly
[i
].Move(aCtr1
.X(),aCtr1
.Y());
2998 for (j
=0; j
<nPolyCount
; j
++)
3000 XPolygon
& aPol
=aTempPolyPoly
[j
];
3001 sal_uInt16 nPointCount
=aPol
.GetPointCount();
3004 while (i
<nPointCount
)
3006 Point
* pPnt
=&aPol
[i
];
3010 if (i
+1<nPointCount
&& aPol
.IsControl(i
))
3011 { // control point on the left
3019 if (i
<nPointCount
&& aPol
.IsControl(i
))
3020 { // control point on the right
3025 MovCrookPoint(*pPnt
,pC1
,pC2
);
3031 rTarget
= aTempPolyPoly
.getB2DPolyPolygon();
3034 void SdrDragCrook::MovCrookPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
)
3036 bool bVert
=bVertical
;
3037 bool bC1
=pC1
!=nullptr;
3038 bool bC2
=pC2
!=nullptr;
3043 Fraction
aFact1(1,1);
3047 ResizePoint(rPnt
,aC
,aFact1
,aFact
);
3050 ResizePoint(*pC1
,aC
,aFact1
,aFact
);
3053 ResizePoint(*pC2
,aC
,aFact1
,aFact
);
3057 ResizePoint(rPnt
,aC
,aFact
,aFact1
);
3060 ResizePoint(*pC1
,aC
,aFact
,aFact1
);
3063 ResizePoint(*pC2
,aC
,aFact
,aFact1
);
3067 if (aRad
.X()!=0 && aRad
.Y()!=0)
3073 case SdrCrookMode::Rotate
: CrookRotateXPoint (rPnt
,pC1
,pC2
,aC
,aRad
,nSin
,nCos
,bVert
); break;
3074 case SdrCrookMode::Slant
: CrookSlantXPoint (rPnt
,pC1
,pC2
,aC
,aRad
,nSin
,nCos
,bVert
); break;
3075 case SdrCrookMode::Stretch
: CrookStretchXPoint(rPnt
,pC1
,pC2
,aC
,aRad
,nSin
,nCos
,bVert
,aMarkRect
); break;
3080 void SdrDragCrook::MoveSdrDrag(const Point
& rPnt
)
3082 if (!DragStat().CheckMinMoved(rPnt
))
3085 bool bNewMoveOnly
=getSdrDragView().IsMoveOnlyDragging();
3087 SdrCrookMode eNewMode
=getSdrDragView().GetCrookMode();
3088 bool bNewContortion
=!bNewMoveOnly
&& ((bContortionAllowed
&& !getSdrDragView().IsCrookNoContortion()) || !bNoContortionAllowed
);
3089 bResize
=!getSdrDragView().IsOrtho() && bResizeAllowed
&& !bNewMoveOnly
;
3090 bool bNewRotate
=bRotateAllowed
&& !bNewContortion
&& !bNewMoveOnly
&& eNewMode
==SdrCrookMode::Rotate
;
3092 Point
aPnt(GetSnapPos(rPnt
));
3094 Point
aNewCenter(aMarkCenter
.X(),aStart
.Y());
3098 aNewCenter
.setX(aStart
.X() );
3099 aNewCenter
.setY(aMarkCenter
.Y() );
3102 if (!getSdrDragView().IsCrookAtCenter())
3104 switch (GetDragHdlKind())
3106 case SdrHdlKind::UpperLeft
: aNewCenter
.setX(aMarkRect
.Right() ); bLft
=true; break;
3107 case SdrHdlKind::Upper
: aNewCenter
.setY(aMarkRect
.Bottom() ); bUpr
=true; break;
3108 case SdrHdlKind::UpperRight
: aNewCenter
.setX(aMarkRect
.Left() ); bRgt
=true; break;
3109 case SdrHdlKind::Left
: aNewCenter
.setX(aMarkRect
.Right() ); bLft
=true; break;
3110 case SdrHdlKind::Right
: aNewCenter
.setX(aMarkRect
.Left() ); bRgt
=true; break;
3111 case SdrHdlKind::LowerLeft
: aNewCenter
.setX(aMarkRect
.Right() ); bLft
=true; break;
3112 case SdrHdlKind::Lower
: aNewCenter
.setY(aMarkRect
.Top() ); bLwr
=true; break;
3113 case SdrHdlKind::LowerRight
: aNewCenter
.setX(aMarkRect
.Left() ); bRgt
=true; break;
3114 default: bAtCenter
=true;
3120 Fraction
aNewFract(1,1);
3121 tools::Long dx1
=aPnt
.X()-aNewCenter
.X();
3122 tools::Long dy1
=aPnt
.Y()-aNewCenter
.Y();
3123 bValid
=bVertical
? dx1
!=0 : dy1
!=0;
3128 bValid
= std::abs(dx1
)*100>std::abs(dy1
);
3130 bValid
= std::abs(dy1
)*100>std::abs(dx1
);
3133 tools::Long nNewRad
=0;
3138 double a
=0; // slope of the radius
3139 tools::Long nPntWink
=0;
3143 a
=static_cast<double>(dy1
)/static_cast<double>(dx1
); // slope of the radius
3144 nNewRad
=(static_cast<tools::Long
>(dy1
*a
)+dx1
) /2;
3145 aNewCenter
.AdjustX(nNewRad
);
3146 nPntWink
=GetAngle(aPnt
-aNewCenter
);
3150 a
=static_cast<double>(dx1
)/static_cast<double>(dy1
); // slope of the radius
3151 nNewRad
=(static_cast<tools::Long
>(dx1
*a
)+dy1
) /2;
3152 aNewCenter
.AdjustY(nNewRad
);
3153 nPntWink
=GetAngle(aPnt
-aNewCenter
)-9000;
3160 if (bRgt
) nPntWink
+=18000;
3161 if (bLft
) nPntWink
=18000-nPntWink
;
3162 if (bLwr
) nPntWink
=-nPntWink
;
3166 if (bRgt
) nPntWink
=-nPntWink
;
3167 if (bUpr
) nPntWink
=18000-nPntWink
;
3168 if (bLwr
) nPntWink
+=18000;
3171 nPntWink
=NormAngle36000(nPntWink
);
3175 if (nNewRad
<0) nPntWink
+=18000;
3176 if (bVertical
) nPntWink
=18000-nPntWink
;
3177 nPntWink
=NormAngle18000(nPntWink
);
3178 nPntWink
= std::abs(nPntWink
);
3181 double nUmfang
= 2 * std::abs(nNewRad
) * M_PI
;
3185 tools::Long nMul
=static_cast<tools::Long
>(nUmfang
*NormAngle36000(nPntWink
)/36000);
3190 aNewFract
=Fraction(nMul
,nMarkSize
);
3195 nAngle
=static_cast<tools::Long
>((nMarkSize
*360/nUmfang
)*100)/2;
3202 if (nAngle
==0 || nNewRad
==0)
3208 if (!bValid
&& bResize
)
3210 tools::Long nMul
=bVertical
? dy1
: dx1
;
3215 tools::Long nDiv
=nMarkSize
;
3220 nMul
= std::abs(nMul
);
3223 aNewFract
=Fraction(nMul
,nDiv
);
3226 if (aNewCenter
==aCenter
&& bNewContortion
==bContortion
&& aNewFract
==aFact
&&
3227 bNewMoveOnly
== getMoveOnly() && bNewRotate
==bRotate
&& eNewMode
==eMode
)
3231 setMoveOnly(bNewMoveOnly
);
3234 bContortion
=bNewContortion
;
3237 aRad
=Point(nNewRad
,nNewRad
);
3238 bResize
=aFact
!=Fraction(1,1) && aFact
.GetDenominator()!=0 && aFact
.IsValid();
3239 DragStat().NextMove(aPnt
);
3243 void SdrDragCrook::applyCurrentTransformationToSdrObject(SdrObject
& rTarget
)
3245 const bool bDoResize(aFact
!=Fraction(1,1));
3246 const bool bDoCrook(aCenter
!=aMarkCenter
&& aRad
.X()!=0 && aRad
.Y()!=0);
3248 if (!(bDoCrook
|| bDoResize
))
3253 Fraction
aFact1(1,1);
3259 rTarget
.Resize(aCenter
,aFact1
,aFact
);
3263 rTarget
.Resize(aCenter
,aFact
,aFact1
);
3268 Point
aCtr0(rTarget
.GetSnapRect().Center());
3273 ResizePoint(aCtr1
,aCenter
,aFact1
,aFact
);
3277 ResizePoint(aCtr1
,aCenter
,aFact
,aFact1
);
3280 Size
aSiz(aCtr1
.X()-aCtr0
.X(),aCtr1
.Y()-aCtr0
.Y());
3288 const tools::Rectangle
aLocalMarkRect(getSdrDragView().GetMarkedObjRect());
3289 const bool bLocalRotate(!bContortion
&& eMode
== SdrCrookMode::Rotate
&& getSdrDragView().IsRotateAllowed());
3291 SdrEditView::ImpCrookObj(&rTarget
,aCenter
,aRad
,eMode
,bVertical
,!bContortion
,bLocalRotate
,aLocalMarkRect
);
3295 void SdrDragCrook::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon
& rTarget
)
3297 // use helper derived from old stuff
3298 MovAllPoints(rTarget
);
3301 bool SdrDragCrook::EndSdrDrag(bool bCopy
)
3305 if (bResize
&& aFact
==Fraction(1,1))
3308 const bool bUndo
= getSdrDragView().IsUndoEnabled();
3310 bool bDoCrook
=aCenter
!=aMarkCenter
&& aRad
.X()!=0 && aRad
.Y()!=0;
3312 if (bDoCrook
|| bResize
)
3314 if (bResize
&& bUndo
)
3316 OUString aStr
= ImpGetDescriptionStr(!bContortion
?STR_EditCrook
:STR_EditCrookContortion
);
3319 aStr
+= SvxResId(STR_EditWithCopy
);
3321 getSdrDragView().BegUndo(aStr
);
3326 Fraction
aFact1(1,1);
3331 getSdrDragView().ResizeMarkedObj(aCenter
,aFact1
,aFact
,bCopy
);
3333 getSdrDragView().ResizeMarkedObj(aCenter
,aFact
,aFact1
,bCopy
);
3338 getSdrDragView().CopyMarkedObj();
3340 const size_t nMarkCount
=getSdrDragView().GetMarkedObjectList().GetMarkCount();
3342 for (size_t nm
=0; nm
<nMarkCount
; ++nm
)
3344 SdrMark
* pM
=getSdrDragView().GetMarkedObjectList().GetMark(nm
);
3345 SdrObject
* pO
=pM
->GetMarkedSdrObj();
3346 Point
aCtr0(pO
->GetSnapRect().Center());
3350 ResizePoint(aCtr1
,aCenter
,aFact1
,aFact
);
3352 ResizePoint(aCtr1
,aCenter
,aFact
,aFact1
);
3354 Size
aSiz(aCtr1
.X()-aCtr0
.X(),aCtr1
.Y()-aCtr0
.Y());
3356 AddUndo(getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pO
,aSiz
));
3366 getSdrDragView().CrookMarkedObj(aCenter
,aRad
,eMode
,bVertical
,!bContortion
,bCopy
);
3369 if (bResize
&& bUndo
)
3370 getSdrDragView().EndUndo();
3378 PointerStyle
SdrDragCrook::GetSdrDragPointer() const
3380 return PointerStyle::Crook
;
3384 SdrDragDistort::SdrDragDistort(SdrDragView
& rNewView
)
3385 : SdrDragMethod(rNewView
),
3387 bContortionAllowed(false),
3388 bNoContortionAllowed(false),
3393 OUString
SdrDragDistort::GetSdrDragComment() const
3395 OUString aStr
= ImpGetDescriptionStr(STR_DragMethDistort
)
3397 + getSdrDragView().GetModel()->GetMetricString(DragStat().GetDX())
3399 + getSdrDragView().GetModel()->GetMetricString(DragStat().GetDY())
3402 if(getSdrDragView().IsDragWithCopy())
3403 aStr
+= SvxResId(STR_EditWithCopy
);
3407 void SdrDragDistort::createSdrDragEntries()
3409 // Add extended frame raster first, so it will be behind objects
3410 if(getSdrDragView().GetSdrPageView())
3412 const basegfx::B2DPolyPolygon
aDragRaster(impCreateDragRaster(*getSdrDragView().GetSdrPageView(), GetMarkedRect()));
3414 if(aDragRaster
.count())
3416 addSdrDragEntry(std::unique_ptr
<SdrDragEntry
>(new SdrDragEntryPolyPolygon(aDragRaster
)));
3421 SdrDragMethod::createSdrDragEntries();
3424 bool SdrDragDistort::BeginSdrDrag()
3426 bContortionAllowed
=getSdrDragView().IsDistortAllowed();
3427 bNoContortionAllowed
=getSdrDragView().IsDistortAllowed(true);
3429 if (bContortionAllowed
|| bNoContortionAllowed
)
3431 SdrHdlKind eKind
=GetDragHdlKind();
3434 if (eKind
==SdrHdlKind::UpperLeft
) nPolyPt
=0;
3435 if (eKind
==SdrHdlKind::UpperRight
) nPolyPt
=1;
3436 if (eKind
==SdrHdlKind::LowerRight
) nPolyPt
=2;
3437 if (eKind
==SdrHdlKind::LowerLeft
) nPolyPt
=3;
3438 if (nPolyPt
>3) return false;
3440 aMarkRect
=GetMarkedRect();
3441 aDistortedRect
=XPolygon(aMarkRect
);
3451 void SdrDragDistort::MovAllPoints(basegfx::B2DPolyPolygon
& rTarget
)
3456 SdrPageView
* pPV
= getSdrDragView().GetSdrPageView();
3458 if(pPV
&& pPV
->HasMarkedObjPageView())
3460 basegfx::B2DPolyPolygon
aDragPolygon(rTarget
);
3461 const basegfx::B2DRange aOriginalRange
= vcl::unotools::b2DRectangleFromRectangle(aMarkRect
);
3462 const basegfx::B2DPoint
aTopLeft(aDistortedRect
[0].X(), aDistortedRect
[0].Y());
3463 const basegfx::B2DPoint
aTopRight(aDistortedRect
[1].X(), aDistortedRect
[1].Y());
3464 const basegfx::B2DPoint
aBottomLeft(aDistortedRect
[3].X(), aDistortedRect
[3].Y());
3465 const basegfx::B2DPoint
aBottomRight(aDistortedRect
[2].X(), aDistortedRect
[2].Y());
3467 aDragPolygon
= basegfx::utils::distort(aDragPolygon
, aOriginalRange
, aTopLeft
, aTopRight
, aBottomLeft
, aBottomRight
);
3468 rTarget
= aDragPolygon
;
3472 void SdrDragDistort::MoveSdrDrag(const Point
& rPnt
)
3474 if (!DragStat().CheckMinMoved(rPnt
))
3477 Point
aPnt(GetSnapPos(rPnt
));
3479 if (getSdrDragView().IsOrtho())
3480 OrthoDistance8(DragStat().GetStart(),aPnt
,getSdrDragView().IsBigOrtho());
3482 bool bNewContortion
=(bContortionAllowed
&& !getSdrDragView().IsCrookNoContortion()) || !bNoContortionAllowed
;
3484 if (bNewContortion
!=bContortion
|| aDistortedRect
[nPolyPt
]!=aPnt
)
3487 aDistortedRect
[nPolyPt
]=aPnt
;
3488 bContortion
=bNewContortion
;
3489 DragStat().NextMove(aPnt
);
3494 bool SdrDragDistort::EndSdrDrag(bool bCopy
)
3497 bool bDoDistort
=DragStat().GetDX()!=0 || DragStat().GetDY()!=0;
3501 getSdrDragView().DistortMarkedObj(aMarkRect
,aDistortedRect
,!bContortion
,bCopy
);
3508 PointerStyle
SdrDragDistort::GetSdrDragPointer() const
3510 return PointerStyle::RefHand
;
3513 void SdrDragDistort::applyCurrentTransformationToSdrObject(SdrObject
& rTarget
)
3515 const bool bDoDistort(DragStat().GetDX()!=0 || DragStat().GetDY()!=0);
3519 SdrEditView::ImpDistortObj(&rTarget
, aMarkRect
, aDistortedRect
, !bContortion
);
3523 void SdrDragDistort::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon
& rTarget
)
3525 // use helper derived from old stuff
3526 MovAllPoints(rTarget
);
3530 SdrDragCrop::SdrDragCrop(SdrDragView
& rNewView
)
3531 : SdrDragObjOwn(rNewView
)
3533 // switch off solid dragging for crop; it just makes no sense since showing
3534 // a 50% transparent object above the original will not be visible
3535 setSolidDraggingActive(false);
3538 OUString
SdrDragCrop::GetSdrDragComment() const
3540 OUString aStr
= ImpGetDescriptionStr(STR_DragMethCrop
)
3542 + getSdrDragView().GetModel()->GetMetricString(DragStat().GetDX())
3544 + getSdrDragView().GetModel()->GetMetricString(DragStat().GetDY())
3547 if(getSdrDragView().IsDragWithCopy())
3548 aStr
+= SvxResId(STR_EditWithCopy
);
3552 bool SdrDragCrop::BeginSdrDrag()
3555 bool bRetval(SdrDragObjOwn::BeginSdrDrag());
3559 // we need the DragHdl, break if not there
3566 bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/)
3570 if(0 == DragStat().GetDX() && 0 == DragStat().GetDY())
3576 const SdrMarkList
& rMarkList
= getSdrDragView().GetMarkedObjectList();
3578 if(1 != rMarkList
.GetMarkCount())
3580 // Crop only with single Object selected
3584 // prepare for SdrGrafObj or others. This code has to work with usual
3585 // SdrGrafObj's from Draw/Impress/Calc, but also with SdrObjects from
3586 // Writer. It would be better to handle this in Writer directly, but
3587 // there are currently no easy mechanisms to plug an alternative interaction
3589 SdrObject
* pSdrObject
= rMarkList
.GetMark(0)->GetMarkedSdrObj();
3590 SdrObjectUniquePtr pFullDragClone
;
3591 bool bExternal(false);
3592 SdrObject
* pExternalSdrObject(nullptr);
3594 // RotGrfFlyFrame: Crop decision for DrawingLayer/Writer now
3595 // locally, no two-in-one methods any more
3596 if (nullptr != pSdrObject
&& dynamic_cast< const SdrGrafObj
* >(pSdrObject
) == nullptr)
3598 // If Writer, get the already offered for interaction SdrGrafObj
3599 // and set up for using that replacement object that contains the
3600 // real transformation. That SdrObject is owned and has to be deleted,
3601 // so use a std::unique_ptr with special handling for the protected
3602 // SDrObject destructor
3603 pFullDragClone
= pSdrObject
->getFullDragClone();
3605 if(dynamic_cast< SdrGrafObj
* >(pFullDragClone
.get()))
3608 pExternalSdrObject
= pSdrObject
;
3609 pSdrObject
= pFullDragClone
.get();
3613 // get and check for SdrGrafObj now
3614 SdrGrafObj
* pObj
= dynamic_cast<SdrGrafObj
*>( pSdrObject
);
3621 // no undo for external needed, done there
3622 const bool bUndo(!bExternal
&& getSdrDragView().IsUndoEnabled());
3626 OUString aUndoStr
= ImpGetDescriptionStr(STR_DragMethCrop
);
3628 getSdrDragView().BegUndo( aUndoStr
);
3629 getSdrDragView().AddUndo( getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj
));
3630 // also need attr undo, the SdrGrafCropItem will be changed
3631 getSdrDragView().AddUndo( getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj
));
3634 // get the original objects transformation
3635 basegfx::B2DHomMatrix aOriginalMatrix
;
3636 basegfx::B2DPolyPolygon aPolyPolygon
;
3637 bool bShearCorrected(false);
3638 pObj
->TRGetBaseGeometry(aOriginalMatrix
, aPolyPolygon
);
3640 { // correct shear, it comes currently mirrored from TRGetBaseGeometry, can be removed with aw080
3641 const basegfx::utils::B2DHomMatrixBufferedDecompose
aTmpDecomp(aOriginalMatrix
);
3643 if(!basegfx::fTools::equalZero(aTmpDecomp
.getShearX()))
3645 bShearCorrected
= true;
3646 aOriginalMatrix
= basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
3647 aTmpDecomp
.getScale(),
3648 -aTmpDecomp
.getShearX(),
3649 aTmpDecomp
.getRotate(),
3650 aTmpDecomp
.getTranslate());
3654 // generate start point of original drag vector in unit coordinates (the
3655 // vis-a-vis of the drag point)
3656 basegfx::B2DPoint
aLocalStart(0.0, 0.0);
3657 bool bOnAxis(false);
3659 switch(GetDragHdlKind())
3661 case SdrHdlKind::UpperLeft
: aLocalStart
.setX(1.0); aLocalStart
.setY(1.0); break;
3662 case SdrHdlKind::Upper
: aLocalStart
.setX(0.5); aLocalStart
.setY(1.0); bOnAxis
= true; break;
3663 case SdrHdlKind::UpperRight
: aLocalStart
.setX(0.0); aLocalStart
.setY(1.0); break;
3664 case SdrHdlKind::Left
: aLocalStart
.setX(1.0); aLocalStart
.setY(0.5); bOnAxis
= true; break;
3665 case SdrHdlKind::Right
: aLocalStart
.setX(0.0); aLocalStart
.setY(0.5); bOnAxis
= true; break;
3666 case SdrHdlKind::LowerLeft
: aLocalStart
.setX(1.0); aLocalStart
.setY(0.0); break;
3667 case SdrHdlKind::Lower
: aLocalStart
.setX(0.5); aLocalStart
.setY(0.0); bOnAxis
= true; break;
3668 case SdrHdlKind::LowerRight
: aLocalStart
.setX(0.0); aLocalStart
.setY(0.0); break;
3672 // create the current drag position in unit coordinates. To get there,
3673 // transform back the DragPoint to UnitCoordinates
3674 basegfx::B2DHomMatrix
aInverse(aOriginalMatrix
);
3676 basegfx::B2DPoint
aLocalCurrent(aInverse
* basegfx::B2DPoint(DragStat().GetNow().X(), DragStat().GetNow().Y()));
3678 // if one of the edge handles is used, limit to X or Y drag only
3681 if(basegfx::fTools::equal(aLocalStart
.getX(), 0.5))
3683 aLocalCurrent
.setX(aLocalStart
.getX());
3687 aLocalCurrent
.setY(aLocalStart
.getY());
3691 // create internal change in unit coordinates
3692 basegfx::B2DHomMatrix aDiscreteChangeMatrix
;
3694 if(!basegfx::fTools::equal(aLocalCurrent
.getX(), aLocalStart
.getX()))
3696 if(aLocalStart
.getX() < 0.5)
3698 aDiscreteChangeMatrix
.scale(aLocalCurrent
.getX(), 1.0);
3702 aDiscreteChangeMatrix
.scale(1.0 - aLocalCurrent
.getX(), 1.0);
3703 aDiscreteChangeMatrix
.translate(aLocalCurrent
.getX(), 0.0);
3707 if(!basegfx::fTools::equal(aLocalCurrent
.getY(), aLocalStart
.getY()))
3709 if(aLocalStart
.getY() < 0.5)
3711 aDiscreteChangeMatrix
.scale(1.0, aLocalCurrent
.getY());
3715 aDiscreteChangeMatrix
.scale(1.0, 1.0 - aLocalCurrent
.getY());
3716 aDiscreteChangeMatrix
.translate(0.0, aLocalCurrent
.getY());
3720 // We now have the whole executed Crop in UnitCoordinates in
3721 // aDiscreteChangeMatrix, go to concrete sizes now.
3722 // Create the unrotated original rectangle and the unrotated modified
3723 // rectangle as Ranges
3724 const basegfx::utils::B2DHomMatrixBufferedDecompose
aOriginalMatrixDecomp(aOriginalMatrix
);
3726 // prepare unsheared/unrotated versions of the old and new transformation
3727 const basegfx::B2DHomMatrix
aOriginalMatrixNoShearNoRotate(
3728 basegfx::utils::createScaleTranslateB2DHomMatrix(
3729 basegfx::absolute(aOriginalMatrixDecomp
.getScale()),
3730 aOriginalMatrixDecomp
.getTranslate()));
3732 // create the ranges for these
3733 basegfx::B2DRange
aRangeOriginalNoShearNoRotate(0.0, 0.0, 1.0, 1.0);
3734 basegfx::B2DRange
aRangeNewNoShearNoRotate(0.0, 0.0, 1.0, 1.0);
3735 aRangeOriginalNoShearNoRotate
.transform(aOriginalMatrixNoShearNoRotate
);
3736 aRangeNewNoShearNoRotate
.transform(aOriginalMatrixNoShearNoRotate
* aDiscreteChangeMatrix
);
3740 // With aLocalStart point (opposed to dragged point), X scale and Y scale,
3741 // we call crop (virtual method) on pSdrObject which calls VirtFlyDrawObj
3742 // crop. Use aLocalStart unchanged, so being relative to the Crop-Action,
3743 // the called instance knows best how to use it
3744 const double fScaleX(aRangeNewNoShearNoRotate
.getWidth() / aRangeOriginalNoShearNoRotate
.getWidth());
3745 const double fScaleY(aRangeNewNoShearNoRotate
.getHeight() / aRangeOriginalNoShearNoRotate
.getHeight());
3747 pExternalSdrObject
->Crop(
3754 // prepare matrix to apply to object; evtl. back-correct shear
3755 basegfx::B2DHomMatrix
aNewObjectMatrix(aOriginalMatrix
* aDiscreteChangeMatrix
);
3759 // back-correct shear
3760 const basegfx::utils::B2DHomMatrixBufferedDecompose
aTmpDecomp(aNewObjectMatrix
);
3762 aNewObjectMatrix
= basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
3763 aTmpDecomp
.getScale(),
3764 -aTmpDecomp
.getShearX(),
3765 aTmpDecomp
.getRotate(),
3766 aTmpDecomp
.getTranslate());
3769 // apply change to object by applying the unit coordinate change followed
3770 // by the original change
3771 pObj
->TRSetBaseGeometry(aNewObjectMatrix
, aPolyPolygon
);
3773 // extract the old Rectangle structures
3774 tools::Rectangle
aOldRect(
3775 basegfx::fround(aRangeOriginalNoShearNoRotate
.getMinX()),
3776 basegfx::fround(aRangeOriginalNoShearNoRotate
.getMinY()),
3777 basegfx::fround(aRangeOriginalNoShearNoRotate
.getMaxX()),
3778 basegfx::fround(aRangeOriginalNoShearNoRotate
.getMaxY()));
3779 tools::Rectangle
aNewRect(
3780 basegfx::fround(aRangeNewNoShearNoRotate
.getMinX()),
3781 basegfx::fround(aRangeNewNoShearNoRotate
.getMinY()),
3782 basegfx::fround(aRangeNewNoShearNoRotate
.getMaxX()),
3783 basegfx::fround(aRangeNewNoShearNoRotate
.getMaxY()));
3785 // continue with the old original stuff
3786 if (!aOldRect
.GetWidth() || !aOldRect
.GetHeight())
3788 throw o3tl::divide_by_zero();
3791 if((pObj
->GetGraphicType() == GraphicType::NONE
) || (pObj
->GetGraphicType() == GraphicType::Default
))
3796 const GraphicObject
& rGraphicObject(pObj
->GetGraphicObject());
3797 // tdf#117145 Usually Writer will go the bExternal path (see above), but more correct for
3798 // the future is to use the MapMode from the SdrModel/SfxItemPool if the Writer's current
3799 // special handling should be unified to this path in the future. Usually it *should* be
3800 // MapUnit::Map100thMM, but better do not mix up Units.
3801 // Checked now what SwVirtFlyDrawObj::NbcCrop is doing - it calculates everything forced
3802 // to MapUnit::Map100thMM, but extracts/packs Twips to the used SdrGrafCropItem in Writer.
3803 const MapMode
aMapModePool(pObj
->getSdrModelFromSdrObject().GetItemPool().GetMetric(0));
3804 Size
aGraphicSize(rGraphicObject
.GetPrefSize());
3806 if(MapUnit::MapPixel
== rGraphicObject
.GetPrefMapMode().GetMapUnit())
3808 aGraphicSize
= Application::GetDefaultDevice()->PixelToLogic(aGraphicSize
, aMapModePool
);
3812 aGraphicSize
= OutputDevice::LogicToLogic(aGraphicSize
, rGraphicObject
.GetPrefMapMode(), aMapModePool
);
3815 if(0 == aGraphicSize
.Width() || 0 == aGraphicSize
.Height())
3820 const SdrGrafCropItem
& rOldCrop
= pObj
->GetMergedItem(SDRATTR_GRAFCROP
);
3821 double fScaleX
= ( aGraphicSize
.Width() - rOldCrop
.GetLeft() - rOldCrop
.GetRight() ) / static_cast<double>(aOldRect
.GetWidth());
3822 double fScaleY
= ( aGraphicSize
.Height() - rOldCrop
.GetTop() - rOldCrop
.GetBottom() ) / static_cast<double>(aOldRect
.GetHeight());
3824 sal_Int32 nDiffLeft
= aNewRect
.Left() - aOldRect
.Left();
3825 sal_Int32 nDiffTop
= aNewRect
.Top() - aOldRect
.Top();
3826 sal_Int32 nDiffRight
= aNewRect
.Right() - aOldRect
.Right();
3827 sal_Int32 nDiffBottom
= aNewRect
.Bottom() - aOldRect
.Bottom();
3829 if(pObj
->IsMirrored())
3831 // mirrored X or Y, for old stuff, exchange X
3833 sal_Int32
nTmp(nDiffLeft
);
3834 nDiffLeft
= -nDiffRight
;
3838 sal_Int32 nLeftCrop
= static_cast<sal_Int32
>( rOldCrop
.GetLeft() + nDiffLeft
* fScaleX
);
3839 sal_Int32 nTopCrop
= static_cast<sal_Int32
>( rOldCrop
.GetTop() + nDiffTop
* fScaleY
);
3840 sal_Int32 nRightCrop
= static_cast<sal_Int32
>( rOldCrop
.GetRight() - nDiffRight
* fScaleX
);
3841 sal_Int32 nBottomCrop
= static_cast<sal_Int32
>( rOldCrop
.GetBottom() - nDiffBottom
* fScaleY
);
3843 SfxItemPool
& rPool
= getSdrDragView().GetModel()->GetItemPool();
3844 SfxItemSet
aSet( rPool
, svl::Items
<SDRATTR_GRAFCROP
, SDRATTR_GRAFCROP
>{} );
3845 aSet
.Put( SdrGrafCropItem( nLeftCrop
, nTopCrop
, nRightCrop
, nBottomCrop
) );
3846 getSdrDragView().SetAttributes( aSet
, false );
3851 getSdrDragView().EndUndo();
3857 PointerStyle
SdrDragCrop::GetSdrDragPointer() const
3859 return PointerStyle::Crop
;
3862 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */