bump product version to 4.1.6.2
[LibreOffice.git] / svx / source / svdraw / svddrgmt.cxx
blobd79d5f2add250718ddd8d409231b203e3128bd43
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "svddrgm1.hxx"
21 #include <math.h>
23 #include <tools/bigint.hxx>
24 #include <vcl/svapp.hxx>
25 #include "svx/xattr.hxx"
26 #include <svx/xpoly.hxx>
27 #include <svx/svdetc.hxx>
28 #include <svx/svdtrans.hxx>
29 #include <svx/svdundo.hxx>
30 #include <svx/svdmark.hxx>
31 #include <svx/svdocapt.hxx>
32 #include <svx/svdpagv.hxx>
33 #include "svx/svdstr.hrc" // names taken from the resource
34 #include "svx/svdglob.hxx" // StringCache
35 #include <svx/svddrgv.hxx>
36 #include <svx/svdograf.hxx>
37 #include <svx/dialogs.hrc>
38 #include <svx/dialmgr.hxx>
39 #include <svx/sdgcpitm.hxx>
40 #include <basegfx/polygon/b2dpolygon.hxx>
41 #include <basegfx/polygon/b2dpolygontools.hxx>
42 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
43 #include <svx/sdr/overlay/overlaymanager.hxx>
44 #include <svx/sdr/overlay/overlayrollingrectangle.hxx>
45 #include <svx/sdrpagewindow.hxx>
46 #include <svx/sdrpaintwindow.hxx>
47 #include <basegfx/matrix/b2dhommatrix.hxx>
48 #include <basegfx/polygon/b2dpolypolygontools.hxx>
49 #include <svx/sdr/contact/viewobjectcontact.hxx>
50 #include <svx/sdr/contact/viewcontact.hxx>
51 #include <svx/sdr/contact/displayinfo.hxx>
52 #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
53 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
54 #include <svx/sdr/contact/objectcontact.hxx>
55 #include "svx/svditer.hxx"
56 #include <svx/svdopath.hxx>
57 #include <svx/polypolygoneditor.hxx>
58 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
59 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
60 #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
61 #include <svx/sdr/primitive2d/sdrattributecreator.hxx>
62 #include <svx/sdr/primitive2d/sdrdecompositiontools.hxx>
63 #include <svx/svdoole2.hxx>
64 #include <svx/svdovirt.hxx>
65 #include <svx/svdouno.hxx>
66 #include <svx/sdr/primitive2d/sdrprimitivetools.hxx>
67 #include <basegfx/matrix/b2dhommatrixtools.hxx>
68 #include <drawinglayer/attribute/sdrlineattribute.hxx>
69 #include <drawinglayer/attribute/sdrlinestartendattribute.hxx>
70 #include <map>
71 #include <vector>
73 ////////////////////////////////////////////////////////////////////////////////////////////////////
75 SdrDragEntry::SdrDragEntry()
76 : mbAddToTransparent(false)
80 SdrDragEntry::~SdrDragEntry()
84 ////////////////////////////////////////////////////////////////////////////////////////////////////
86 SdrDragEntryPolyPolygon::SdrDragEntryPolyPolygon(const basegfx::B2DPolyPolygon& rOriginalPolyPolygon)
87 : SdrDragEntry(),
88 maOriginalPolyPolygon(rOriginalPolyPolygon)
92 SdrDragEntryPolyPolygon::~SdrDragEntryPolyPolygon()
96 drawinglayer::primitive2d::Primitive2DSequence SdrDragEntryPolyPolygon::createPrimitive2DSequenceInCurrentState(SdrDragMethod& rDragMethod)
98 drawinglayer::primitive2d::Primitive2DSequence aRetval;
100 if(maOriginalPolyPolygon.count())
102 basegfx::B2DPolyPolygon aCopy(maOriginalPolyPolygon);
103 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
105 rDragMethod.applyCurrentTransformationToPolyPolygon(aCopy);
106 basegfx::BColor aColA(aSvtOptionsDrawinglayer.GetStripeColorA().getBColor());
107 basegfx::BColor aColB(aSvtOptionsDrawinglayer.GetStripeColorB().getBColor());
108 const double fStripeLength(aSvtOptionsDrawinglayer.GetStripeLength());
110 if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
112 aColA = aColB = Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
113 aColB.invert();
116 drawinglayer::primitive2d::Primitive2DReference aPolyPolygonMarkerPrimitive2D(
117 new drawinglayer::primitive2d::PolyPolygonMarkerPrimitive2D(aCopy, aColA, aColB, fStripeLength));
119 aRetval = drawinglayer::primitive2d::Primitive2DSequence(&aPolyPolygonMarkerPrimitive2D, 1);
122 return aRetval;
125 ////////////////////////////////////////////////////////////////////////////////////////////////////
127 SdrDragEntrySdrObject::SdrDragEntrySdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact, bool bModify)
128 : SdrDragEntry(),
129 maOriginal(rOriginal),
130 mpClone(0),
131 mrObjectContact(rObjectContact),
132 mbModify(bModify)
134 // add SdrObject parts to transparent overlay stuff
135 setAddToTransparent(true);
138 SdrDragEntrySdrObject::~SdrDragEntrySdrObject()
140 if(mpClone)
142 SdrObject::Free(mpClone);
146 void SdrDragEntrySdrObject::prepareCurrentState(SdrDragMethod& rDragMethod)
148 // for the moment, i need to re-create the clone in all cases. I need to figure
149 // out when clone and original have the same class, so that i can use operator=
150 // in those cases
152 if(mpClone)
154 SdrObject::Free(mpClone);
155 mpClone = 0;
158 if(mbModify)
160 if(!mpClone)
162 mpClone = maOriginal.getFullDragClone();
165 // apply original transformation, implemented at the DragMethods
166 rDragMethod.applyCurrentTransformationToSdrObject(*mpClone);
170 drawinglayer::primitive2d::Primitive2DSequence SdrDragEntrySdrObject::createPrimitive2DSequenceInCurrentState(SdrDragMethod&)
172 const SdrObject* pSource = &maOriginal;
174 if(mbModify && mpClone)
176 // choose source for geometry data
177 pSource = mpClone;
180 // get VOC and Primitive2DSequence
181 sdr::contact::ViewContact& rVC = pSource->GetViewContact();
182 sdr::contact::ViewObjectContact& rVOC = rVC.GetViewObjectContact(mrObjectContact);
183 sdr::contact::DisplayInfo aDisplayInfo;
185 // Do not use the last ViewPort set at the OC from the last ProcessDisplay(),
186 // here we want the complete primitive sequence without visibility clippings
187 mrObjectContact.resetViewPort();
189 return rVOC.getPrimitive2DSequenceHierarchy(aDisplayInfo);
192 ////////////////////////////////////////////////////////////////////////////////////////////////////
194 SdrDragEntryPrimitive2DSequence::SdrDragEntryPrimitive2DSequence(
195 const drawinglayer::primitive2d::Primitive2DSequence& rSequence,
196 bool bAddToTransparent)
197 : SdrDragEntry(),
198 maPrimitive2DSequence(rSequence)
200 // add parts to transparent overlay stuff if necessary
201 setAddToTransparent(bAddToTransparent);
204 SdrDragEntryPrimitive2DSequence::~SdrDragEntryPrimitive2DSequence()
208 drawinglayer::primitive2d::Primitive2DSequence SdrDragEntryPrimitive2DSequence::createPrimitive2DSequenceInCurrentState(SdrDragMethod& rDragMethod)
210 drawinglayer::primitive2d::Primitive2DReference aTransformPrimitive2D(
211 new drawinglayer::primitive2d::TransformPrimitive2D(
212 rDragMethod.getCurrentTransformation(),
213 maPrimitive2DSequence));
215 return drawinglayer::primitive2d::Primitive2DSequence(&aTransformPrimitive2D, 1);
218 ////////////////////////////////////////////////////////////////////////////////////////////////////
220 SdrDragEntryPointGlueDrag::SdrDragEntryPointGlueDrag(const std::vector< basegfx::B2DPoint >& rPositions, bool bIsPointDrag)
221 : maPositions(rPositions),
222 mbIsPointDrag(bIsPointDrag)
224 // add SdrObject parts to transparent overlay stuff
225 setAddToTransparent(true);
228 SdrDragEntryPointGlueDrag::~SdrDragEntryPointGlueDrag()
232 drawinglayer::primitive2d::Primitive2DSequence SdrDragEntryPointGlueDrag::createPrimitive2DSequenceInCurrentState(SdrDragMethod& rDragMethod)
234 drawinglayer::primitive2d::Primitive2DSequence aRetval;
236 if(!maPositions.empty())
238 basegfx::B2DPolygon aPolygon;
239 sal_uInt32 a(0);
241 for(a = 0; a < maPositions.size(); a++)
243 aPolygon.append(maPositions[a]);
246 basegfx::B2DPolyPolygon aPolyPolygon(aPolygon);
248 rDragMethod.applyCurrentTransformationToPolyPolygon(aPolyPolygon);
250 const basegfx::B2DPolygon aTransformed(aPolyPolygon.getB2DPolygon(0));
251 std::vector< basegfx::B2DPoint > aTransformedPositions;
253 aTransformedPositions.reserve(aTransformed.count());
255 for(a = 0; a < aTransformed.count(); a++)
257 aTransformedPositions.push_back(aTransformed.getB2DPoint(a));
260 if(mbIsPointDrag)
262 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
263 basegfx::BColor aColor(aSvtOptionsDrawinglayer.GetStripeColorA().getBColor());
265 if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
267 aColor = Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
270 drawinglayer::primitive2d::Primitive2DReference aMarkerArrayPrimitive2D(
271 new drawinglayer::primitive2d::MarkerArrayPrimitive2D(aTransformedPositions,
272 drawinglayer::primitive2d::createDefaultCross_3x3(aColor)));
274 aRetval = drawinglayer::primitive2d::Primitive2DSequence(&aMarkerArrayPrimitive2D, 1);
276 else
278 drawinglayer::primitive2d::Primitive2DReference aMarkerArrayPrimitive2D(
279 new drawinglayer::primitive2d::MarkerArrayPrimitive2D(aTransformedPositions,
280 SdrHdl::createGluePointBitmap()));
281 aRetval = drawinglayer::primitive2d::Primitive2DSequence(&aMarkerArrayPrimitive2D, 1);
285 return aRetval;
288 ////////////////////////////////////////////////////////////////////////////////////////////////////
290 TYPEINIT0(SdrDragMethod);
292 void SdrDragMethod::resetSdrDragEntries()
294 // clear entries; creation is on demand
295 clearSdrDragEntries();
298 basegfx::B2DRange SdrDragMethod::getCurrentRange() const
300 return getB2DRangeFromOverlayObjectList();
303 void SdrDragMethod::clearSdrDragEntries()
305 for(sal_uInt32 a(0); a < maSdrDragEntries.size(); a++)
307 delete maSdrDragEntries[a];
310 maSdrDragEntries.clear();
313 void SdrDragMethod::addSdrDragEntry(SdrDragEntry* pNew)
315 if(pNew)
317 maSdrDragEntries.push_back(pNew);
321 void SdrDragMethod::createSdrDragEntries()
323 if(getSdrDragView().GetSdrPageView() && getSdrDragView().GetSdrPageView()->HasMarkedObjPageView())
325 if(getSdrDragView().IsDraggingPoints())
327 createSdrDragEntries_PointDrag();
329 else if(getSdrDragView().IsDraggingGluePoints())
331 createSdrDragEntries_GlueDrag();
333 else
335 if(getSolidDraggingActive())
337 createSdrDragEntries_SolidDrag();
339 else
341 createSdrDragEntries_PolygonDrag();
347 void SdrDragMethod::createSdrDragEntryForSdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact, bool bModify)
349 // add full object drag; Clone() at the object has to work
350 // for this
351 addSdrDragEntry(new SdrDragEntrySdrObject(rOriginal, rObjectContact, bModify));
354 void SdrDragMethod::createSdrDragEntries_SolidDrag()
356 const sal_uInt32 nMarkAnz(getSdrDragView().GetMarkedObjectCount());
357 SdrPageView* pPV = getSdrDragView().GetSdrPageView();
359 if(pPV)
361 for(sal_uInt32 a(0); a < nMarkAnz; a++)
363 SdrMark* pM = getSdrDragView().GetSdrMarkByIndex(a);
365 if(pM->GetPageView() == pPV)
367 const SdrObject* pObject = pM->GetMarkedSdrObj();
369 if(pObject)
371 if(pPV->PageWindowCount())
373 sdr::contact::ObjectContact& rOC = pPV->GetPageWindow(0)->GetObjectContact();
374 SdrObjListIter aIter(*pObject);
376 while(aIter.IsMore())
378 SdrObject* pCandidate = aIter.Next();
380 if(pCandidate)
382 const bool bSuppressFullDrag(!pCandidate->supportsFullDrag());
383 bool bAddWireframe(bSuppressFullDrag);
385 if(!bAddWireframe && !pCandidate->HasLineStyle())
387 // add wireframe for objects without outline
388 bAddWireframe = true;
391 if(!bSuppressFullDrag)
393 // add full object drag; Clone() at the object has to work
394 // for this
395 createSdrDragEntryForSdrObject(*pCandidate, rOC, true);
398 if(bAddWireframe)
400 // when dragging a 50% transparent copy of a filled or not filled object without
401 // outline, this is normally hard to see. Add extra wireframe in that case. This
402 // works nice e.g. with text frames etc.
403 addSdrDragEntry(new SdrDragEntryPolyPolygon(pCandidate->TakeXorPoly()));
414 void SdrDragMethod::createSdrDragEntries_PolygonDrag()
416 const sal_uInt32 nMarkAnz(getSdrDragView().GetMarkedObjectCount());
417 bool bNoPolygons(getSdrDragView().IsNoDragXorPolys() || nMarkAnz > getSdrDragView().GetDragXorPolyLimit());
418 basegfx::B2DPolyPolygon aResult;
419 sal_uInt32 nPointCount(0);
421 for(sal_uInt32 a(0); !bNoPolygons && a < nMarkAnz; a++)
423 SdrMark* pM = getSdrDragView().GetSdrMarkByIndex(a);
425 if(pM->GetPageView() == getSdrDragView().GetSdrPageView())
427 const basegfx::B2DPolyPolygon aNewPolyPolygon(pM->GetMarkedSdrObj()->TakeXorPoly());
429 for(sal_uInt32 b(0); b < aNewPolyPolygon.count(); b++)
431 nPointCount += aNewPolyPolygon.getB2DPolygon(b).count();
434 if(nPointCount > getSdrDragView().GetDragXorPointLimit())
436 bNoPolygons = true;
439 if(!bNoPolygons)
441 aResult.append(aNewPolyPolygon);
446 if(bNoPolygons)
448 const Rectangle aR(getSdrDragView().GetSdrPageView()->MarkSnap());
449 const basegfx::B2DRange aNewRectangle(aR.Left(), aR.Top(), aR.Right(), aR.Bottom());
450 basegfx::B2DPolygon aNewPolygon(basegfx::tools::createPolygonFromRect(aNewRectangle));
452 aResult = basegfx::B2DPolyPolygon(basegfx::tools::expandToCurve(aNewPolygon));
455 if(aResult.count())
457 addSdrDragEntry(new SdrDragEntryPolyPolygon(aResult));
461 void SdrDragMethod::createSdrDragEntries_PointDrag()
463 const sal_uInt32 nMarkAnz(getSdrDragView().GetMarkedObjectCount());
464 std::vector< basegfx::B2DPoint > aPositions;
466 for(sal_uInt32 nm(0); nm < nMarkAnz; nm++)
468 SdrMark* pM = getSdrDragView().GetSdrMarkByIndex(nm);
470 if(pM->GetPageView() == getSdrDragView().GetSdrPageView())
472 const SdrUShortCont* pPts = pM->GetMarkedPoints();
474 if(pPts && !pPts->empty())
476 const SdrObject* pObj = pM->GetMarkedSdrObj();
477 const SdrPathObj* pPath = dynamic_cast< const SdrPathObj* >(pObj);
479 if(pPath)
481 const basegfx::B2DPolyPolygon aPathXPP = pPath->GetPathPoly();
483 if(aPathXPP.count())
485 for(SdrUShortCont::const_iterator it = pPts->begin(); it != pPts->end(); ++it)
487 sal_uInt32 nPolyNum, nPointNum;
488 const sal_uInt16 nObjPt = *it;
490 if(sdr::PolyPolygonEditor::GetRelativePolyPoint(aPathXPP, nObjPt, nPolyNum, nPointNum))
492 aPositions.push_back(aPathXPP.getB2DPolygon(nPolyNum).getB2DPoint(nPointNum));
501 if(!aPositions.empty())
503 addSdrDragEntry(new SdrDragEntryPointGlueDrag(aPositions, true));
507 void SdrDragMethod::createSdrDragEntries_GlueDrag()
509 const sal_uInt32 nMarkAnz(getSdrDragView().GetMarkedObjectCount());
510 std::vector< basegfx::B2DPoint > aPositions;
512 for(sal_uInt32 nm(0); nm < nMarkAnz; nm++)
514 SdrMark* pM = getSdrDragView().GetSdrMarkByIndex(nm);
516 if(pM->GetPageView() == getSdrDragView().GetSdrPageView())
518 const SdrUShortCont* pPts = pM->GetMarkedGluePoints();
520 if(pPts && !pPts->empty())
522 const SdrObject* pObj = pM->GetMarkedSdrObj();
523 const SdrGluePointList* pGPL = pObj->GetGluePointList();
525 if(pGPL)
527 for(SdrUShortCont::const_iterator it = pPts->begin(); it != pPts->end(); ++it)
529 const sal_uInt16 nObjPt = *it;
530 const sal_uInt16 nGlueNum(pGPL->FindGluePoint(nObjPt));
532 if(SDRGLUEPOINT_NOTFOUND != nGlueNum)
534 const Point aPoint((*pGPL)[nGlueNum].GetAbsolutePos(*pObj));
535 aPositions.push_back(basegfx::B2DPoint(aPoint.X(), aPoint.Y()));
543 if(!aPositions.empty())
545 addSdrDragEntry(new SdrDragEntryPointGlueDrag(aPositions, false));
549 void SdrDragMethod::ImpTakeDescriptionStr(sal_uInt16 nStrCacheID, XubString& rStr, sal_uInt16 nVal) const
551 sal_uInt16 nOpt=0;
552 if (IsDraggingPoints()) {
553 nOpt=IMPSDR_POINTSDESCRIPTION;
554 } else if (IsDraggingGluePoints()) {
555 nOpt=IMPSDR_GLUEPOINTSDESCRIPTION;
557 getSdrDragView().ImpTakeDescriptionStr(nStrCacheID,rStr,nVal,nOpt);
560 SdrObject* SdrDragMethod::GetDragObj() const
562 SdrObject* pObj=NULL;
563 if (getSdrDragView().pDragHdl!=NULL) pObj=getSdrDragView().pDragHdl->GetObj();
564 if (pObj==NULL) pObj=getSdrDragView().pMarkedObj;
565 return pObj;
568 SdrPageView* SdrDragMethod::GetDragPV() const
570 SdrPageView* pPV=NULL;
571 if (getSdrDragView().pDragHdl!=NULL) pPV=getSdrDragView().pDragHdl->GetPageView();
572 if (pPV==NULL) pPV=getSdrDragView().pMarkedPV;
573 return pPV;
576 void SdrDragMethod::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
578 // the original applies the transformation using TRGetBaseGeometry/TRSetBaseGeometry.
579 // Later this should be the only needed one for linear transforms (not for SdrDragCrook and
580 // SdrDragDistort, those are NOT linear). Currently, this can not yet be used since the
581 // special handling of rotate/mirror due to the not-being-able to handle it in the old
582 // drawinglayer stuff. Text would currently not correctly be mirrored in the preview.
583 basegfx::B2DHomMatrix aObjectTransform;
584 basegfx::B2DPolyPolygon aObjectPolyPolygon;
585 bool bPolyUsed(rTarget.TRGetBaseGeometry(aObjectTransform, aObjectPolyPolygon));
587 // apply transform to object transform
588 aObjectTransform *= getCurrentTransformation();
590 if(bPolyUsed)
592 // do something special since the object size is in the polygon
593 // break up matrix to get the scale
594 basegfx::B2DTuple aScale;
595 basegfx::B2DTuple aTranslate;
596 double fRotate, fShearX;
597 aObjectTransform.decompose(aScale, aTranslate, fRotate, fShearX);
599 // get polygon's position and size
600 const basegfx::B2DRange aPolyRange(aObjectPolyPolygon.getB2DRange());
602 // get the scaling factors (do not mirror, this is in the object transformation)
603 const double fScaleX(fabs(aScale.getX()) / (basegfx::fTools::equalZero(aPolyRange.getWidth()) ? 1.0 : aPolyRange.getWidth()));
604 const double fScaleY(fabs(aScale.getY()) / (basegfx::fTools::equalZero(aPolyRange.getHeight()) ? 1.0 : aPolyRange.getHeight()));
606 // prepare transform matrix for polygon
607 basegfx::B2DHomMatrix aPolyTransform(basegfx::tools::createTranslateB2DHomMatrix(
608 -aPolyRange.getMinX(), -aPolyRange.getMinY()));
609 aPolyTransform.scale(fScaleX, fScaleY);
611 // transform the polygon
612 aObjectPolyPolygon.transform(aPolyTransform);
615 rTarget.TRSetBaseGeometry(getCurrentTransformation() * aObjectTransform, aObjectPolyPolygon);
618 void SdrDragMethod::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon& rTarget)
620 // original uses CurrentTransformation
621 rTarget.transform(getCurrentTransformation());
624 SdrDragMethod::SdrDragMethod(SdrDragView& rNewView)
625 : maSdrDragEntries(),
626 maOverlayObjectList(),
627 mrSdrDragView(rNewView),
628 mbMoveOnly(false),
629 mbSolidDraggingActive(getSdrDragView().IsSolidDragging())
631 if(mbSolidDraggingActive && Application::GetSettings().GetStyleSettings().GetHighContrastMode())
633 // fallback to wireframe when high contrast is used
634 mbSolidDraggingActive = false;
638 SdrDragMethod::~SdrDragMethod()
640 clearSdrDragEntries();
643 void SdrDragMethod::Show()
645 getSdrDragView().ShowDragObj();
648 void SdrDragMethod::Hide()
650 getSdrDragView().HideDragObj();
653 basegfx::B2DHomMatrix SdrDragMethod::getCurrentTransformation()
655 return basegfx::B2DHomMatrix();
658 void SdrDragMethod::CancelSdrDrag()
660 Hide();
663 struct compareConstSdrObjectRefs
665 bool operator()(const SdrObject* p1, const SdrObject* p2) const
667 return (p1 < p2);
671 typedef std::map< const SdrObject*, SdrObject*, compareConstSdrObjectRefs> SdrObjectAndCloneMap;
673 void SdrDragMethod::CreateOverlayGeometry(sdr::overlay::OverlayManager& rOverlayManager)
675 // create SdrDragEntries on demand
676 if(maSdrDragEntries.empty())
678 createSdrDragEntries();
681 // if there are entries, derive OverlayObjects from the entries, including
682 // modification from current interactive state
683 if(!maSdrDragEntries.empty())
685 // #i54102# SdrDragEntrySdrObject creates clones of SdrObjects as base for creating the needed
686 // primitives, holding the original and the clone. If connectors (Edges) are involved,
687 // the cloned connectors need to be connected to the cloned SdrObjects (after cloning
688 // they are connected to the original SdrObjects). To do so, trigger the preparation
689 // steps for SdrDragEntrySdrObject, save an association of (orig, clone) in a helper
690 // and evtl. remember if it was an edge
691 SdrObjectAndCloneMap aOriginalAndClones;
692 std::vector< SdrEdgeObj* > aEdges;
693 sal_uInt32 a;
695 // #i54102# execute prepareCurrentState for all SdrDragEntrySdrObject, register pair of original and
696 // clone, remember edges
697 for(a = 0; a < maSdrDragEntries.size(); a++)
699 SdrDragEntrySdrObject* pSdrDragEntrySdrObject = dynamic_cast< SdrDragEntrySdrObject*>(maSdrDragEntries[a]);
701 if(pSdrDragEntrySdrObject)
703 pSdrDragEntrySdrObject->prepareCurrentState(*this);
705 SdrEdgeObj* pSdrEdgeObj = dynamic_cast< SdrEdgeObj* >(pSdrDragEntrySdrObject->getClone());
707 if(pSdrEdgeObj)
709 aEdges.push_back(pSdrEdgeObj);
712 if(pSdrDragEntrySdrObject->getClone())
714 aOriginalAndClones[&pSdrDragEntrySdrObject->getOriginal()] = pSdrDragEntrySdrObject->getClone();
719 // #i54102# if there are edges, reconnect their ends to the corresponding clones (if found)
720 if(aEdges.size())
722 for(a = 0; a < aEdges.size(); a++)
724 SdrEdgeObj* pSdrEdgeObj = aEdges[a];
725 SdrObject* pConnectedTo = pSdrEdgeObj->GetConnectedNode(true);
727 if(pConnectedTo)
729 SdrObjectAndCloneMap::iterator aEntry = aOriginalAndClones.find(pConnectedTo);
731 if(aEntry != aOriginalAndClones.end())
733 pSdrEdgeObj->ConnectToNode(true, aEntry->second);
737 pConnectedTo = pSdrEdgeObj->GetConnectedNode(false);
739 if(pConnectedTo)
741 SdrObjectAndCloneMap::iterator aEntry = aOriginalAndClones.find(pConnectedTo);
743 if(aEntry != aOriginalAndClones.end())
745 pSdrEdgeObj->ConnectToNode(false, aEntry->second);
751 // collect primitives for visualisation
752 drawinglayer::primitive2d::Primitive2DSequence aResult;
753 drawinglayer::primitive2d::Primitive2DSequence aResultTransparent;
755 for(a = 0; a < maSdrDragEntries.size(); a++)
757 SdrDragEntry* pCandidate = maSdrDragEntries[a];
759 if(pCandidate)
761 const drawinglayer::primitive2d::Primitive2DSequence aCandidateResult(pCandidate->createPrimitive2DSequenceInCurrentState(*this));
763 if(aCandidateResult.hasElements())
765 if(pCandidate->getAddToTransparent())
767 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(aResultTransparent, aCandidateResult);
769 else
771 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(aResult, aCandidateResult);
777 if(DoAddConnectorOverlays())
779 const drawinglayer::primitive2d::Primitive2DSequence aConnectorOverlays(AddConnectorOverlays());
781 if(aConnectorOverlays.hasElements())
783 // add connector overlays to transparent part
784 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(aResultTransparent, aConnectorOverlays);
788 if(aResult.hasElements())
790 sdr::overlay::OverlayObject* pNewOverlayObject = new sdr::overlay::OverlayPrimitive2DSequenceObject(aResult);
791 rOverlayManager.add(*pNewOverlayObject);
792 addToOverlayObjectList(*pNewOverlayObject);
795 if(aResultTransparent.hasElements())
797 drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparencePrimitive2D(new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(aResultTransparent, 0.5));
798 aResultTransparent = drawinglayer::primitive2d::Primitive2DSequence(&aUnifiedTransparencePrimitive2D, 1);
800 sdr::overlay::OverlayObject* pNewOverlayObject = new sdr::overlay::OverlayPrimitive2DSequenceObject(aResultTransparent);
801 rOverlayManager.add(*pNewOverlayObject);
802 addToOverlayObjectList(*pNewOverlayObject);
806 // add DragStripes if necessary (help lines cross the page when dragging)
807 if(getSdrDragView().IsDragStripes())
809 Rectangle aActionRectangle;
810 getSdrDragView().TakeActionRect(aActionRectangle);
812 const basegfx::B2DPoint aTopLeft(aActionRectangle.Left(), aActionRectangle.Top());
813 const basegfx::B2DPoint aBottomRight(aActionRectangle.Right(), aActionRectangle.Bottom());
814 sdr::overlay::OverlayRollingRectangleStriped* pNew = new sdr::overlay::OverlayRollingRectangleStriped(
815 aTopLeft, aBottomRight, true, false);
817 rOverlayManager.add(*pNew);
818 addToOverlayObjectList(*pNew);
822 void SdrDragMethod::destroyOverlayGeometry()
824 clearOverlayObjectList();
827 bool SdrDragMethod::DoAddConnectorOverlays()
829 // these conditions are translated from SdrDragView::ImpDrawEdgeXor
830 const SdrMarkList& rMarkedNodes = getSdrDragView().GetEdgesOfMarkedNodes();
832 if(!rMarkedNodes.GetMarkCount())
834 return false;
837 if(!getSdrDragView().IsRubberEdgeDragging() && !getSdrDragView().IsDetailedEdgeDragging())
839 return false;
842 if(getSdrDragView().IsDraggingPoints() || getSdrDragView().IsDraggingGluePoints())
844 return false;
847 if(!getMoveOnly() && !(
848 IS_TYPE(SdrDragMove, this) || IS_TYPE(SdrDragResize, this) ||
849 IS_TYPE(SdrDragRotate,this) || IS_TYPE(SdrDragMirror,this)))
851 return false;
854 const bool bDetail(getSdrDragView().IsDetailedEdgeDragging() && getMoveOnly());
856 if(!bDetail && !getSdrDragView().IsRubberEdgeDragging())
858 return false;
861 // one more migrated from SdrEdgeObj::NspToggleEdgeXor
862 if(IS_TYPE(SdrDragObjOwn, this) || IS_TYPE(SdrDragMovHdl, this))
864 return false;
867 return true;
870 drawinglayer::primitive2d::Primitive2DSequence SdrDragMethod::AddConnectorOverlays()
872 drawinglayer::primitive2d::Primitive2DSequence aRetval;
873 const bool bDetail(getSdrDragView().IsDetailedEdgeDragging() && getMoveOnly());
874 const SdrMarkList& rMarkedNodes = getSdrDragView().GetEdgesOfMarkedNodes();
876 for(sal_uInt16 a(0); a < rMarkedNodes.GetMarkCount(); a++)
878 SdrMark* pEM = rMarkedNodes.GetMark(a);
880 if(pEM && pEM->GetMarkedSdrObj())
882 SdrEdgeObj* pEdge = dynamic_cast< SdrEdgeObj* >(pEM->GetMarkedSdrObj());
884 if(pEdge)
886 const basegfx::B2DPolygon aEdgePolygon(pEdge->ImplAddConnectorOverlay(*this, pEM->IsCon1(), pEM->IsCon2(), bDetail));
888 if(aEdgePolygon.count())
890 // this polygon is a temporary calculated connector path, so it is not possible to fetch
891 // the needed primitives directly from the pEdge object which does not get changed. If full
892 // drag is on, use the SdrObjects ItemSet to create a adequate representation
893 bool bUseSolidDragging(getSolidDraggingActive());
895 if(bUseSolidDragging)
897 // switch off solid dragging if connector is not visible
898 if(!pEdge->HasLineStyle())
900 bUseSolidDragging = false;
904 if(bUseSolidDragging)
906 const SfxItemSet& rItemSet = pEdge->GetMergedItemSet();
907 const drawinglayer::attribute::SdrLineAttribute aLine(
908 drawinglayer::primitive2d::createNewSdrLineAttribute(rItemSet));
910 if(!aLine.isDefault())
912 const drawinglayer::attribute::SdrLineStartEndAttribute aLineStartEnd(
913 drawinglayer::primitive2d::createNewSdrLineStartEndAttribute(
914 rItemSet,
915 aLine.getWidth()));
917 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(
918 aRetval, drawinglayer::primitive2d::createPolygonLinePrimitive(
919 aEdgePolygon,
920 basegfx::B2DHomMatrix(),
921 aLine,
922 aLineStartEnd));
925 else
927 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
928 basegfx::BColor aColA(aSvtOptionsDrawinglayer.GetStripeColorA().getBColor());
929 basegfx::BColor aColB(aSvtOptionsDrawinglayer.GetStripeColorB().getBColor());
930 const double fStripeLength(aSvtOptionsDrawinglayer.GetStripeLength());
932 if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
934 aColA = aColB = Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
935 aColB.invert();
938 drawinglayer::primitive2d::Primitive2DReference aPolyPolygonMarkerPrimitive2D(
939 new drawinglayer::primitive2d::PolyPolygonMarkerPrimitive2D(
940 basegfx::B2DPolyPolygon(aEdgePolygon), aColA, aColB, fStripeLength));
941 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aPolyPolygonMarkerPrimitive2D);
948 return aRetval;
951 ////////////////////////////////////////////////////////////////////////////////////////////////////
953 TYPEINIT1(SdrDragMovHdl,SdrDragMethod);
955 SdrDragMovHdl::SdrDragMovHdl(SdrDragView& rNewView)
956 : SdrDragMethod(rNewView)
960 void SdrDragMovHdl::createSdrDragEntries()
962 // SdrDragMovHdl does not use the default drags,
963 // but creates nothing
966 void SdrDragMovHdl::TakeSdrDragComment(XubString& rStr) const
968 rStr=ImpGetResStr(STR_DragMethMovHdl);
969 if (getSdrDragView().IsDragWithCopy()) rStr+=ImpGetResStr(STR_EditWithCopy);
972 bool SdrDragMovHdl::BeginSdrDrag()
974 if( !GetDragHdl() )
975 return false;
977 DragStat().Ref1()=GetDragHdl()->GetPos();
978 DragStat().SetShown(!DragStat().IsShown());
979 SdrHdlKind eKind=GetDragHdl()->GetKind();
980 SdrHdl* pH1=GetHdlList().GetHdl(HDL_REF1);
981 SdrHdl* pH2=GetHdlList().GetHdl(HDL_REF2);
983 if (eKind==HDL_MIRX)
985 if (pH1==NULL || pH2==NULL)
987 OSL_FAIL("SdrDragMovHdl::BeginSdrDrag(): Moving the axis of reflection: reference handles not found.");
988 return false;
991 DragStat().SetActionRect(Rectangle(pH1->GetPos(),pH2->GetPos()));
993 else
995 Point aPt(GetDragHdl()->GetPos());
996 DragStat().SetActionRect(Rectangle(aPt,aPt));
999 return true;
1002 void SdrDragMovHdl::MoveSdrDrag(const Point& rNoSnapPnt)
1004 Point aPnt(rNoSnapPnt);
1006 if ( GetDragHdl() && DragStat().CheckMinMoved(rNoSnapPnt))
1008 if (GetDragHdl()->GetKind()==HDL_MIRX)
1010 SdrHdl* pH1=GetHdlList().GetHdl(HDL_REF1);
1011 SdrHdl* pH2=GetHdlList().GetHdl(HDL_REF2);
1013 if (pH1==NULL || pH2==NULL)
1014 return;
1016 if (!DragStat().IsNoSnap())
1018 long nBestXSnap=0;
1019 long nBestYSnap=0;
1020 bool bXSnapped=false;
1021 bool bYSnapped=false;
1022 Point aDif(aPnt-DragStat().GetStart());
1023 getSdrDragView().CheckSnap(Ref1()+aDif,NULL,nBestXSnap,nBestYSnap,bXSnapped,bYSnapped);
1024 getSdrDragView().CheckSnap(Ref2()+aDif,NULL,nBestXSnap,nBestYSnap,bXSnapped,bYSnapped);
1025 aPnt.X()+=nBestXSnap;
1026 aPnt.Y()+=nBestYSnap;
1029 if (aPnt!=DragStat().GetNow())
1031 Hide();
1032 DragStat().NextMove(aPnt);
1033 Point aDif(DragStat().GetNow()-DragStat().GetStart());
1034 pH1->SetPos(Ref1()+aDif);
1035 pH2->SetPos(Ref2()+aDif);
1037 SdrHdl* pHM = GetHdlList().GetHdl(HDL_MIRX);
1039 if(pHM)
1040 pHM->Touch();
1042 Show();
1043 DragStat().SetActionRect(Rectangle(pH1->GetPos(),pH2->GetPos()));
1046 else
1048 if (!DragStat().IsNoSnap()) SnapPos(aPnt);
1049 long nSA=0;
1051 if (getSdrDragView().IsAngleSnapEnabled())
1052 nSA=getSdrDragView().GetSnapAngle();
1054 if (getSdrDragView().IsMirrorAllowed(true,true))
1055 { // limited
1056 if (!getSdrDragView().IsMirrorAllowed(false,false)) nSA=4500;
1057 if (!getSdrDragView().IsMirrorAllowed(true,false)) nSA=9000;
1060 if (getSdrDragView().IsOrtho() && nSA!=9000)
1061 nSA=4500;
1063 if (nSA!=0)
1064 { // angle snapping
1065 SdrHdlKind eRef=HDL_REF1;
1067 if (GetDragHdl()->GetKind()==HDL_REF1)
1068 eRef=HDL_REF2;
1070 SdrHdl* pH=GetHdlList().GetHdl(eRef);
1072 if (pH!=NULL)
1074 Point aRef(pH->GetPos());
1075 long nWink=NormAngle360(GetAngle(aPnt-aRef));
1076 long nNeuWink=nWink;
1077 nNeuWink+=nSA/2;
1078 nNeuWink/=nSA;
1079 nNeuWink*=nSA;
1080 nNeuWink=NormAngle360(nNeuWink);
1081 double a=(nNeuWink-nWink)*nPi180;
1082 double nSin=sin(a);
1083 double nCos=cos(a);
1084 RotatePoint(aPnt,aRef,nSin,nCos);
1086 // eliminate rounding errors for certain values
1087 if (nSA==9000)
1089 if (nNeuWink==0 || nNeuWink==18000) aPnt.Y()=aRef.Y();
1090 if (nNeuWink==9000 || nNeuWink==27000) aPnt.X()=aRef.X();
1093 if (nSA==4500)
1094 OrthoDistance8(aRef,aPnt,true);
1098 if (aPnt!=DragStat().GetNow())
1100 Hide();
1101 DragStat().NextMove(aPnt);
1102 GetDragHdl()->SetPos(DragStat().GetNow());
1103 SdrHdl* pHM = GetHdlList().GetHdl(HDL_MIRX);
1105 if(pHM)
1106 pHM->Touch();
1108 Show();
1109 DragStat().SetActionRect(Rectangle(aPnt,aPnt));
1115 bool SdrDragMovHdl::EndSdrDrag(bool /*bCopy*/)
1117 if( GetDragHdl() )
1119 switch (GetDragHdl()->GetKind())
1121 case HDL_REF1:
1122 Ref1()=DragStat().GetNow();
1123 break;
1125 case HDL_REF2:
1126 Ref2()=DragStat().GetNow();
1127 break;
1129 case HDL_MIRX:
1130 Ref1()+=DragStat().GetNow()-DragStat().GetStart();
1131 Ref2()+=DragStat().GetNow()-DragStat().GetStart();
1132 break;
1134 default: break;
1138 return true;
1141 void SdrDragMovHdl::CancelSdrDrag()
1143 Hide();
1145 SdrHdl* pHdl = GetDragHdl();
1146 if( pHdl )
1147 pHdl->SetPos(DragStat().GetRef1());
1149 SdrHdl* pHM = GetHdlList().GetHdl(HDL_MIRX);
1151 if(pHM)
1152 pHM->Touch();
1155 Pointer SdrDragMovHdl::GetSdrDragPointer() const
1157 const SdrHdl* pHdl = GetDragHdl();
1159 if (pHdl!=NULL)
1161 return pHdl->GetPointer();
1164 return Pointer(POINTER_REFHAND);
1167 ////////////////////////////////////////////////////////////////////////////////////////////////////
1169 TYPEINIT1(SdrDragObjOwn,SdrDragMethod);
1171 SdrDragObjOwn::SdrDragObjOwn(SdrDragView& rNewView)
1172 : SdrDragMethod(rNewView),
1173 mpClone(0)
1175 const SdrObject* pObj = GetDragObj();
1177 if(pObj)
1179 // suppress full drag for some object types
1180 setSolidDraggingActive(pObj->supportsFullDrag());
1184 SdrDragObjOwn::~SdrDragObjOwn()
1186 if(mpClone)
1188 SdrObject::Free(mpClone);
1192 void SdrDragObjOwn::createSdrDragEntries()
1194 if(mpClone)
1196 basegfx::B2DPolyPolygon aDragPolyPolygon;
1197 bool bAddWireframe(true);
1199 if(getSolidDraggingActive())
1201 SdrPageView* pPV = getSdrDragView().GetSdrPageView();
1203 if(pPV && pPV->PageWindowCount())
1205 sdr::contact::ObjectContact& rOC = pPV->GetPageWindow(0)->GetObjectContact();
1206 addSdrDragEntry(new SdrDragEntrySdrObject(*mpClone, rOC, false));
1208 // potentially no wireframe needed, full drag works
1209 bAddWireframe = false;
1213 if(!bAddWireframe)
1215 // check for extra conditions for wireframe, e.g. no border at
1216 // objects
1217 if(!mpClone->HasLineStyle())
1219 bAddWireframe = true;
1223 if(bAddWireframe)
1225 // use wireframe poly when full drag is off or did not work
1226 aDragPolyPolygon = mpClone->TakeXorPoly();
1229 // add evtl. extra DragPolyPolygon
1230 const basegfx::B2DPolyPolygon aSpecialDragPolyPolygon(mpClone->getSpecialDragPoly(DragStat()));
1232 if(aSpecialDragPolyPolygon.count())
1234 aDragPolyPolygon.append(aSpecialDragPolyPolygon);
1237 if(aDragPolyPolygon.count())
1239 addSdrDragEntry(new SdrDragEntryPolyPolygon(aDragPolyPolygon));
1244 void SdrDragObjOwn::TakeSdrDragComment(XubString& rStr) const
1246 // #i103058# get info string from the clone preferred, the original will
1247 // not be changed. For security, use original as fallback
1248 if(mpClone)
1250 rStr = mpClone->getSpecialDragComment(DragStat());
1252 else
1254 const SdrObject* pObj = GetDragObj();
1256 if(pObj)
1258 rStr = pObj->getSpecialDragComment(DragStat());
1263 bool SdrDragObjOwn::BeginSdrDrag()
1265 if(!mpClone)
1267 const SdrObject* pObj = GetDragObj();
1269 if(pObj && !pObj->IsResizeProtect())
1271 if(pObj->beginSpecialDrag(DragStat()))
1273 // create initial clone to have a start visualization
1274 mpClone = pObj->getFullDragClone();
1275 mpClone->applySpecialDrag(DragStat());
1277 return true;
1282 return false;
1285 void SdrDragObjOwn::MoveSdrDrag(const Point& rNoSnapPnt)
1287 const SdrObject* pObj = GetDragObj();
1289 if(pObj)
1291 Point aPnt(rNoSnapPnt);
1292 SdrPageView* pPV = GetDragPV();
1294 if(pPV)
1296 if(!DragStat().IsNoSnap())
1298 SnapPos(aPnt);
1301 if(getSdrDragView().IsOrtho())
1303 if (DragStat().IsOrtho8Possible())
1305 OrthoDistance8(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho());
1307 else if (DragStat().IsOrtho4Possible())
1309 OrthoDistance4(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho());
1313 if(DragStat().CheckMinMoved(rNoSnapPnt))
1315 if(aPnt != DragStat().GetNow())
1317 Hide();
1318 DragStat().NextMove(aPnt);
1320 // since SdrDragObjOwn currently supports no transformation of
1321 // existing SdrDragEntries but only their recreation, a recreation
1322 // after every move is needed in this mode. Delete existing
1323 // SdrDragEntries here to force their recreation in the following Show().
1324 clearSdrDragEntries();
1326 // delete current clone (after the last reference to it is deleted above)
1327 if(mpClone)
1329 SdrObject::Free(mpClone);
1330 mpClone = 0;
1333 // create a new clone and modify to current drag state
1334 if(!mpClone)
1336 mpClone = pObj->getFullDragClone();
1337 mpClone->applySpecialDrag(DragStat());
1339 // #120999# AutoGrowWidth may change for SdrTextObj due to the automatism used
1340 // with bDisableAutoWidthOnDragging, so not only geometry changes but
1341 // also this (pretty indirect) property change is possible. If it gets
1342 // changed, it needs to be copied to the original since nothing will
1343 // happen when it only changes in the drag clone
1344 const bool bOldAutoGrowWidth(((SdrTextAutoGrowWidthItem&)pObj->GetMergedItem(SDRATTR_TEXT_AUTOGROWWIDTH)).GetValue());
1345 const bool bNewAutoGrowWidth(((SdrTextAutoGrowWidthItem&)mpClone->GetMergedItem(SDRATTR_TEXT_AUTOGROWWIDTH)).GetValue());
1347 if(bOldAutoGrowWidth != bNewAutoGrowWidth)
1349 GetDragObj()->SetMergedItem(SdrTextAutoGrowWidthItem(bNewAutoGrowWidth));
1353 Show();
1360 bool SdrDragObjOwn::EndSdrDrag(bool /*bCopy*/)
1362 Hide();
1363 std::vector< SdrUndoAction* > vConnectorUndoActions;
1364 bool bRet = false;
1365 SdrObject* pObj = GetDragObj();
1367 if(pObj)
1369 SdrUndoAction* pUndo = NULL;
1370 SdrUndoAction* pUndo2 = NULL;
1371 const bool bUndo = getSdrDragView().IsUndoEnabled();
1373 if( bUndo )
1375 if(!getSdrDragView().IsInsObjPoint() && pObj->IsInserted() )
1377 if (DragStat().IsEndDragChangesAttributes())
1379 pUndo=getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj);
1381 if (DragStat().IsEndDragChangesGeoAndAttributes())
1383 vConnectorUndoActions = getSdrDragView().CreateConnectorUndo( *pObj );
1384 pUndo2 = getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj);
1387 else
1389 vConnectorUndoActions = getSdrDragView().CreateConnectorUndo( *pObj );
1390 pUndo= getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj);
1394 if( pUndo )
1396 getSdrDragView().BegUndo( pUndo->GetComment() );
1398 else
1400 getSdrDragView().BegUndo();
1404 // Maybe use operator = for setting changed object data (do not change selection in
1405 // view, this will destroy the interactor). This is possible since a clone is now
1406 // directly modified by the modifiers. Only SdrTableObj is adding own UNDOs
1407 // in its SdrTableObj::endSpecialDrag, so currently not possible. OTOH it uses
1408 // a CreateUndoGeoObject(), so maybe setting SetEndDragChangesAttributes is okay. I
1409 // will test this now
1410 Rectangle aBoundRect0;
1412 if(pObj->GetUserCall())
1414 aBoundRect0 = pObj->GetLastBoundRect();
1417 bRet = pObj->applySpecialDrag(DragStat());
1419 if(bRet)
1421 pObj->SetChanged();
1422 pObj->BroadcastObjectChange();
1423 pObj->SendUserCall( SDRUSERCALL_RESIZE, aBoundRect0 );
1426 if(bRet)
1428 if( bUndo )
1430 getSdrDragView().AddUndoActions( vConnectorUndoActions );
1432 if ( pUndo )
1434 getSdrDragView().AddUndo(pUndo);
1437 if ( pUndo2 )
1439 getSdrDragView().AddUndo(pUndo2);
1443 else
1445 if( bUndo )
1447 std::vector< SdrUndoAction* >::iterator vConnectorUndoIter( vConnectorUndoActions.begin() );
1449 while( vConnectorUndoIter != vConnectorUndoActions.end() )
1451 delete *vConnectorUndoIter++;
1454 delete pUndo;
1455 delete pUndo2;
1459 if( bUndo )
1460 getSdrDragView().EndUndo();
1463 return bRet;
1466 Pointer SdrDragObjOwn::GetSdrDragPointer() const
1468 const SdrHdl* pHdl=GetDragHdl();
1470 if (pHdl)
1472 return pHdl->GetPointer();
1475 return Pointer(POINTER_MOVE);
1478 ////////////////////////////////////////////////////////////////////////////////////////////////////
1480 TYPEINIT1(SdrDragMove,SdrDragMethod);
1482 void SdrDragMove::createSdrDragEntryForSdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact, bool /*bModify*/)
1484 // for SdrDragMove, use current Primitive2DSequence of SdrObject visualization
1485 // in given ObjectContact directly
1486 sdr::contact::ViewContact& rVC = rOriginal.GetViewContact();
1487 sdr::contact::ViewObjectContact& rVOC = rVC.GetViewObjectContact(rObjectContact);
1488 sdr::contact::DisplayInfo aDisplayInfo;
1490 // Do not use the last ViewPort set at the OC from the last ProcessDisplay(),
1491 // here we want the complete primitive sequence without visible clippings
1492 rObjectContact.resetViewPort();
1494 addSdrDragEntry(new SdrDragEntryPrimitive2DSequence(rVOC.getPrimitive2DSequenceHierarchy(aDisplayInfo), true));
1497 void SdrDragMove::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
1499 rTarget.Move(Size(DragStat().GetDX(), DragStat().GetDY()));
1502 SdrDragMove::SdrDragMove(SdrDragView& rNewView)
1503 : SdrDragMethod(rNewView)
1505 setMoveOnly(true);
1508 void SdrDragMove::TakeSdrDragComment(XubString& rStr) const
1510 OUString aStr;
1512 ImpTakeDescriptionStr(STR_DragMethMove, rStr);
1513 rStr.AppendAscii(" (x=");
1514 getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDX(), aStr);
1515 rStr.Append(aStr);
1516 rStr.AppendAscii(" y=");
1517 getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDY(), aStr);
1518 rStr.Append(aStr);
1519 rStr += sal_Unicode(')');
1521 if(getSdrDragView().IsDragWithCopy())
1523 if(!getSdrDragView().IsInsObjPoint() && !getSdrDragView().IsInsGluePoint())
1525 rStr += ImpGetResStr(STR_EditWithCopy);
1530 bool SdrDragMove::BeginSdrDrag()
1532 DragStat().SetActionRect(GetMarkedRect());
1533 Show();
1535 return true;
1538 basegfx::B2DHomMatrix SdrDragMove::getCurrentTransformation()
1540 return basegfx::tools::createTranslateB2DHomMatrix(DragStat().GetDX(), DragStat().GetDY());
1543 void SdrDragMove::ImpCheckSnap(const Point& rPt)
1545 Point aPt(rPt);
1546 sal_uInt16 nRet=SnapPos(aPt);
1547 aPt-=rPt;
1549 if ((nRet & SDRSNAP_XSNAPPED) !=0)
1551 if (bXSnapped)
1553 if (std::abs(aPt.X())<std::abs(nBestXSnap))
1555 nBestXSnap=aPt.X();
1558 else
1560 nBestXSnap=aPt.X();
1561 bXSnapped=true;
1565 if ((nRet & SDRSNAP_YSNAPPED) !=0)
1567 if (bYSnapped)
1569 if (std::abs(aPt.Y())<std::abs(nBestYSnap))
1571 nBestYSnap=aPt.Y();
1574 else
1576 nBestYSnap=aPt.Y();
1577 bYSnapped=true;
1582 void SdrDragMove::MoveSdrDrag(const Point& rNoSnapPnt_)
1584 nBestXSnap=0;
1585 nBestYSnap=0;
1586 bXSnapped=false;
1587 bYSnapped=false;
1588 Point aNoSnapPnt(rNoSnapPnt_);
1589 const Rectangle& aSR=GetMarkedRect();
1590 long nMovedx=aNoSnapPnt.X()-DragStat().GetStart().X();
1591 long nMovedy=aNoSnapPnt.Y()-DragStat().GetStart().Y();
1592 Point aLO(aSR.TopLeft()); aLO.X()+=nMovedx; aLO.Y()+=nMovedy;
1593 Point aRU(aSR.BottomRight()); aRU.X()+=nMovedx; aRU.Y()+=nMovedy;
1594 Point aLU(aLO.X(),aRU.Y());
1595 Point aRO(aRU.X(),aLO.Y());
1596 ImpCheckSnap(aLO);
1598 if (!getSdrDragView().IsMoveSnapOnlyTopLeft())
1600 ImpCheckSnap(aRO);
1601 ImpCheckSnap(aLU);
1602 ImpCheckSnap(aRU);
1605 Point aPnt(aNoSnapPnt.X()+nBestXSnap,aNoSnapPnt.Y()+nBestYSnap);
1606 bool bOrtho=getSdrDragView().IsOrtho();
1608 if (bOrtho)
1609 OrthoDistance8(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho());
1611 if (DragStat().CheckMinMoved(aNoSnapPnt))
1613 Point aPt1(aPnt);
1614 Rectangle aLR(getSdrDragView().GetWorkArea());
1615 bool bWorkArea=!aLR.IsEmpty();
1616 bool bDragLimit=IsDragLimit();
1618 if (bDragLimit || bWorkArea)
1620 Rectangle aSR2(GetMarkedRect());
1621 Point aD(aPt1-DragStat().GetStart());
1623 if (bDragLimit)
1625 Rectangle aR2(GetDragLimitRect());
1627 if (bWorkArea)
1628 aLR.Intersection(aR2);
1629 else
1630 aLR=aR2;
1633 if (aSR2.Left()>aLR.Left() || aSR2.Right()<aLR.Right())
1634 { // any space to move to?
1635 aSR2.Move(aD.X(),0);
1637 if (aSR2.Left()<aLR.Left())
1639 aPt1.X()-=aSR2.Left()-aLR.Left();
1641 else if (aSR2.Right()>aLR.Right())
1643 aPt1.X()-=aSR2.Right()-aLR.Right();
1646 else
1647 aPt1.X()=DragStat().GetStart().X(); // no space to move to
1649 if (aSR2.Top()>aLR.Top() || aSR2.Bottom()<aLR.Bottom())
1650 { // any space to move to?
1651 aSR2.Move(0,aD.Y());
1653 if (aSR2.Top()<aLR.Top())
1655 aPt1.Y()-=aSR2.Top()-aLR.Top();
1657 else if (aSR2.Bottom()>aLR.Bottom())
1659 aPt1.Y()-=aSR2.Bottom()-aLR.Bottom();
1662 else
1663 aPt1.Y()=DragStat().GetStart().Y(); // no space to move to
1666 if (getSdrDragView().IsDraggingGluePoints())
1667 { // restrict glue points to the BoundRect of the Obj
1668 aPt1-=DragStat().GetStart();
1669 const SdrMarkList& rML=GetMarkedObjectList();
1670 sal_uLong nMarkAnz=rML.GetMarkCount();
1672 for (sal_uLong nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++)
1674 const SdrMark* pM=rML.GetMark(nMarkNum);
1675 const SdrUShortCont* pPts=pM->GetMarkedGluePoints();
1676 sal_uLong nPtAnz=pPts==NULL ? 0 : pPts->size();
1678 if (nPtAnz!=0)
1680 const SdrObject* pObj=pM->GetMarkedSdrObj();
1681 const SdrGluePointList* pGPL=pObj->GetGluePointList();
1682 Rectangle aBound(pObj->GetCurrentBoundRect());
1684 for (SdrUShortCont::const_iterator it = pPts->begin(); it != pPts->end(); ++it)
1686 sal_uInt16 nId = *it;
1687 sal_uInt16 nGlueNum=pGPL->FindGluePoint(nId);
1689 if (nGlueNum!=SDRGLUEPOINT_NOTFOUND)
1691 Point aPt((*pGPL)[nGlueNum].GetAbsolutePos(*pObj));
1692 aPt+=aPt1; // move by this much
1693 if (aPt.X()<aBound.Left() ) aPt1.X()-=aPt.X()-aBound.Left() ;
1694 if (aPt.X()>aBound.Right() ) aPt1.X()-=aPt.X()-aBound.Right() ;
1695 if (aPt.Y()<aBound.Top() ) aPt1.Y()-=aPt.Y()-aBound.Top() ;
1696 if (aPt.Y()>aBound.Bottom()) aPt1.Y()-=aPt.Y()-aBound.Bottom();
1702 aPt1+=DragStat().GetStart();
1705 if (bOrtho)
1706 OrthoDistance8(DragStat().GetStart(),aPt1,false);
1708 if (aPt1!=DragStat().GetNow())
1710 Hide();
1711 DragStat().NextMove(aPt1);
1712 Rectangle aAction(GetMarkedRect());
1713 aAction.Move(DragStat().GetDX(),DragStat().GetDY());
1714 DragStat().SetActionRect(aAction);
1715 Show();
1720 bool SdrDragMove::EndSdrDrag(bool bCopy)
1722 Hide();
1724 if (getSdrDragView().IsInsObjPoint() || getSdrDragView().IsInsGluePoint())
1725 bCopy=false;
1727 if (IsDraggingPoints())
1729 getSdrDragView().MoveMarkedPoints(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy);
1731 else if (IsDraggingGluePoints())
1733 getSdrDragView().MoveMarkedGluePoints(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy);
1735 else
1737 getSdrDragView().MoveMarkedObj(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy);
1740 return true;
1743 Pointer SdrDragMove::GetSdrDragPointer() const
1745 if (IsDraggingPoints() || IsDraggingGluePoints())
1747 return Pointer(POINTER_MOVEPOINT);
1749 else
1751 return Pointer(POINTER_MOVE);
1755 ////////////////////////////////////////////////////////////////////////////////////////////////////
1757 TYPEINIT1(SdrDragResize,SdrDragMethod);
1759 SdrDragResize::SdrDragResize(SdrDragView& rNewView)
1760 : SdrDragMethod(rNewView),
1761 aXFact(1,1),
1762 aYFact(1,1)
1766 void SdrDragResize::TakeSdrDragComment(XubString& rStr) const
1768 ImpTakeDescriptionStr(STR_DragMethResize, rStr);
1769 bool bEqual(aXFact == aYFact);
1770 Fraction aFact1(1,1);
1771 Point aStart(DragStat().GetStart());
1772 Point aRef(DragStat().GetRef1());
1773 sal_Int32 nXDiv(aStart.X() - aRef.X());
1775 if(!nXDiv)
1776 nXDiv = 1;
1778 sal_Int32 nYDiv(aStart.Y() - aRef.Y());
1780 if(!nYDiv)
1781 nYDiv = 1;
1783 bool bX(aXFact != aFact1 && std::abs(nXDiv) > 1);
1784 bool bY(aYFact != aFact1 && std::abs(nYDiv) > 1);
1786 if(bX || bY)
1788 XubString aStr;
1790 rStr.AppendAscii(" (");
1792 if(bX)
1794 if(!bEqual)
1795 rStr.AppendAscii("x=");
1797 getSdrDragView().GetModel()->TakePercentStr(aXFact, aStr);
1798 rStr += aStr;
1801 if(bY && !bEqual)
1803 if(bX)
1804 rStr += sal_Unicode(' ');
1806 rStr.AppendAscii("y=");
1807 getSdrDragView().GetModel()->TakePercentStr(aYFact, aStr);
1808 rStr += aStr;
1811 rStr += sal_Unicode(')');
1814 if(getSdrDragView().IsDragWithCopy())
1815 rStr += ImpGetResStr(STR_EditWithCopy);
1818 bool SdrDragResize::BeginSdrDrag()
1820 SdrHdlKind eRefHdl=HDL_MOVE;
1821 SdrHdl* pRefHdl=NULL;
1823 switch (GetDragHdlKind())
1825 case HDL_UPLFT: eRefHdl=HDL_LWRGT; break;
1826 case HDL_UPPER: eRefHdl=HDL_LOWER; DragStat().SetHorFixed(true); break;
1827 case HDL_UPRGT: eRefHdl=HDL_LWLFT; break;
1828 case HDL_LEFT : eRefHdl=HDL_RIGHT; DragStat().SetVerFixed(true); break;
1829 case HDL_RIGHT: eRefHdl=HDL_LEFT ; DragStat().SetVerFixed(true); break;
1830 case HDL_LWLFT: eRefHdl=HDL_UPRGT; break;
1831 case HDL_LOWER: eRefHdl=HDL_UPPER; DragStat().SetHorFixed(true); break;
1832 case HDL_LWRGT: eRefHdl=HDL_UPLFT; break;
1833 default: break;
1836 if (eRefHdl!=HDL_MOVE)
1837 pRefHdl=GetHdlList().GetHdl(eRefHdl);
1839 if (pRefHdl!=NULL && !getSdrDragView().IsResizeAtCenter())
1841 // Calc hack to adjust for calc grid
1842 DragStat().Ref1()=pRefHdl->GetPos() - getSdrDragView().GetGridOffset();
1844 else
1846 SdrHdl* pRef1=GetHdlList().GetHdl(HDL_UPLFT);
1847 SdrHdl* pRef2=GetHdlList().GetHdl(HDL_LWRGT);
1849 if (pRef1!=NULL && pRef2!=NULL)
1851 DragStat().Ref1()=Rectangle(pRef1->GetPos(),pRef2->GetPos()).Center();
1853 else
1855 DragStat().Ref1()=GetMarkedRect().Center();
1859 Show();
1861 return true;
1864 basegfx::B2DHomMatrix SdrDragResize::getCurrentTransformation()
1866 basegfx::B2DHomMatrix aRetval(basegfx::tools::createTranslateB2DHomMatrix(
1867 -DragStat().Ref1().X(), -DragStat().Ref1().Y()));
1868 aRetval.scale(aXFact, aYFact);
1869 aRetval.translate(DragStat().Ref1().X(), DragStat().Ref1().Y());
1871 return aRetval;
1874 void SdrDragResize::MoveSdrDrag(const Point& rNoSnapPnt)
1876 Point aPnt(GetSnapPos(rNoSnapPnt));
1877 Point aStart(DragStat().GetStart());
1878 Point aRef(DragStat().GetRef1());
1879 Fraction aMaxFact(0x7FFFFFFF,1);
1880 Rectangle aLR(getSdrDragView().GetWorkArea());
1881 bool bWorkArea=!aLR.IsEmpty();
1882 bool bDragLimit=IsDragLimit();
1884 if (bDragLimit || bWorkArea)
1886 Rectangle aSR(GetMarkedRect());
1888 if (bDragLimit)
1890 Rectangle aR2(GetDragLimitRect());
1892 if (bWorkArea)
1893 aLR.Intersection(aR2);
1894 else
1895 aLR=aR2;
1898 if (aPnt.X()<aLR.Left())
1899 aPnt.X()=aLR.Left();
1900 else if (aPnt.X()>aLR.Right())
1901 aPnt.X()=aLR.Right();
1903 if (aPnt.Y()<aLR.Top())
1904 aPnt.Y()=aLR.Top();
1905 else if (aPnt.Y()>aLR.Bottom())
1906 aPnt.Y()=aLR.Bottom();
1908 if (aRef.X()>aSR.Left())
1910 Fraction aMax(aRef.X()-aLR.Left(),aRef.X()-aSR.Left());
1912 if (aMax<aMaxFact)
1913 aMaxFact=aMax;
1916 if (aRef.X()<aSR.Right())
1918 Fraction aMax(aLR.Right()-aRef.X(),aSR.Right()-aRef.X());
1920 if (aMax<aMaxFact)
1921 aMaxFact=aMax;
1924 if (aRef.Y()>aSR.Top())
1926 Fraction aMax(aRef.Y()-aLR.Top(),aRef.Y()-aSR.Top());
1928 if (aMax<aMaxFact)
1929 aMaxFact=aMax;
1932 if (aRef.Y()<aSR.Bottom())
1934 Fraction aMax(aLR.Bottom()-aRef.Y(),aSR.Bottom()-aRef.Y());
1936 if (aMax<aMaxFact)
1937 aMaxFact=aMax;
1941 long nXDiv=aStart.X()-aRef.X(); if (nXDiv==0) nXDiv=1;
1942 long nYDiv=aStart.Y()-aRef.Y(); if (nYDiv==0) nYDiv=1;
1943 long nXMul=aPnt.X()-aRef.X();
1944 long nYMul=aPnt.Y()-aRef.Y();
1946 if (nXDiv<0)
1948 nXDiv=-nXDiv;
1949 nXMul=-nXMul;
1952 if (nYDiv<0)
1954 nYDiv=-nYDiv;
1955 nYMul=-nYMul;
1958 bool bXNeg=nXMul<0; if (bXNeg) nXMul=-nXMul;
1959 bool bYNeg=nYMul<0; if (bYNeg) nYMul=-nYMul;
1960 bool bOrtho=getSdrDragView().IsOrtho() || !getSdrDragView().IsResizeAllowed(false);
1962 if (!DragStat().IsHorFixed() && !DragStat().IsVerFixed())
1964 if (std::abs(nXDiv)<=1 || std::abs(nYDiv)<=1)
1965 bOrtho=false;
1967 if (bOrtho)
1969 if ((Fraction(nXMul,nXDiv)>Fraction(nYMul,nYDiv)) !=getSdrDragView().IsBigOrtho())
1971 nXMul=nYMul;
1972 nXDiv=nYDiv;
1974 else
1976 nYMul=nXMul;
1977 nYDiv=nXDiv;
1981 else
1983 if (bOrtho)
1985 if (DragStat().IsHorFixed())
1987 bXNeg=false;
1988 nXMul=nYMul;
1989 nXDiv=nYDiv;
1992 if (DragStat().IsVerFixed())
1994 bYNeg=false;
1995 nYMul=nXMul;
1996 nYDiv=nXDiv;
1999 else
2001 if (DragStat().IsHorFixed())
2003 bXNeg=false;
2004 nXMul=1;
2005 nXDiv=1;
2008 if (DragStat().IsVerFixed())
2010 bYNeg=false;
2011 nYMul=1;
2012 nYDiv=1;
2017 Fraction aNeuXFact(nXMul,nXDiv);
2018 Fraction aNeuYFact(nYMul,nYDiv);
2020 if (bOrtho)
2022 if (aNeuXFact>aMaxFact)
2024 aNeuXFact=aMaxFact;
2025 aNeuYFact=aMaxFact;
2028 if (aNeuYFact>aMaxFact)
2030 aNeuXFact=aMaxFact;
2031 aNeuYFact=aMaxFact;
2035 if (bXNeg)
2036 aNeuXFact=Fraction(-aNeuXFact.GetNumerator(),aNeuXFact.GetDenominator());
2038 if (bYNeg)
2039 aNeuYFact=Fraction(-aNeuYFact.GetNumerator(),aNeuYFact.GetDenominator());
2041 if (DragStat().CheckMinMoved(aPnt))
2043 if ((!DragStat().IsHorFixed() && aPnt.X()!=DragStat().GetNow().X()) ||
2044 (!DragStat().IsVerFixed() && aPnt.Y()!=DragStat().GetNow().Y()))
2046 Hide();
2047 DragStat().NextMove(aPnt);
2048 aXFact=aNeuXFact;
2049 aYFact=aNeuYFact;
2050 Show();
2055 void SdrDragResize::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
2057 rTarget.Resize(DragStat().Ref1(),aXFact,aYFact);
2060 bool SdrDragResize::EndSdrDrag(bool bCopy)
2062 Hide();
2064 if (IsDraggingPoints())
2066 getSdrDragView().ResizeMarkedPoints(DragStat().Ref1(),aXFact,aYFact,bCopy);
2068 else if (IsDraggingGluePoints())
2070 getSdrDragView().ResizeMarkedGluePoints(DragStat().Ref1(),aXFact,aYFact,bCopy);
2072 else
2074 getSdrDragView().ResizeMarkedObj(DragStat().Ref1(),aXFact,aYFact,bCopy);
2077 return true;
2080 Pointer SdrDragResize::GetSdrDragPointer() const
2082 const SdrHdl* pHdl=GetDragHdl();
2084 if (pHdl!=NULL)
2086 return pHdl->GetPointer();
2089 return Pointer(POINTER_MOVE);
2092 ////////////////////////////////////////////////////////////////////////////////////////////////////
2094 TYPEINIT1(SdrDragRotate,SdrDragMethod);
2096 void SdrDragRotate::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
2098 rTarget.Rotate(DragStat().GetRef1(), nWink, sin(nWink*nPi180), cos(nWink*nPi180));
2101 SdrDragRotate::SdrDragRotate(SdrDragView& rNewView)
2102 : SdrDragMethod(rNewView),
2103 nSin(0.0),
2104 nCos(1.0),
2105 nWink0(0),
2106 nWink(0),
2107 bRight(false)
2111 void SdrDragRotate::TakeSdrDragComment(XubString& rStr) const
2113 ImpTakeDescriptionStr(STR_DragMethRotate, rStr);
2114 rStr.AppendAscii(" (");
2115 sal_Int32 nTmpWink(NormAngle360(nWink));
2117 if(bRight && nWink)
2119 nTmpWink -= 36000;
2122 OUString aStr;
2123 getSdrDragView().GetModel()->TakeWinkStr(nTmpWink, aStr);
2124 rStr.Append(aStr);
2125 rStr += sal_Unicode(')');
2127 if(getSdrDragView().IsDragWithCopy())
2128 rStr += ImpGetResStr(STR_EditWithCopy);
2131 bool SdrDragRotate::BeginSdrDrag()
2133 SdrHdl* pH=GetHdlList().GetHdl(HDL_REF1);
2135 if (pH!=NULL)
2137 Show();
2138 DragStat().Ref1()=pH->GetPos();
2139 nWink0=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
2140 return true;
2142 else
2144 OSL_FAIL("SdrDragRotate::BeginSdrDrag(): No reference point handle found.");
2145 return false;
2149 basegfx::B2DHomMatrix SdrDragRotate::getCurrentTransformation()
2151 return basegfx::tools::createRotateAroundPoint(
2152 DragStat().GetRef1().X(), DragStat().GetRef1().Y(),
2153 -atan2(nSin, nCos));
2156 void SdrDragRotate::MoveSdrDrag(const Point& rPnt_)
2158 Point aPnt(rPnt_);
2159 if (DragStat().CheckMinMoved(aPnt))
2161 long nNeuWink=NormAngle360(GetAngle(aPnt-DragStat().GetRef1())-nWink0);
2162 long nSA=0;
2164 if (getSdrDragView().IsAngleSnapEnabled())
2165 nSA=getSdrDragView().GetSnapAngle();
2167 if (!getSdrDragView().IsRotateAllowed(false))
2168 nSA=9000;
2170 if (nSA!=0)
2171 { // angle snapping
2172 nNeuWink+=nSA/2;
2173 nNeuWink/=nSA;
2174 nNeuWink*=nSA;
2177 nNeuWink=NormAngle180(nNeuWink);
2179 if (nWink!=nNeuWink)
2181 sal_uInt16 nSekt0=GetAngleSector(nWink);
2182 sal_uInt16 nSekt1=GetAngleSector(nNeuWink);
2184 if (nSekt0==0 && nSekt1==3)
2185 bRight=true;
2187 if (nSekt0==3 && nSekt1==0)
2188 bRight=false;
2190 nWink=nNeuWink;
2191 double a=nWink*nPi180;
2192 double nSin1=sin(a); // calculate now, so as little time as possible
2193 double nCos1=cos(a); // passes between Hide() and Show()
2194 Hide();
2195 nSin=nSin1;
2196 nCos=nCos1;
2197 DragStat().NextMove(aPnt);
2198 Show();
2203 bool SdrDragRotate::EndSdrDrag(bool bCopy)
2205 Hide();
2207 if (nWink!=0)
2209 if (IsDraggingPoints())
2211 getSdrDragView().RotateMarkedPoints(DragStat().GetRef1(),nWink,bCopy);
2213 else if (IsDraggingGluePoints())
2215 getSdrDragView().RotateMarkedGluePoints(DragStat().GetRef1(),nWink,bCopy);
2217 else
2219 getSdrDragView().RotateMarkedObj(DragStat().GetRef1(),nWink,bCopy);
2222 return true;
2225 Pointer SdrDragRotate::GetSdrDragPointer() const
2227 return Pointer(POINTER_ROTATE);
2230 ////////////////////////////////////////////////////////////////////////////////////////////////////
2232 TYPEINIT1(SdrDragShear,SdrDragMethod);
2234 SdrDragShear::SdrDragShear(SdrDragView& rNewView, bool bSlant1)
2235 : SdrDragMethod(rNewView),
2236 aFact(1,1),
2237 nWink0(0),
2238 nWink(0),
2239 nTan(0.0),
2240 bVertical(false),
2241 bResize(false),
2242 bUpSideDown(false),
2243 bSlant(bSlant1)
2247 void SdrDragShear::TakeSdrDragComment(XubString& rStr) const
2249 ImpTakeDescriptionStr(STR_DragMethShear, rStr);
2250 rStr.AppendAscii(" (");
2252 sal_Int32 nTmpWink(nWink);
2254 if(bUpSideDown)
2255 nTmpWink += 18000;
2257 nTmpWink = NormAngle180(nTmpWink);
2259 OUString aStr;
2260 getSdrDragView().GetModel()->TakeWinkStr(nTmpWink, aStr);
2261 rStr.Append(aStr);
2262 rStr += sal_Unicode(')');
2264 if(getSdrDragView().IsDragWithCopy())
2265 rStr += ImpGetResStr(STR_EditWithCopy);
2268 bool SdrDragShear::BeginSdrDrag()
2270 SdrHdlKind eRefHdl=HDL_MOVE;
2271 SdrHdl* pRefHdl=NULL;
2273 switch (GetDragHdlKind())
2275 case HDL_UPPER: eRefHdl=HDL_LOWER; break;
2276 case HDL_LOWER: eRefHdl=HDL_UPPER; break;
2277 case HDL_LEFT : eRefHdl=HDL_RIGHT; bVertical=true; break;
2278 case HDL_RIGHT: eRefHdl=HDL_LEFT ; bVertical=true; break;
2279 default: break;
2282 if (eRefHdl!=HDL_MOVE)
2283 pRefHdl=GetHdlList().GetHdl(eRefHdl);
2285 if (pRefHdl!=NULL)
2287 DragStat().Ref1()=pRefHdl->GetPos();
2288 nWink0=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
2290 else
2292 OSL_FAIL("SdrDragShear::BeginSdrDrag(): No reference point handle for shearing found.");
2293 return false;
2296 Show();
2297 return true;
2300 basegfx::B2DHomMatrix SdrDragShear::getCurrentTransformation()
2302 basegfx::B2DHomMatrix aRetval(basegfx::tools::createTranslateB2DHomMatrix(
2303 -DragStat().GetRef1().X(), -DragStat().GetRef1().Y()));
2305 if (bResize)
2307 if (bVertical)
2309 aRetval.scale(aFact, 1.0);
2310 aRetval.shearY(-nTan);
2312 else
2314 aRetval.scale(1.0, aFact);
2315 aRetval.shearX(-nTan);
2319 aRetval.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y());
2321 return aRetval;
2324 void SdrDragShear::MoveSdrDrag(const Point& rPnt)
2326 if (DragStat().CheckMinMoved(rPnt))
2328 bResize=!getSdrDragView().IsOrtho();
2329 long nSA=0;
2331 if (getSdrDragView().IsAngleSnapEnabled())
2332 nSA=getSdrDragView().GetSnapAngle();
2334 Point aP0(DragStat().GetStart());
2335 Point aPnt(rPnt);
2336 Fraction aNeuFact(1,1);
2338 // if angle snapping not activated, snap to raster (except when using slant)
2339 if (nSA==0 && !bSlant)
2340 aPnt=GetSnapPos(aPnt);
2342 if (!bSlant && !bResize)
2343 { // shear, but no resize
2344 if (bVertical)
2345 aPnt.X()=aP0.X();
2346 else
2347 aPnt.Y()=aP0.Y();
2350 Point aRef(DragStat().GetRef1());
2351 Point aDif(aPnt-aRef);
2353 long nNeuWink=0;
2355 if (bSlant)
2357 nNeuWink=NormAngle180(-(GetAngle(aDif)-nWink0));
2359 if (bVertical)
2360 nNeuWink=NormAngle180(-nNeuWink);
2362 else
2364 if (bVertical)
2365 nNeuWink=NormAngle180(GetAngle(aDif));
2366 else
2367 nNeuWink=NormAngle180(-(GetAngle(aDif)-9000));
2369 if (nNeuWink<-9000 || nNeuWink>9000)
2370 nNeuWink=NormAngle180(nNeuWink+18000);
2372 if (bResize)
2374 Point aPt2(aPnt);
2376 if (nSA!=0)
2377 aPt2=GetSnapPos(aPnt); // snap this one in any case
2379 if (bVertical)
2381 aNeuFact=Fraction(aPt2.X()-aRef.X(),aP0.X()-aRef.X());
2383 else
2385 aNeuFact=Fraction(aPt2.Y()-aRef.Y(),aP0.Y()-aRef.Y());
2390 bool bNeg=nNeuWink<0;
2392 if (bNeg)
2393 nNeuWink=-nNeuWink;
2395 if (nSA!=0)
2396 { // angle snapping
2397 nNeuWink+=nSA/2;
2398 nNeuWink/=nSA;
2399 nNeuWink*=nSA;
2402 nNeuWink=NormAngle360(nNeuWink);
2403 bUpSideDown=nNeuWink>9000 && nNeuWink<27000;
2405 if (bSlant)
2406 { // calculate resize for slant
2407 // when angle snapping is activated, disable 89 degree limit
2408 long nTmpWink=nNeuWink;
2409 if (bUpSideDown) nNeuWink-=18000;
2410 if (bNeg) nTmpWink=-nTmpWink;
2411 bResize=true;
2412 double nCos=cos(nTmpWink*nPi180);
2413 aNeuFact=nCos;
2414 Kuerzen(aFact,10); // three decimals should be enough
2417 if (nNeuWink>8900)
2418 nNeuWink=8900;
2420 if (bNeg)
2421 nNeuWink=-nNeuWink;
2423 if (nWink!=nNeuWink || aFact!=aNeuFact)
2425 nWink=nNeuWink;
2426 aFact=aNeuFact;
2427 double a=nWink*nPi180;
2428 double nTan1=tan(a); // calculate now, so as little time as possible passes between Hide() and Show()
2429 Hide();
2430 nTan=nTan1;
2431 DragStat().NextMove(rPnt);
2432 Show();
2437 void SdrDragShear::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
2439 if (bResize)
2441 if (bVertical)
2443 rTarget.Resize(DragStat().GetRef1(),aFact,Fraction(1,1));
2445 else
2447 rTarget.Resize(DragStat().GetRef1(),Fraction(1,1),aFact);
2451 if (nWink!=0)
2453 rTarget.Shear(DragStat().GetRef1(),nWink,tan(nWink*nPi180),bVertical);
2457 bool SdrDragShear::EndSdrDrag(bool bCopy)
2459 Hide();
2461 if (bResize && aFact==Fraction(1,1))
2462 bResize=false;
2464 if (nWink!=0 || bResize)
2466 if (nWink!=0 && bResize)
2468 XubString aStr;
2469 ImpTakeDescriptionStr(STR_EditShear,aStr);
2471 if (bCopy)
2472 aStr+=ImpGetResStr(STR_EditWithCopy);
2474 getSdrDragView().BegUndo(aStr);
2477 if (bResize)
2479 if (bVertical)
2481 getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),aFact,Fraction(1,1),bCopy);
2483 else
2485 getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),Fraction(1,1),aFact,bCopy);
2488 bCopy=false;
2491 if (nWink!=0)
2493 getSdrDragView().ShearMarkedObj(DragStat().GetRef1(),nWink,bVertical,bCopy);
2496 if (nWink!=0 && bResize)
2497 getSdrDragView().EndUndo();
2499 return true;
2502 return false;
2505 Pointer SdrDragShear::GetSdrDragPointer() const
2507 if (bVertical)
2508 return Pointer(POINTER_VSHEAR);
2509 else
2510 return Pointer(POINTER_HSHEAR);
2513 ////////////////////////////////////////////////////////////////////////////////////////////////////
2515 TYPEINIT1(SdrDragMirror,SdrDragMethod);
2517 void SdrDragMirror::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
2519 if(bMirrored)
2521 rTarget.Mirror(DragStat().GetRef1(), DragStat().GetRef2());
2525 SdrDragMirror::SdrDragMirror(SdrDragView& rNewView)
2526 : SdrDragMethod(rNewView),
2527 nWink(0),
2528 bMirrored(false),
2529 bSide0(false)
2533 bool SdrDragMirror::ImpCheckSide(const Point& rPnt) const
2535 long nWink1=GetAngle(rPnt-DragStat().GetRef1());
2536 nWink1-=nWink;
2537 nWink1=NormAngle360(nWink1);
2539 return nWink1<18000;
2542 void SdrDragMirror::TakeSdrDragComment(XubString& rStr) const
2544 if (aDif.X()==0)
2545 ImpTakeDescriptionStr(STR_DragMethMirrorHori,rStr);
2546 else if (aDif.Y()==0)
2547 ImpTakeDescriptionStr(STR_DragMethMirrorVert,rStr);
2548 else if (std::abs(aDif.X()) == std::abs(aDif.Y()))
2549 ImpTakeDescriptionStr(STR_DragMethMirrorDiag,rStr);
2550 else
2551 ImpTakeDescriptionStr(STR_DragMethMirrorFree,rStr);
2553 if (getSdrDragView().IsDragWithCopy())
2554 rStr+=ImpGetResStr(STR_EditWithCopy);
2557 bool SdrDragMirror::BeginSdrDrag()
2559 SdrHdl* pH1=GetHdlList().GetHdl(HDL_REF1);
2560 SdrHdl* pH2=GetHdlList().GetHdl(HDL_REF2);
2562 if (pH1!=NULL && pH2!=NULL)
2564 DragStat().Ref1()=pH1->GetPos();
2565 DragStat().Ref2()=pH2->GetPos();
2566 Ref1()=pH1->GetPos();
2567 Ref2()=pH2->GetPos();
2568 aDif=pH2->GetPos()-pH1->GetPos();
2569 bool b90=(aDif.X()==0) || aDif.Y()==0;
2570 bool b45=b90 || (std::abs(aDif.X()) == std::abs(aDif.Y()));
2571 nWink=NormAngle360(GetAngle(aDif));
2573 if (!getSdrDragView().IsMirrorAllowed(false,false) && !b45)
2574 return false; // free choice of axis angle not allowed
2576 if (!getSdrDragView().IsMirrorAllowed(true,false) && !b90)
2577 return false; // 45 degrees not allowed either
2579 bSide0=ImpCheckSide(DragStat().GetStart());
2580 Show();
2581 return true;
2583 else
2585 OSL_FAIL("SdrDragMirror::BeginSdrDrag(): Axis of reflection not found.");
2586 return false;
2590 basegfx::B2DHomMatrix SdrDragMirror::getCurrentTransformation()
2592 basegfx::B2DHomMatrix aRetval;
2594 if (bMirrored)
2596 const double fDeltaX(DragStat().GetRef2().X() - DragStat().GetRef1().X());
2597 const double fDeltaY(DragStat().GetRef2().Y() - DragStat().GetRef1().Y());
2598 const double fRotation(atan2(fDeltaY, fDeltaX));
2600 aRetval = basegfx::tools::createTranslateB2DHomMatrix(-DragStat().GetRef1().X(), -DragStat().GetRef1().Y());
2601 aRetval.rotate(-fRotation);
2602 aRetval.scale(1.0, -1.0);
2603 aRetval.rotate(fRotation);
2604 aRetval.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y());
2607 return aRetval;
2610 void SdrDragMirror::MoveSdrDrag(const Point& rPnt)
2612 if (DragStat().CheckMinMoved(rPnt))
2614 bool bNeuSide=ImpCheckSide(rPnt);
2615 bool bNeuMirr=bSide0!=bNeuSide;
2617 if (bMirrored!=bNeuMirr)
2619 Hide();
2620 bMirrored=bNeuMirr;
2621 DragStat().NextMove(rPnt);
2622 Show();
2627 bool SdrDragMirror::EndSdrDrag(bool bCopy)
2629 Hide();
2631 if (bMirrored)
2633 getSdrDragView().MirrorMarkedObj(DragStat().GetRef1(),DragStat().GetRef2(),bCopy);
2636 return true;
2639 Pointer SdrDragMirror::GetSdrDragPointer() const
2641 return Pointer(POINTER_MIRROR);
2644 ////////////////////////////////////////////////////////////////////////////////////////////////////
2646 TYPEINIT1(SdrDragGradient, SdrDragMethod);
2648 SdrDragGradient::SdrDragGradient(SdrDragView& rNewView, bool bGrad)
2649 : SdrDragMethod(rNewView),
2650 pIAOHandle(NULL),
2651 bIsGradient(bGrad)
2655 void SdrDragGradient::TakeSdrDragComment(XubString& rStr) const
2657 if(IsGradient())
2658 ImpTakeDescriptionStr(STR_DragMethGradient, rStr);
2659 else
2660 ImpTakeDescriptionStr(STR_DragMethTransparence, rStr);
2663 bool SdrDragGradient::BeginSdrDrag()
2665 bool bRetval(false);
2667 pIAOHandle = (SdrHdlGradient*)GetHdlList().GetHdl(IsGradient() ? HDL_GRAD : HDL_TRNS);
2669 if(pIAOHandle)
2671 // save old values
2672 DragStat().Ref1() = pIAOHandle->GetPos();
2673 DragStat().Ref2() = pIAOHandle->Get2ndPos();
2675 // what was hit?
2676 bool bHit(false);
2677 SdrHdlColor* pColHdl = pIAOHandle->GetColorHdl1();
2679 // init handling flags
2680 pIAOHandle->SetMoveSingleHandle(false);
2681 pIAOHandle->SetMoveFirstHandle(false);
2683 // test first color handle
2684 if(pColHdl)
2686 basegfx::B2DPoint aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2688 if(pColHdl->getOverlayObjectList().isHitLogic(aPosition))
2690 bHit = true;
2691 pIAOHandle->SetMoveSingleHandle(true);
2692 pIAOHandle->SetMoveFirstHandle(true);
2696 // test second color handle
2697 pColHdl = pIAOHandle->GetColorHdl2();
2699 if(!bHit && pColHdl)
2701 basegfx::B2DPoint aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2703 if(pColHdl->getOverlayObjectList().isHitLogic(aPosition))
2705 bHit = true;
2706 pIAOHandle->SetMoveSingleHandle(true);
2710 // test gradient handle itself
2711 if(!bHit)
2713 basegfx::B2DPoint aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2715 if(pIAOHandle->getOverlayObjectList().isHitLogic(aPosition))
2717 bHit = true;
2721 // everything up and running :o}
2722 bRetval = bHit;
2724 else
2726 OSL_FAIL("SdrDragGradient::BeginSdrDrag(): IAOGradient not found.");
2729 return bRetval;
2732 void SdrDragGradient::MoveSdrDrag(const Point& rPnt)
2734 if(pIAOHandle && DragStat().CheckMinMoved(rPnt))
2736 DragStat().NextMove(rPnt);
2738 // Do the Move here!!! DragStat().GetStart()
2739 Point aMoveDiff = rPnt - DragStat().GetStart();
2741 if(pIAOHandle->IsMoveSingleHandle())
2743 if(pIAOHandle->IsMoveFirstHandle())
2745 pIAOHandle->SetPos(DragStat().Ref1() + aMoveDiff);
2746 if(pIAOHandle->GetColorHdl1())
2747 pIAOHandle->GetColorHdl1()->SetPos(DragStat().Ref1() + aMoveDiff);
2749 else
2751 pIAOHandle->Set2ndPos(DragStat().Ref2() + aMoveDiff);
2752 if(pIAOHandle->GetColorHdl2())
2753 pIAOHandle->GetColorHdl2()->SetPos(DragStat().Ref2() + aMoveDiff);
2756 else
2758 pIAOHandle->SetPos(DragStat().Ref1() + aMoveDiff);
2759 pIAOHandle->Set2ndPos(DragStat().Ref2() + aMoveDiff);
2761 if(pIAOHandle->GetColorHdl1())
2762 pIAOHandle->GetColorHdl1()->SetPos(DragStat().Ref1() + aMoveDiff);
2764 if(pIAOHandle->GetColorHdl2())
2765 pIAOHandle->GetColorHdl2()->SetPos(DragStat().Ref2() + aMoveDiff);
2768 // new state
2769 pIAOHandle->FromIAOToItem(getSdrDragView().GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(), false, false);
2773 bool SdrDragGradient::EndSdrDrag(bool /*bCopy*/)
2775 Ref1() = pIAOHandle->GetPos();
2776 Ref2() = pIAOHandle->Get2ndPos();
2778 // new state
2779 pIAOHandle->FromIAOToItem(getSdrDragView().GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(), true, true);
2781 return true;
2784 void SdrDragGradient::CancelSdrDrag()
2786 // restore old values
2787 pIAOHandle->SetPos(DragStat().Ref1());
2788 pIAOHandle->Set2ndPos(DragStat().Ref2());
2790 if(pIAOHandle->GetColorHdl1())
2791 pIAOHandle->GetColorHdl1()->SetPos(DragStat().Ref1());
2793 if(pIAOHandle->GetColorHdl2())
2794 pIAOHandle->GetColorHdl2()->SetPos(DragStat().Ref2());
2796 // new state
2797 pIAOHandle->FromIAOToItem(getSdrDragView().GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(), true, false);
2800 Pointer SdrDragGradient::GetSdrDragPointer() const
2802 return Pointer(POINTER_REFHAND);
2805 ////////////////////////////////////////////////////////////////////////////////////////////////////
2807 TYPEINIT1(SdrDragCrook,SdrDragMethod);
2809 SdrDragCrook::SdrDragCrook(SdrDragView& rNewView)
2810 : SdrDragMethod(rNewView),
2811 aFact(1,1),
2812 bContortionAllowed(false),
2813 bNoContortionAllowed(false),
2814 bContortion(false),
2815 bResizeAllowed(false),
2816 bResize(false),
2817 bRotateAllowed(false),
2818 bRotate(false),
2819 bVertical(false),
2820 bValid(false),
2821 bLft(false),
2822 bRgt(false),
2823 bUpr(false),
2824 bLwr(false),
2825 bAtCenter(false),
2826 nWink(0),
2827 nMarkSize(0),
2828 eMode(SDRCROOK_ROTATE)
2832 void SdrDragCrook::TakeSdrDragComment(XubString& rStr) const
2834 ImpTakeDescriptionStr(!bContortion ? STR_DragMethCrook : STR_DragMethCrookContortion, rStr);
2836 if(bValid)
2838 rStr.AppendAscii(" (");
2840 sal_Int32 nVal(nWink);
2842 if(bAtCenter)
2843 nVal *= 2;
2845 nVal = std::abs(nVal);
2846 OUString aStr;
2847 getSdrDragView().GetModel()->TakeWinkStr(nVal, aStr);
2848 rStr.Append(aStr);
2849 rStr += sal_Unicode(')');
2852 if(getSdrDragView().IsDragWithCopy())
2853 rStr += ImpGetResStr(STR_EditWithCopy);
2856 // These defines parameterize the created raster
2857 // for interactions
2858 #define DRAG_CROOK_RASTER_MINIMUM (4)
2859 #define DRAG_CROOK_RASTER_MAXIMUM (15)
2860 #define DRAG_CROOK_RASTER_DISTANCE (30)
2862 basegfx::B2DPolyPolygon impCreateDragRaster(SdrPageView& rPageView, const Rectangle& rMarkRect)
2864 basegfx::B2DPolyPolygon aRetval;
2866 if(rPageView.PageWindowCount())
2868 OutputDevice& rOut = (rPageView.GetPageWindow(0)->GetPaintWindow().GetOutputDevice());
2869 Rectangle aPixelSize = rOut.LogicToPixel(rMarkRect);
2870 sal_uInt32 nHorDiv(aPixelSize.GetWidth() / DRAG_CROOK_RASTER_DISTANCE);
2871 sal_uInt32 nVerDiv(aPixelSize.GetHeight() / DRAG_CROOK_RASTER_DISTANCE);
2873 if(nHorDiv > DRAG_CROOK_RASTER_MAXIMUM)
2874 nHorDiv = DRAG_CROOK_RASTER_MAXIMUM;
2875 if(nHorDiv < DRAG_CROOK_RASTER_MINIMUM)
2876 nHorDiv = DRAG_CROOK_RASTER_MINIMUM;
2878 if(nVerDiv > DRAG_CROOK_RASTER_MAXIMUM)
2879 nVerDiv = DRAG_CROOK_RASTER_MAXIMUM;
2880 if(nVerDiv < DRAG_CROOK_RASTER_MINIMUM)
2881 nVerDiv = DRAG_CROOK_RASTER_MINIMUM;
2883 const double fXLen(rMarkRect.GetWidth() / (double)nHorDiv);
2884 const double fYLen(rMarkRect.GetHeight() / (double)nVerDiv);
2885 double fYPos(rMarkRect.Top());
2886 sal_uInt32 a, b;
2888 for(a = 0; a <= nVerDiv; a++)
2890 // horizontal lines
2891 for(b = 0; b < nHorDiv; b++)
2893 basegfx::B2DPolygon aHorLineSegment;
2895 const double fNewX(rMarkRect.Left() + (b * fXLen));
2896 aHorLineSegment.append(basegfx::B2DPoint(fNewX, fYPos));
2897 aHorLineSegment.appendBezierSegment(
2898 basegfx::B2DPoint(fNewX + (fXLen * (1.0 / 3.0)), fYPos),
2899 basegfx::B2DPoint(fNewX + (fXLen * (2.0 / 3.0)), fYPos),
2900 basegfx::B2DPoint(fNewX + fXLen, fYPos));
2901 aRetval.append(aHorLineSegment);
2904 // increments
2905 fYPos += fYLen;
2908 double fXPos(rMarkRect.Left());
2910 for(a = 0; a <= nHorDiv; a++)
2912 // vertical lines
2913 for(b = 0; b < nVerDiv; b++)
2915 basegfx::B2DPolygon aVerLineSegment;
2917 const double fNewY(rMarkRect.Top() + (b * fYLen));
2918 aVerLineSegment.append(basegfx::B2DPoint(fXPos, fNewY));
2919 aVerLineSegment.appendBezierSegment(
2920 basegfx::B2DPoint(fXPos, fNewY + (fYLen * (1.0 / 3.0))),
2921 basegfx::B2DPoint(fXPos, fNewY + (fYLen * (2.0 / 3.0))),
2922 basegfx::B2DPoint(fXPos, fNewY + fYLen));
2923 aRetval.append(aVerLineSegment);
2926 // increments
2927 fXPos += fXLen;
2931 return aRetval;
2934 void SdrDragCrook::createSdrDragEntries()
2936 // Add extended frame raster first, so it will be behind objects
2937 if(getSdrDragView().GetSdrPageView())
2939 const basegfx::B2DPolyPolygon aDragRaster(impCreateDragRaster(*getSdrDragView().GetSdrPageView(), GetMarkedRect()));
2941 if(aDragRaster.count())
2943 addSdrDragEntry(new SdrDragEntryPolyPolygon(aDragRaster));
2947 // call parent
2948 SdrDragMethod::createSdrDragEntries();
2951 bool SdrDragCrook::BeginSdrDrag()
2953 bContortionAllowed=getSdrDragView().IsCrookAllowed(false);
2954 bNoContortionAllowed=getSdrDragView().IsCrookAllowed(true);
2955 bResizeAllowed=getSdrDragView().IsResizeAllowed(false);
2956 bRotateAllowed=getSdrDragView().IsRotateAllowed(false);
2958 if (bContortionAllowed || bNoContortionAllowed)
2960 bVertical=(GetDragHdlKind()==HDL_LOWER || GetDragHdlKind()==HDL_UPPER);
2961 aMarkRect=GetMarkedRect();
2962 aMarkCenter=aMarkRect.Center();
2963 nMarkSize=bVertical ? (aMarkRect.GetHeight()-1) : (aMarkRect.GetWidth()-1);
2964 aCenter=aMarkCenter;
2965 aStart=DragStat().GetStart();
2966 Show();
2967 return true;
2969 else
2971 return false;
2975 void SdrDragCrook::_MovAllPoints(basegfx::B2DPolyPolygon& rTarget)
2977 SdrPageView* pPV = getSdrDragView().GetSdrPageView();
2979 if(pPV)
2981 XPolyPolygon aTempPolyPoly(rTarget);
2983 if (pPV->HasMarkedObjPageView())
2985 sal_uInt16 nPolyAnz=aTempPolyPoly.Count();
2987 if (!bContortion && !getSdrDragView().IsNoDragXorPolys())
2989 sal_uInt16 n1st=0,nLast=0;
2990 Point aC(aCenter);
2992 while (n1st<nPolyAnz)
2994 nLast=n1st;
2995 while (nLast<nPolyAnz && aTempPolyPoly[nLast].GetPointCount()!=0) nLast++;
2996 Rectangle aBound(aTempPolyPoly[n1st].GetBoundRect());
2997 sal_uInt16 i;
2999 for (i=n1st+1; i<nLast; i++)
3001 aBound.Union(aTempPolyPoly[n1st].GetBoundRect());
3004 Point aCtr0(aBound.Center());
3005 Point aCtr1(aCtr0);
3007 if (bResize)
3009 Fraction aFact1(1,1);
3011 if (bVertical)
3013 ResizePoint(aCtr1,aC,aFact1,aFact);
3015 else
3017 ResizePoint(aCtr1,aC,aFact,aFact1);
3021 bool bRotOk=false;
3022 double nSin=0,nCos=0;
3024 if (aRad.X()!=0 && aRad.Y()!=0)
3026 bRotOk=bRotate;
3028 switch (eMode)
3030 case SDRCROOK_ROTATE : CrookRotateXPoint (aCtr1,NULL,NULL,aC,aRad,nSin,nCos,bVertical); break;
3031 case SDRCROOK_SLANT : CrookSlantXPoint (aCtr1,NULL,NULL,aC,aRad,nSin,nCos,bVertical); break;
3032 case SDRCROOK_STRETCH: CrookStretchXPoint(aCtr1,NULL,NULL,aC,aRad,nSin,nCos,bVertical,aMarkRect); break;
3033 } // switch
3036 aCtr1-=aCtr0;
3038 for (i=n1st; i<nLast; i++)
3040 if (bRotOk)
3042 RotateXPoly(aTempPolyPoly[i],aCtr0,nSin,nCos);
3045 aTempPolyPoly[i].Move(aCtr1.X(),aCtr1.Y());
3048 n1st=nLast+1;
3051 else
3053 sal_uInt16 i,j;
3055 for (j=0; j<nPolyAnz; j++)
3057 XPolygon& aPol=aTempPolyPoly[j];
3058 sal_uInt16 nPtAnz=aPol.GetPointCount();
3059 i=0;
3061 while (i<nPtAnz)
3063 Point* pPnt=&aPol[i];
3064 Point* pC1=NULL;
3065 Point* pC2=NULL;
3067 if (i+1<nPtAnz && aPol.IsControl(i))
3068 { // control point on the left
3069 pC1=pPnt;
3070 i++;
3071 pPnt=&aPol[i];
3074 i++;
3076 if (i<nPtAnz && aPol.IsControl(i))
3077 { // control point on the right
3078 pC2=&aPol[i];
3079 i++;
3082 _MovCrookPoint(*pPnt,pC1,pC2);
3088 rTarget = aTempPolyPoly.getB2DPolyPolygon();
3092 void SdrDragCrook::_MovCrookPoint(Point& rPnt, Point* pC1, Point* pC2)
3094 bool bVert=bVertical;
3095 bool bC1=pC1!=NULL;
3096 bool bC2=pC2!=NULL;
3097 Point aC(aCenter);
3099 if (bResize)
3101 Fraction aFact1(1,1);
3103 if (bVert)
3105 ResizePoint(rPnt,aC,aFact1,aFact);
3107 if (bC1)
3108 ResizePoint(*pC1,aC,aFact1,aFact);
3110 if (bC2)
3111 ResizePoint(*pC2,aC,aFact1,aFact);
3113 else
3115 ResizePoint(rPnt,aC,aFact,aFact1);
3117 if (bC1)
3118 ResizePoint(*pC1,aC,aFact,aFact1);
3120 if (bC2)
3121 ResizePoint(*pC2,aC,aFact,aFact1);
3125 if (aRad.X()!=0 && aRad.Y()!=0)
3127 double nSin,nCos;
3129 switch (eMode)
3131 case SDRCROOK_ROTATE : CrookRotateXPoint (rPnt,pC1,pC2,aC,aRad,nSin,nCos,bVert); break;
3132 case SDRCROOK_SLANT : CrookSlantXPoint (rPnt,pC1,pC2,aC,aRad,nSin,nCos,bVert); break;
3133 case SDRCROOK_STRETCH: CrookStretchXPoint(rPnt,pC1,pC2,aC,aRad,nSin,nCos,bVert,aMarkRect); break;
3134 } // switch
3138 void SdrDragCrook::MoveSdrDrag(const Point& rPnt)
3140 if (DragStat().CheckMinMoved(rPnt))
3142 Point aPnt(rPnt);
3143 bool bNeuMoveOnly=getSdrDragView().IsMoveOnlyDragging();
3144 bAtCenter=false;
3145 SdrCrookMode eNeuMode=getSdrDragView().GetCrookMode();
3146 bool bNeuContortion=!bNeuMoveOnly && ((bContortionAllowed && !getSdrDragView().IsCrookNoContortion()) || !bNoContortionAllowed);
3147 bResize=!getSdrDragView().IsOrtho() && bResizeAllowed && !bNeuMoveOnly;
3148 bool bNeuRotate=bRotateAllowed && !bNeuContortion && !bNeuMoveOnly && eNeuMode==SDRCROOK_ROTATE;
3149 long nSA=0;
3151 if (nSA==0)
3152 aPnt=GetSnapPos(aPnt);
3154 Point aNeuCenter(aMarkCenter.X(),aStart.Y());
3156 if (bVertical)
3158 aNeuCenter.X()=aStart.X();
3159 aNeuCenter.Y()=aMarkCenter.Y();
3162 if (!getSdrDragView().IsCrookAtCenter())
3164 switch (GetDragHdlKind())
3166 case HDL_UPLFT: aNeuCenter.X()=aMarkRect.Right(); bLft=true; break;
3167 case HDL_UPPER: aNeuCenter.Y()=aMarkRect.Bottom(); bUpr=true; break;
3168 case HDL_UPRGT: aNeuCenter.X()=aMarkRect.Left(); bRgt=true; break;
3169 case HDL_LEFT : aNeuCenter.X()=aMarkRect.Right(); bLft=true; break;
3170 case HDL_RIGHT: aNeuCenter.X()=aMarkRect.Left(); bRgt=true; break;
3171 case HDL_LWLFT: aNeuCenter.X()=aMarkRect.Right(); bLft=true; break;
3172 case HDL_LOWER: aNeuCenter.Y()=aMarkRect.Top(); bLwr=true; break;
3173 case HDL_LWRGT: aNeuCenter.X()=aMarkRect.Left(); bRgt=true; break;
3174 default: bAtCenter=true;
3177 else
3178 bAtCenter=true;
3180 Fraction aNeuFact(1,1);
3181 long dx1=aPnt.X()-aNeuCenter.X();
3182 long dy1=aPnt.Y()-aNeuCenter.Y();
3183 bValid=bVertical ? dx1!=0 : dy1!=0;
3185 if (bValid)
3187 if (bVertical)
3188 bValid = std::abs(dx1)*100>std::abs(dy1);
3189 else
3190 bValid = std::abs(dy1)*100>std::abs(dx1);
3193 long nNeuRad=0;
3194 nWink=0;
3196 if (bValid)
3198 double a=0; // slope of the radius
3199 long nPntWink=0;
3201 if (bVertical)
3203 a=((double)dy1)/((double)dx1); // slope of the radius
3204 nNeuRad=((long)(dy1*a)+dx1) /2;
3205 aNeuCenter.X()+=nNeuRad;
3206 nPntWink=GetAngle(aPnt-aNeuCenter);
3208 else
3210 a=((double)dx1)/((double)dy1); // slope of the radius
3211 nNeuRad=((long)(dx1*a)+dy1) /2;
3212 aNeuCenter.Y()+=nNeuRad;
3213 nPntWink=GetAngle(aPnt-aNeuCenter)-9000;
3216 if (!bAtCenter)
3218 if (nNeuRad<0)
3220 if (bRgt) nPntWink+=18000;
3221 if (bLft) nPntWink=18000-nPntWink;
3222 if (bLwr) nPntWink=-nPntWink;
3224 else
3226 if (bRgt) nPntWink=-nPntWink;
3227 if (bUpr) nPntWink=18000-nPntWink;
3228 if (bLwr) nPntWink+=18000;
3231 nPntWink=NormAngle360(nPntWink);
3233 else
3235 if (nNeuRad<0) nPntWink+=18000;
3236 if (bVertical) nPntWink=18000-nPntWink;
3237 nPntWink=NormAngle180(nPntWink);
3238 nPntWink = std::abs(nPntWink);
3241 double nUmfang = 2 * std::abs(nNeuRad)*nPi;
3243 if (bResize)
3245 if (nSA!=0)
3246 { // angle snapping
3247 long nWink0=nPntWink;
3248 nPntWink+=nSA/2;
3249 nPntWink/=nSA;
3250 nPntWink*=nSA;
3251 BigInt a2(nNeuRad);
3252 a2*=BigInt(nWink);
3253 a2/=BigInt(nWink0);
3254 nNeuRad=long(a2);
3256 if (bVertical)
3257 aNeuCenter.X()=aStart.X()+nNeuRad;
3258 else
3259 aNeuCenter.Y()=aStart.Y()+nNeuRad;
3262 long nMul=(long)(nUmfang*NormAngle360(nPntWink)/36000);
3264 if (bAtCenter)
3265 nMul*=2;
3267 aNeuFact=Fraction(nMul,nMarkSize);
3268 nWink=nPntWink;
3270 else
3272 nWink=(long)((nMarkSize*360/nUmfang)*100)/2;
3274 if (nWink==0)
3275 bValid=false;
3277 if (bValid && nSA!=0)
3278 { // angle snapping
3279 long nWink0=nWink;
3280 nWink+=nSA/2;
3281 nWink/=nSA;
3282 nWink*=nSA;
3283 BigInt a2(nNeuRad);
3284 a2*=BigInt(nWink);
3285 a2/=BigInt(nWink0);
3286 nNeuRad=long(a2);
3288 if (bVertical)
3289 aNeuCenter.X()=aStart.X()+nNeuRad;
3290 else
3291 aNeuCenter.Y()=aStart.Y()+nNeuRad;
3296 if (nWink==0 || nNeuRad==0)
3297 bValid=false;
3299 if (!bValid)
3300 nNeuRad=0;
3302 if (!bValid && bResize)
3304 long nMul=bVertical ? dy1 : dx1;
3306 if (bLft || bUpr)
3307 nMul=-nMul;
3309 long nDiv=nMarkSize;
3311 if (bAtCenter)
3313 nMul*=2;
3314 nMul = std::abs(nMul);
3317 aNeuFact=Fraction(nMul,nDiv);
3320 if (aNeuCenter!=aCenter || bNeuContortion!=bContortion || aNeuFact!=aFact ||
3321 bNeuMoveOnly != getMoveOnly() || bNeuRotate!=bRotate || eNeuMode!=eMode)
3323 Hide();
3324 setMoveOnly(bNeuMoveOnly);
3325 bRotate=bNeuRotate;
3326 eMode=eNeuMode;
3327 bContortion=bNeuContortion;
3328 aCenter=aNeuCenter;
3329 aFact=aNeuFact;
3330 aRad=Point(nNeuRad,nNeuRad);
3331 bResize=aFact!=Fraction(1,1) && aFact.GetDenominator()!=0 && aFact.IsValid();
3332 DragStat().NextMove(aPnt);
3333 Show();
3338 void SdrDragCrook::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
3340 const bool bDoResize(aFact!=Fraction(1,1));
3341 const bool bDoCrook(aCenter!=aMarkCenter && aRad.X()!=0 && aRad.Y()!=0);
3343 if (bDoCrook || bDoResize)
3345 if (bDoResize)
3347 Fraction aFact1(1,1);
3349 if (bContortion)
3351 if (bVertical)
3353 rTarget.Resize(aCenter,aFact1,aFact);
3355 else
3357 rTarget.Resize(aCenter,aFact,aFact1);
3360 else
3362 Point aCtr0(rTarget.GetSnapRect().Center());
3363 Point aCtr1(aCtr0);
3365 if (bVertical)
3367 ResizePoint(aCtr1,aCenter,aFact1,aFact);
3369 else
3371 ResizePoint(aCtr1,aCenter,aFact,aFact1);
3374 Size aSiz(aCtr1.X()-aCtr0.X(),aCtr1.Y()-aCtr0.Y());
3376 rTarget.Move(aSiz);
3380 if (bDoCrook)
3382 const Rectangle aLocalMarkRect(getSdrDragView().GetMarkedObjRect());
3383 const bool bLocalRotate(!bContortion && eMode == SDRCROOK_ROTATE && getSdrDragView().IsRotateAllowed(false));
3385 getSdrDragView().ImpCrookObj(&rTarget,aCenter,aRad,eMode,bVertical,!bContortion,bLocalRotate,aLocalMarkRect);
3390 void SdrDragCrook::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon& rTarget)
3392 // use helper derived from old stuff
3393 _MovAllPoints(rTarget);
3396 bool SdrDragCrook::EndSdrDrag(bool bCopy)
3398 Hide();
3400 if (bResize && aFact==Fraction(1,1))
3401 bResize=false;
3403 const bool bUndo = getSdrDragView().IsUndoEnabled();
3405 bool bDoCrook=aCenter!=aMarkCenter && aRad.X()!=0 && aRad.Y()!=0;
3407 if (bDoCrook || bResize)
3409 if (bResize && bUndo)
3411 XubString aStr;
3412 ImpTakeDescriptionStr(!bContortion?STR_EditCrook:STR_EditCrookContortion,aStr);
3414 if (bCopy)
3415 aStr+=ImpGetResStr(STR_EditWithCopy);
3417 getSdrDragView().BegUndo(aStr);
3420 if (bResize)
3422 Fraction aFact1(1,1);
3424 if (bContortion)
3426 if (bVertical)
3427 getSdrDragView().ResizeMarkedObj(aCenter,aFact1,aFact,bCopy);
3428 else
3429 getSdrDragView().ResizeMarkedObj(aCenter,aFact,aFact1,bCopy);
3431 else
3433 if (bCopy)
3434 getSdrDragView().CopyMarkedObj();
3436 sal_uLong nMarkAnz=getSdrDragView().GetMarkedObjectList().GetMarkCount();
3438 for (sal_uLong nm=0; nm<nMarkAnz; nm++)
3440 SdrMark* pM=getSdrDragView().GetMarkedObjectList().GetMark(nm);
3441 SdrObject* pO=pM->GetMarkedSdrObj();
3442 Point aCtr0(pO->GetSnapRect().Center());
3443 Point aCtr1(aCtr0);
3445 if (bVertical)
3446 ResizePoint(aCtr1,aCenter,aFact1,aFact);
3447 else
3448 ResizePoint(aCtr1,aCenter,aFact,aFact1);
3450 Size aSiz(aCtr1.X()-aCtr0.X(),aCtr1.Y()-aCtr0.Y());
3451 if( bUndo )
3452 AddUndo(getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pO,aSiz));
3453 pO->Move(aSiz);
3457 bCopy=false;
3460 if (bDoCrook)
3462 getSdrDragView().CrookMarkedObj(aCenter,aRad,eMode,bVertical,!bContortion,bCopy);
3463 getSdrDragView().SetLastCrookCenter(aCenter);
3466 if (bResize && bUndo)
3467 getSdrDragView().EndUndo();
3469 return true;
3472 return false;
3475 Pointer SdrDragCrook::GetSdrDragPointer() const
3477 return Pointer(POINTER_CROOK);
3480 ////////////////////////////////////////////////////////////////////////////////////////////////////
3482 TYPEINIT1(SdrDragDistort,SdrDragMethod);
3484 SdrDragDistort::SdrDragDistort(SdrDragView& rNewView)
3485 : SdrDragMethod(rNewView),
3486 nPolyPt(0),
3487 bContortionAllowed(false),
3488 bNoContortionAllowed(false),
3489 bContortion(false)
3493 void SdrDragDistort::TakeSdrDragComment(XubString& rStr) const
3495 ImpTakeDescriptionStr(STR_DragMethDistort, rStr);
3497 OUString aStr;
3499 rStr.AppendAscii(" (x=");
3500 getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDX(), aStr);
3501 rStr.Append(aStr);
3502 rStr.AppendAscii(" y=");
3503 getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDY(), aStr);
3504 rStr.Append(aStr);
3505 rStr += sal_Unicode(')');
3507 if(getSdrDragView().IsDragWithCopy())
3508 rStr += ImpGetResStr(STR_EditWithCopy);
3511 void SdrDragDistort::createSdrDragEntries()
3513 // Add extended frame raster first, so it will be behind objects
3514 if(getSdrDragView().GetSdrPageView())
3516 const basegfx::B2DPolyPolygon aDragRaster(impCreateDragRaster(*getSdrDragView().GetSdrPageView(), GetMarkedRect()));
3518 if(aDragRaster.count())
3520 addSdrDragEntry(new SdrDragEntryPolyPolygon(aDragRaster));
3524 // call parent
3525 SdrDragMethod::createSdrDragEntries();
3528 bool SdrDragDistort::BeginSdrDrag()
3530 bContortionAllowed=getSdrDragView().IsDistortAllowed(false);
3531 bNoContortionAllowed=getSdrDragView().IsDistortAllowed(true);
3533 if (bContortionAllowed || bNoContortionAllowed)
3535 SdrHdlKind eKind=GetDragHdlKind();
3536 nPolyPt=0xFFFF;
3538 if (eKind==HDL_UPLFT) nPolyPt=0;
3539 if (eKind==HDL_UPRGT) nPolyPt=1;
3540 if (eKind==HDL_LWRGT) nPolyPt=2;
3541 if (eKind==HDL_LWLFT) nPolyPt=3;
3542 if (nPolyPt>3) return false;
3544 aMarkRect=GetMarkedRect();
3545 aDistortedRect=XPolygon(aMarkRect);
3546 Show();
3547 return true;
3549 else
3551 return false;
3555 void SdrDragDistort::_MovAllPoints(basegfx::B2DPolyPolygon& rTarget)
3557 if (bContortion)
3559 SdrPageView* pPV = getSdrDragView().GetSdrPageView();
3561 if(pPV)
3563 if (pPV->HasMarkedObjPageView())
3565 basegfx::B2DPolyPolygon aDragPolygon(rTarget);
3566 const basegfx::B2DRange aOriginalRange(aMarkRect.Left(), aMarkRect.Top(), aMarkRect.Right(), aMarkRect.Bottom());
3567 const basegfx::B2DPoint aTopLeft(aDistortedRect[0].X(), aDistortedRect[0].Y());
3568 const basegfx::B2DPoint aTopRight(aDistortedRect[1].X(), aDistortedRect[1].Y());
3569 const basegfx::B2DPoint aBottomLeft(aDistortedRect[3].X(), aDistortedRect[3].Y());
3570 const basegfx::B2DPoint aBottomRight(aDistortedRect[2].X(), aDistortedRect[2].Y());
3572 aDragPolygon = basegfx::tools::distort(aDragPolygon, aOriginalRange, aTopLeft, aTopRight, aBottomLeft, aBottomRight);
3573 rTarget = aDragPolygon;
3579 void SdrDragDistort::MoveSdrDrag(const Point& rPnt)
3581 if (DragStat().CheckMinMoved(rPnt))
3583 Point aPnt(GetSnapPos(rPnt));
3585 if (getSdrDragView().IsOrtho())
3586 OrthoDistance8(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho());
3588 bool bNeuContortion=(bContortionAllowed && !getSdrDragView().IsCrookNoContortion()) || !bNoContortionAllowed;
3590 if (bNeuContortion!=bContortion || aDistortedRect[nPolyPt]!=aPnt)
3592 Hide();
3593 aDistortedRect[nPolyPt]=aPnt;
3594 bContortion=bNeuContortion;
3595 DragStat().NextMove(aPnt);
3596 Show();
3601 bool SdrDragDistort::EndSdrDrag(bool bCopy)
3603 Hide();
3604 bool bDoDistort=DragStat().GetDX()!=0 || DragStat().GetDY()!=0;
3606 if (bDoDistort)
3608 getSdrDragView().DistortMarkedObj(aMarkRect,aDistortedRect,!bContortion,bCopy);
3609 return true;
3612 return false;
3615 Pointer SdrDragDistort::GetSdrDragPointer() const
3617 return Pointer(POINTER_REFHAND);
3620 void SdrDragDistort::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
3622 const bool bDoDistort(DragStat().GetDX()!=0 || DragStat().GetDY()!=0);
3624 if (bDoDistort)
3626 getSdrDragView().ImpDistortObj(&rTarget, aMarkRect, aDistortedRect, !bContortion);
3630 void SdrDragDistort::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon& rTarget)
3632 // use helper derived from old stuff
3633 _MovAllPoints(rTarget);
3636 ////////////////////////////////////////////////////////////////////////////////////////////////////
3638 TYPEINIT1(SdrDragCrop,SdrDragResize);
3640 SdrDragCrop::SdrDragCrop(SdrDragView& rNewView)
3641 : SdrDragResize(rNewView)
3643 // switch off solid dragging for crop; it just makes no sense since showing
3644 // a 50% transparent object above the original will not be visible
3645 setSolidDraggingActive(false);
3648 void SdrDragCrop::TakeSdrDragComment(XubString& rStr) const
3650 ImpTakeDescriptionStr(STR_DragMethCrop, rStr);
3652 OUString aStr;
3654 rStr.AppendAscii(" (x=");
3655 getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDX(), aStr);
3656 rStr.Append(aStr);
3657 rStr.AppendAscii(" y=");
3658 getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDY(), aStr);
3659 rStr.Append(aStr);
3660 rStr += sal_Unicode(')');
3662 if(getSdrDragView().IsDragWithCopy())
3663 rStr += ImpGetResStr(STR_EditWithCopy);
3666 bool SdrDragCrop::EndSdrDrag(bool bCopy)
3668 Hide();
3670 if( DragStat().GetDX()==0 && DragStat().GetDY()==0 )
3671 return false;
3673 const SdrMarkList& rMarkList = getSdrDragView().GetMarkedObjectList();
3675 if( rMarkList.GetMarkCount() != 1 )
3676 return false;
3678 SdrGrafObj* pObj = dynamic_cast<SdrGrafObj*>( rMarkList.GetMark( 0 )->GetMarkedSdrObj() );
3680 if( !pObj || (pObj->GetGraphicType() == GRAPHIC_NONE) || (pObj->GetGraphicType() == GRAPHIC_DEFAULT) )
3681 return false;
3683 const GraphicObject& rGraphicObject = pObj->GetGraphicObject();
3684 const MapMode aMapMode100thmm(MAP_100TH_MM);
3685 Size aGraphicSize(rGraphicObject.GetPrefSize());
3687 if( MAP_PIXEL == rGraphicObject.GetPrefMapMode().GetMapUnit() )
3688 aGraphicSize = Application::GetDefaultDevice()->PixelToLogic( aGraphicSize, aMapMode100thmm );
3689 else
3690 aGraphicSize = Application::GetDefaultDevice()->LogicToLogic( aGraphicSize, rGraphicObject.GetPrefMapMode(), aMapMode100thmm);
3692 if( aGraphicSize.A() == 0 || aGraphicSize.B() == 0 )
3693 return false;
3695 const SdrGrafCropItem& rOldCrop = (const SdrGrafCropItem&)pObj->GetMergedItem(SDRATTR_GRAFCROP);
3697 const bool bUndo = getSdrDragView().IsUndoEnabled();
3699 if( bUndo )
3701 String aUndoStr;
3702 ImpTakeDescriptionStr(STR_DragMethCrop, aUndoStr);
3704 getSdrDragView().BegUndo( aUndoStr );
3705 getSdrDragView().AddUndo( getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject( *pObj ) );
3708 Rectangle aOldRect( pObj->GetLogicRect() );
3709 getSdrDragView().ResizeMarkedObj(DragStat().Ref1(),aXFact,aYFact,bCopy);
3710 Rectangle aNewRect( pObj->GetLogicRect() );
3712 double fScaleX = ( aGraphicSize.Width() - rOldCrop.GetLeft() - rOldCrop.GetRight() ) / (double)aOldRect.GetWidth();
3713 double fScaleY = ( aGraphicSize.Height() - rOldCrop.GetTop() - rOldCrop.GetBottom() ) / (double)aOldRect.GetHeight();
3715 // to correct the never working combination of cropped images and mirroring
3716 // I have to correct the rectangles the calculation is based on here. In the current
3717 // core geometry stuff a vertical mirror is expressed as 180 degree rotation. All
3718 // this can be removed again when aw080 will have cleaned up the old
3719 // (non-)transformation mess in the core.
3720 if(18000 == pObj->GetGeoStat().nDrehWink)
3722 // old notation of vertical mirror, need to correct diffs since both rects
3723 // are rotated by 180 degrees
3724 aOldRect = Rectangle(aOldRect.TopLeft() - (aOldRect.BottomRight() - aOldRect.TopLeft()), aOldRect.TopLeft());
3725 aNewRect = Rectangle(aNewRect.TopLeft() - (aNewRect.BottomRight() - aNewRect.TopLeft()), aNewRect.TopLeft());
3728 sal_Int32 nDiffLeft = aNewRect.Left() - aOldRect.Left();
3729 sal_Int32 nDiffTop = aNewRect.Top() - aOldRect.Top();
3730 sal_Int32 nDiffRight = aNewRect.Right() - aOldRect.Right();
3731 sal_Int32 nDiffBottom = aNewRect.Bottom() - aOldRect.Bottom();
3733 sal_Int32 nLeftCrop = static_cast<sal_Int32>( rOldCrop.GetLeft() + nDiffLeft * fScaleX );
3734 sal_Int32 nTopCrop = static_cast<sal_Int32>( rOldCrop.GetTop() + nDiffTop * fScaleY );
3735 sal_Int32 nRightCrop = static_cast<sal_Int32>( rOldCrop.GetRight() - nDiffRight * fScaleX );
3736 sal_Int32 nBottomCrop = static_cast<sal_Int32>( rOldCrop.GetBottom() - nDiffBottom * fScaleY );
3738 SfxItemPool& rPool = getSdrDragView().GetModel()->GetItemPool();
3739 SfxItemSet aSet( rPool, SDRATTR_GRAFCROP, SDRATTR_GRAFCROP );
3740 aSet.Put( SdrGrafCropItem( nLeftCrop, nTopCrop, nRightCrop, nBottomCrop ) );
3741 getSdrDragView().SetAttributes( aSet, false );
3743 if( bUndo )
3744 getSdrDragView().EndUndo();
3746 return true;
3749 Pointer SdrDragCrop::GetSdrDragPointer() const
3751 return Pointer(POINTER_CROP);
3754 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */