xref: /AOO41X/main/svx/source/svdraw/svddrgmt.cxx (revision 707fc0d4d52eb4f69d89a98ffec6918ca5de6326)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include "svddrgm1.hxx"
28 #include <math.h>
29 
30 #ifndef _MATH_H
31 #define _MATH_H
32 #endif
33 #include <tools/bigint.hxx>
34 #include <vcl/svapp.hxx>
35 
36 #include "svx/xattr.hxx"
37 #include <svx/xpoly.hxx>
38 #include <svx/svdetc.hxx>
39 #include <svx/svdtrans.hxx>
40 #include <svx/svdundo.hxx>
41 #include <svx/svdmark.hxx>
42 #include <svx/svdocapt.hxx>
43 #include <svx/svdpagv.hxx>
44 #include "svx/svdstr.hrc"   // Namen aus der Resource
45 #include "svx/svdglob.hxx"  // StringCache
46 #include <svx/svddrgv.hxx>
47 #include <svx/svdundo.hxx>
48 #include <svx/svdograf.hxx>
49 #include <svx/dialogs.hrc>
50 #include <svx/dialmgr.hxx>
51 #include <svx/sdgcpitm.hxx>
52 #include <basegfx/polygon/b2dpolygon.hxx>
53 #include <basegfx/polygon/b2dpolygontools.hxx>
54 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
55 #include <svx/sdr/overlay/overlaymanager.hxx>
56 #include <svx/sdr/overlay/overlayrollingrectangle.hxx>
57 #include <svx/sdrpagewindow.hxx>
58 #include <svx/sdrpaintwindow.hxx>
59 #include <basegfx/matrix/b2dhommatrix.hxx>
60 #include <basegfx/polygon/b2dpolypolygontools.hxx>
61 #include <svx/sdr/contact/viewobjectcontact.hxx>
62 #include <svx/sdr/contact/viewcontact.hxx>
63 #include <svx/sdr/contact/displayinfo.hxx>
64 #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
65 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
66 #include <svx/sdr/contact/objectcontact.hxx>
67 #include "svx/svditer.hxx"
68 #include <svx/svdopath.hxx>
69 #include <svx/polypolygoneditor.hxx>
70 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
71 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
72 #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
73 #include <svx/sdr/primitive2d/sdrattributecreator.hxx>
74 #include <svx/sdr/primitive2d/sdrdecompositiontools.hxx>
75 #include <svx/svdoole2.hxx>
76 #include <svx/svdovirt.hxx>
77 #include <svx/svdouno.hxx>
78 #include <svx/sdr/primitive2d/sdrprimitivetools.hxx>
79 #include <basegfx/matrix/b2dhommatrixtools.hxx>
80 #include <drawinglayer/attribute/sdrlineattribute.hxx>
81 #include <drawinglayer/attribute/sdrlinestartendattribute.hxx>
82 
83 ////////////////////////////////////////////////////////////////////////////////////////////////////
84 
85 SdrDragEntry::SdrDragEntry()
86 :   mbAddToTransparent(false)
87 {
88 }
89 
90 SdrDragEntry::~SdrDragEntry()
91 {
92 }
93 
94 ////////////////////////////////////////////////////////////////////////////////////////////////////
95 
96 SdrDragEntryPolyPolygon::SdrDragEntryPolyPolygon(const basegfx::B2DPolyPolygon& rOriginalPolyPolygon)
97 :   SdrDragEntry(),
98     maOriginalPolyPolygon(rOriginalPolyPolygon)
99 {
100 }
101 
102 SdrDragEntryPolyPolygon::~SdrDragEntryPolyPolygon()
103 {
104 }
105 
106 drawinglayer::primitive2d::Primitive2DSequence SdrDragEntryPolyPolygon::createPrimitive2DSequenceInCurrentState(SdrDragMethod& rDragMethod)
107 {
108     drawinglayer::primitive2d::Primitive2DSequence aRetval;
109 
110     if(maOriginalPolyPolygon.count())
111     {
112         basegfx::B2DPolyPolygon aCopy(maOriginalPolyPolygon);
113         const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
114 
115         rDragMethod.applyCurrentTransformationToPolyPolygon(aCopy);
116         basegfx::BColor aColA(aSvtOptionsDrawinglayer.GetStripeColorA().getBColor());
117         basegfx::BColor aColB(aSvtOptionsDrawinglayer.GetStripeColorB().getBColor());
118         const double fStripeLength(aSvtOptionsDrawinglayer.GetStripeLength());
119 
120         if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
121         {
122             aColA = aColB = Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
123             aColB.invert();
124         }
125 
126         drawinglayer::primitive2d::Primitive2DReference aPolyPolygonMarkerPrimitive2D(
127             new drawinglayer::primitive2d::PolyPolygonMarkerPrimitive2D(aCopy, aColA, aColB, fStripeLength));
128 
129         aRetval = drawinglayer::primitive2d::Primitive2DSequence(&aPolyPolygonMarkerPrimitive2D, 1);
130     }
131 
132     return aRetval;
133 }
134 
135 ////////////////////////////////////////////////////////////////////////////////////////////////////
136 
137 SdrDragEntrySdrObject::SdrDragEntrySdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact, bool bModify)
138 :   SdrDragEntry(),
139     maOriginal(rOriginal),
140     mpClone(0),
141     mrObjectContact(rObjectContact),
142     mbModify(bModify)
143 {
144     // add SdrObject parts to transparent overlay stuff
145     setAddToTransparent(true);
146 }
147 
148 SdrDragEntrySdrObject::~SdrDragEntrySdrObject()
149 {
150     if(mpClone)
151     {
152         SdrObject::Free(mpClone);
153     }
154 }
155 
156 drawinglayer::primitive2d::Primitive2DSequence SdrDragEntrySdrObject::createPrimitive2DSequenceInCurrentState(SdrDragMethod& rDragMethod)
157 {
158     // for the moment, i need to re-create the clone in all cases. I need to figure
159     // out when clone and original have the same class, so that i can use operator=
160     // in those cases
161 
162     //        // copy all other needed stuff
163     //        basegfx::B2DHomMatrix aMatrix;
164     //        basegfx::B2DPolyPolygon aPolyPolygon;
165     //      pOleObject->TRGetBaseGeometry(aMatrix, aPolyPolygon);
166     //        pClone->TRSetBaseGeometry(aMatrix, aPolyPolygon);
167 
168     const SdrObject* pSource = &maOriginal;
169 
170     if(mpClone)
171     {
172         SdrObject::Free(mpClone);
173         mpClone = 0;
174     }
175 
176     if(mbModify)
177     {
178         if(!mpClone)
179         {
180             mpClone = maOriginal.getFullDragClone();
181         }
182 
183         // apply original transformation, implemented at the DragMethods
184         rDragMethod.applyCurrentTransformationToSdrObject(*mpClone);
185 
186         // choose source for geometry data
187         pSource = mpClone;
188     }
189 
190     // get VOC and Primitive2DSequence
191     sdr::contact::ViewContact& rVC = pSource->GetViewContact();
192     sdr::contact::ViewObjectContact& rVOC = rVC.GetViewObjectContact(mrObjectContact);
193     sdr::contact::DisplayInfo aDisplayInfo;
194 
195     // Do not use the last ViewPort set at the OC from the last ProcessDisplay(),
196     // here we want the complete primitive sequence without visibility clippings
197     mrObjectContact.resetViewPort();
198 
199     return rVOC.getPrimitive2DSequenceHierarchy(aDisplayInfo);
200 }
201 
202 ////////////////////////////////////////////////////////////////////////////////////////////////////
203 
204 SdrDragEntryPrimitive2DSequence::SdrDragEntryPrimitive2DSequence(
205     const drawinglayer::primitive2d::Primitive2DSequence& rSequence,
206     bool bAddToTransparent)
207 :   SdrDragEntry(),
208     maPrimitive2DSequence(rSequence)
209 {
210     // add parts to transparent overlay stuff eventually
211     setAddToTransparent(bAddToTransparent);
212 }
213 
214 SdrDragEntryPrimitive2DSequence::~SdrDragEntryPrimitive2DSequence()
215 {
216 }
217 
218 drawinglayer::primitive2d::Primitive2DSequence SdrDragEntryPrimitive2DSequence::createPrimitive2DSequenceInCurrentState(SdrDragMethod& rDragMethod)
219 {
220     drawinglayer::primitive2d::Primitive2DReference aTransformPrimitive2D(
221         new drawinglayer::primitive2d::TransformPrimitive2D(
222             rDragMethod.getCurrentTransformation(),
223             maPrimitive2DSequence));
224 
225     return drawinglayer::primitive2d::Primitive2DSequence(&aTransformPrimitive2D, 1);
226 }
227 
228 ////////////////////////////////////////////////////////////////////////////////////////////////////
229 
230 SdrDragEntryPointGlueDrag::SdrDragEntryPointGlueDrag(const std::vector< basegfx::B2DPoint >& rPositions, bool bIsPointDrag)
231 :   maPositions(rPositions),
232     mbIsPointDrag(bIsPointDrag)
233 {
234     // add SdrObject parts to transparent overlay stuff
235     setAddToTransparent(true);
236 }
237 
238 SdrDragEntryPointGlueDrag::~SdrDragEntryPointGlueDrag()
239 {
240 }
241 
242 drawinglayer::primitive2d::Primitive2DSequence SdrDragEntryPointGlueDrag::createPrimitive2DSequenceInCurrentState(SdrDragMethod& rDragMethod)
243 {
244     drawinglayer::primitive2d::Primitive2DSequence aRetval;
245 
246     if(!maPositions.empty())
247     {
248         basegfx::B2DPolygon aPolygon;
249         sal_uInt32 a(0);
250 
251         for(a = 0; a < maPositions.size(); a++)
252         {
253             aPolygon.append(maPositions[a]);
254         }
255 
256         basegfx::B2DPolyPolygon aPolyPolygon(aPolygon);
257 
258         rDragMethod.applyCurrentTransformationToPolyPolygon(aPolyPolygon);
259 
260         const basegfx::B2DPolygon aTransformed(aPolyPolygon.getB2DPolygon(0));
261         std::vector< basegfx::B2DPoint > aTransformedPositions;
262 
263         aTransformedPositions.reserve(aTransformed.count());
264 
265         for(a = 0; a < aTransformed.count(); a++)
266         {
267             aTransformedPositions.push_back(aTransformed.getB2DPoint(a));
268         }
269 
270         if(mbIsPointDrag)
271         {
272             const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
273             basegfx::BColor aColor(aSvtOptionsDrawinglayer.GetStripeColorA().getBColor());
274 
275             if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
276             {
277                 aColor = Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
278             }
279 
280             drawinglayer::primitive2d::Primitive2DReference aMarkerArrayPrimitive2D(
281                 new drawinglayer::primitive2d::MarkerArrayPrimitive2D(aTransformedPositions,
282                     drawinglayer::primitive2d::createDefaultCross_3x3(aColor)));
283 
284             aRetval = drawinglayer::primitive2d::Primitive2DSequence(&aMarkerArrayPrimitive2D, 1);
285         }
286         else
287         {
288             const basegfx::BColor aBackPen(1.0, 1.0, 1.0);
289             const basegfx::BColor aRGBFrontColor(0.0, 0.0, 1.0); // COL_LIGHTBLUE
290             drawinglayer::primitive2d::Primitive2DReference aMarkerArrayPrimitive2D(
291                 new drawinglayer::primitive2d::MarkerArrayPrimitive2D(aTransformedPositions,
292                     drawinglayer::primitive2d::createDefaultGluepoint_7x7(aBackPen, aRGBFrontColor)));
293 
294             aRetval = drawinglayer::primitive2d::Primitive2DSequence(&aMarkerArrayPrimitive2D, 1);
295         }
296     }
297 
298     return aRetval;
299 }
300 
301 ////////////////////////////////////////////////////////////////////////////////////////////////////
302 
303 TYPEINIT0(SdrDragMethod);
304 
305 void SdrDragMethod::resetSdrDragEntries()
306 {
307     // clear entries; creation is on demand
308     clearSdrDragEntries();
309 }
310 
311 basegfx::B2DRange SdrDragMethod::getCurrentRange() const
312 {
313     return getB2DRangeFromOverlayObjectList();
314 }
315 
316 void SdrDragMethod::createSdrDragEntries()
317 {
318     if(getSdrDragView().GetSdrPageView() && getSdrDragView().GetSdrPageView()->HasMarkedObjPageView())
319     {
320         if(getSdrDragView().IsDraggingPoints())
321         {
322             createSdrDragEntries_PointDrag();
323         }
324         else if(getSdrDragView().IsDraggingGluePoints())
325         {
326             createSdrDragEntries_GlueDrag();
327         }
328         else
329         {
330             if(getSolidDraggingActive())
331             {
332                 createSdrDragEntries_SolidDrag();
333             }
334             else
335             {
336                 createSdrDragEntries_PolygonDrag();
337             }
338         }
339     }
340 }
341 
342 void SdrDragMethod::createSdrDragEntryForSdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact, bool bModify)
343 {
344     // add full obejct drag; Clone() at the object has to work
345     // for this
346     addSdrDragEntry(new SdrDragEntrySdrObject(rOriginal, rObjectContact, bModify));
347 }
348 
349 void SdrDragMethod::createSdrDragEntries_SolidDrag()
350 {
351     const sal_uInt32 nMarkAnz(getSdrDragView().GetMarkedObjectCount());
352     SdrPageView* pPV = getSdrDragView().GetSdrPageView();
353 
354     if(pPV)
355     {
356         for(sal_uInt32 a(0); a < nMarkAnz; a++)
357         {
358             SdrMark* pM = getSdrDragView().GetSdrMarkByIndex(a);
359 
360             if(pM->GetPageView() == pPV)
361             {
362                 const SdrObject* pObject = pM->GetMarkedSdrObj();
363 
364                 if(pObject)
365                 {
366                     if(pPV->PageWindowCount())
367                     {
368                         sdr::contact::ObjectContact& rOC = pPV->GetPageWindow(0)->GetObjectContact();
369                         SdrObjListIter aIter(*pObject);
370 
371                         while(aIter.IsMore())
372                         {
373                             SdrObject* pCandidate = aIter.Next();
374 
375                             if(pCandidate)
376                             {
377                                 const bool bSuppressFullDrag(!pCandidate->supportsFullDrag());
378                                 bool bAddWireframe(bSuppressFullDrag);
379 
380                                 if(!bAddWireframe && !pCandidate->HasLineStyle())
381                                 {
382                                     // add wireframe for objects without outline
383                                     bAddWireframe = true;
384                                 }
385 
386                                 if(!bSuppressFullDrag)
387                                 {
388                                     // add full obejct drag; Clone() at the object has to work
389                                     // for this
390                                     createSdrDragEntryForSdrObject(*pCandidate, rOC, true);
391                                 }
392 
393                                 if(bAddWireframe)
394                                 {
395                                     // when dragging a 50% transparent copy of a filled or not filled object without
396                                     // outline, this is normally hard to see. Add extra wireframe in that case. This
397                                     // works nice e.g. with thext frames etc.
398                                     addSdrDragEntry(new SdrDragEntryPolyPolygon(pCandidate->TakeXorPoly()));
399                                 }
400                             }
401                         }
402                     }
403                 }
404             }
405         }
406     }
407 }
408 
409 void SdrDragMethod::createSdrDragEntries_PolygonDrag()
410 {
411     const sal_uInt32 nMarkAnz(getSdrDragView().GetMarkedObjectCount());
412     bool bNoPolygons(getSdrDragView().IsNoDragXorPolys() || nMarkAnz > getSdrDragView().GetDragXorPolyLimit());
413     basegfx::B2DPolyPolygon aResult;
414     sal_uInt32 nPointCount(0);
415 
416     for(sal_uInt32 a(0); !bNoPolygons && a < nMarkAnz; a++)
417     {
418         SdrMark* pM = getSdrDragView().GetSdrMarkByIndex(a);
419 
420         if(pM->GetPageView() == getSdrDragView().GetSdrPageView())
421         {
422             const basegfx::B2DPolyPolygon aNewPolyPolygon(pM->GetMarkedSdrObj()->TakeXorPoly());
423 
424             for(sal_uInt32 b(0); b < aNewPolyPolygon.count(); b++)
425             {
426                 nPointCount += aNewPolyPolygon.getB2DPolygon(b).count();
427             }
428 
429             if(nPointCount > getSdrDragView().GetDragXorPointLimit())
430             {
431                 bNoPolygons = true;
432             }
433 
434             if(!bNoPolygons)
435             {
436                 aResult.append(aNewPolyPolygon);
437             }
438         }
439     }
440 
441     if(bNoPolygons)
442     {
443         const Rectangle aR(getSdrDragView().GetSdrPageView()->MarkSnap());
444         const basegfx::B2DRange aNewRectangle(aR.Left(), aR.Top(), aR.Right(), aR.Bottom());
445         basegfx::B2DPolygon aNewPolygon(basegfx::tools::createPolygonFromRect(aNewRectangle));
446 
447         aResult = basegfx::B2DPolyPolygon(basegfx::tools::expandToCurve(aNewPolygon));
448     }
449 
450     if(aResult.count())
451     {
452         addSdrDragEntry(new SdrDragEntryPolyPolygon(aResult));
453     }
454 }
455 
456 void SdrDragMethod::createSdrDragEntries_PointDrag()
457 {
458     const sal_uInt32 nMarkAnz(getSdrDragView().GetMarkedObjectCount());
459     std::vector< basegfx::B2DPoint > aPositions;
460 
461     for(sal_uInt32 nm(0); nm < nMarkAnz; nm++)
462     {
463         SdrMark* pM = getSdrDragView().GetSdrMarkByIndex(nm);
464 
465         if(pM->GetPageView() == getSdrDragView().GetSdrPageView())
466         {
467             const SdrUShortCont* pPts = pM->GetMarkedPoints();
468 
469             if(pPts && pPts->GetCount())
470             {
471                 const SdrObject* pObj = pM->GetMarkedSdrObj();
472                 const SdrPathObj* pPath = dynamic_cast< const SdrPathObj* >(pObj);
473 
474                 if(pPath)
475                 {
476                     const basegfx::B2DPolyPolygon aPathXPP = pPath->GetPathPoly();
477 
478                     if(aPathXPP.count())
479                     {
480                         const sal_uInt32 nPtAnz(pPts->GetCount());
481 
482                         for(sal_uInt32 nPtNum(0); nPtNum < nPtAnz; nPtNum++)
483                         {
484                             sal_uInt32 nPolyNum, nPointNum;
485                             const sal_uInt16 nObjPt(pPts->GetObject(nPtNum));
486 
487                             if(sdr::PolyPolygonEditor::GetRelativePolyPoint(aPathXPP, nObjPt, nPolyNum, nPointNum))
488                             {
489                                 aPositions.push_back(aPathXPP.getB2DPolygon(nPolyNum).getB2DPoint(nPointNum));
490                             }
491                         }
492                     }
493                 }
494             }
495         }
496     }
497 
498     if(!aPositions.empty())
499     {
500         addSdrDragEntry(new SdrDragEntryPointGlueDrag(aPositions, true));
501     }
502 }
503 
504 void SdrDragMethod::createSdrDragEntries_GlueDrag()
505 {
506     const sal_uInt32 nMarkAnz(getSdrDragView().GetMarkedObjectCount());
507     std::vector< basegfx::B2DPoint > aPositions;
508 
509     for(sal_uInt32 nm(0); nm < nMarkAnz; nm++)
510     {
511         SdrMark* pM = getSdrDragView().GetSdrMarkByIndex(nm);
512 
513         if(pM->GetPageView() == getSdrDragView().GetSdrPageView())
514         {
515             const SdrUShortCont* pPts = pM->GetMarkedGluePoints();
516 
517             if(pPts && pPts->GetCount())
518             {
519                 const SdrObject* pObj = pM->GetMarkedSdrObj();
520                 const SdrGluePointList* pGPL = pObj->GetGluePointList();
521 
522                 if(pGPL)
523                 {
524                     const sal_uInt32 nPtAnz(pPts->GetCount());
525 
526                     for(sal_uInt32 nPtNum(0); nPtNum < nPtAnz; nPtNum++)
527                     {
528                         const sal_uInt16 nObjPt(pPts->GetObject(nPtNum));
529                         const sal_uInt16 nGlueNum(pGPL->FindGluePoint(nObjPt));
530 
531                         if(SDRGLUEPOINT_NOTFOUND != nGlueNum)
532                         {
533                             const Point aPoint((*pGPL)[nGlueNum].GetAbsolutePos(*pObj));
534                             aPositions.push_back(basegfx::B2DPoint(aPoint.X(), aPoint.Y()));
535                         }
536                     }
537                 }
538             }
539         }
540     }
541 
542     if(!aPositions.empty())
543     {
544         addSdrDragEntry(new SdrDragEntryPointGlueDrag(aPositions, false));
545     }
546 }
547 
548 void SdrDragMethod::ImpTakeDescriptionStr(sal_uInt16 nStrCacheID, XubString& rStr, sal_uInt16 nVal) const
549 {
550     sal_uInt16 nOpt=0;
551     if (IsDraggingPoints()) {
552         nOpt=IMPSDR_POINTSDESCRIPTION;
553     } else if (IsDraggingGluePoints()) {
554         nOpt=IMPSDR_GLUEPOINTSDESCRIPTION;
555     }
556     getSdrDragView().ImpTakeDescriptionStr(nStrCacheID,rStr,nVal,nOpt);
557 }
558 
559 SdrObject* SdrDragMethod::GetDragObj() const
560 {
561     SdrObject* pObj=NULL;
562     if (getSdrDragView().pDragHdl!=NULL) pObj=getSdrDragView().pDragHdl->GetObj();
563     if (pObj==NULL) pObj=getSdrDragView().pMarkedObj;
564     return pObj;
565 }
566 
567 SdrPageView* SdrDragMethod::GetDragPV() const
568 {
569     SdrPageView* pPV=NULL;
570     if (getSdrDragView().pDragHdl!=NULL) pPV=getSdrDragView().pDragHdl->GetPageView();
571     if (pPV==NULL) pPV=getSdrDragView().pMarkedPV;
572     return pPV;
573 }
574 
575 void SdrDragMethod::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
576 {
577     // the original applies the transformation using TRGetBaseGeometry/TRSetBaseGeometry.
578     // Later this should be the only needed one for linear transforms (not for SdrDragCrook and
579     // SdrDragDistort, those are NOT linear). Currently, this can not yet be used since the
580     // special handling of rotate/mirror due to the not-being-able to handle it in the old
581     // drawinglayer stuff. Text would currently not correctly be mirrored in the preview.
582     basegfx::B2DHomMatrix aObjectTransform;
583     basegfx::B2DPolyPolygon aObjectPolyPolygon;
584     bool bPolyUsed(rTarget.TRGetBaseGeometry(aObjectTransform, aObjectPolyPolygon));
585 
586     // apply transform to object transform
587     aObjectTransform *= getCurrentTransformation();
588 
589     if(bPolyUsed)
590     {
591         // do something special since the object size is in the polygon
592         // break up matrix to get the scale
593         basegfx::B2DTuple aScale;
594         basegfx::B2DTuple aTranslate;
595         double fRotate, fShearX;
596         aObjectTransform.decompose(aScale, aTranslate, fRotate, fShearX);
597 
598         // get polygon's pos and size
599         const basegfx::B2DRange aPolyRange(aObjectPolyPolygon.getB2DRange());
600 
601         // get the scaling factors (do not mirror, this is in the object transformation)
602         const double fScaleX(fabs(aScale.getX()) / (basegfx::fTools::equalZero(aPolyRange.getWidth()) ? 1.0 : aPolyRange.getWidth()));
603         const double fScaleY(fabs(aScale.getY()) / (basegfx::fTools::equalZero(aPolyRange.getHeight()) ? 1.0 : aPolyRange.getHeight()));
604 
605         // prepare transform matrix for polygon
606         basegfx::B2DHomMatrix aPolyTransform(basegfx::tools::createTranslateB2DHomMatrix(
607             -aPolyRange.getMinX(), -aPolyRange.getMinY()));
608         aPolyTransform.scale(fScaleX, fScaleY);
609 
610         // normally the poly should be moved back, but the translation is in the object
611         // transformation and thus does not need to be done
612         // aPolyTransform.translate(-aPolyRange.getMinX(), -aPolyRange.getMinY());
613 
614         // transform the polygon
615         aObjectPolyPolygon.transform(aPolyTransform);
616     }
617 
618     rTarget.TRSetBaseGeometry(getCurrentTransformation() * aObjectTransform, aObjectPolyPolygon);
619 }
620 
621 void SdrDragMethod::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon& rTarget)
622 {
623     // original uses CurrentTransformation
624     rTarget.transform(getCurrentTransformation());
625 }
626 
627 SdrDragMethod::SdrDragMethod(SdrDragView& rNewView)
628 :   maSdrDragEntries(),
629     maOverlayObjectList(),
630     mrSdrDragView(rNewView),
631     mbMoveOnly(false),
632     mbSolidDraggingActive(getSdrDragView().IsSolidDragging())
633 {
634     if(mbSolidDraggingActive && Application::GetSettings().GetStyleSettings().GetHighContrastMode())
635     {
636         // fallback to wireframe when high contrast is used
637         mbSolidDraggingActive = false;
638     }
639 }
640 
641 SdrDragMethod::~SdrDragMethod()
642 {
643     clearSdrDragEntries();
644 }
645 
646 void SdrDragMethod::Show()
647 {
648     getSdrDragView().ShowDragObj();
649 }
650 
651 void SdrDragMethod::Hide()
652 {
653     getSdrDragView().HideDragObj();
654 }
655 
656 basegfx::B2DHomMatrix SdrDragMethod::getCurrentTransformation()
657 {
658     return basegfx::B2DHomMatrix();
659 }
660 
661 void SdrDragMethod::CancelSdrDrag()
662 {
663     Hide();
664 }
665 
666 void SdrDragMethod::CreateOverlayGeometry(sdr::overlay::OverlayManager& rOverlayManager)
667 {
668     // create SdrDragEntries on demand
669     if(maSdrDragEntries.empty())
670     {
671         createSdrDragEntries();
672     }
673 
674     // if there are entries, derive OverlayObjects from the entries, including
675     // modification from current interactive state
676     if(!maSdrDragEntries.empty())
677     {
678         drawinglayer::primitive2d::Primitive2DSequence aResult;
679         drawinglayer::primitive2d::Primitive2DSequence aResultTransparent;
680 
681         for(sal_uInt32 a(0); a < maSdrDragEntries.size(); a++)
682         {
683             SdrDragEntry* pCandidate = maSdrDragEntries[a];
684 
685             if(pCandidate)
686             {
687                 const drawinglayer::primitive2d::Primitive2DSequence aCandidateResult(pCandidate->createPrimitive2DSequenceInCurrentState(*this));
688 
689                 if(aCandidateResult.hasElements())
690                 {
691                     if(pCandidate->getAddToTransparent())
692                     {
693                         drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(aResultTransparent, aCandidateResult);
694                     }
695                     else
696                     {
697                         drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(aResult, aCandidateResult);
698                     }
699                 }
700             }
701         }
702 
703         if(DoAddConnectorOverlays())
704         {
705             const drawinglayer::primitive2d::Primitive2DSequence aConnectorOverlays(AddConnectorOverlays());
706 
707             if(aConnectorOverlays.hasElements())
708             {
709                 // add connector overlays to transparent part
710                 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(aResultTransparent, aConnectorOverlays);
711             }
712         }
713 
714         if(aResult.hasElements())
715         {
716             sdr::overlay::OverlayObject* pNewOverlayObject = new sdr::overlay::OverlayPrimitive2DSequenceObject(aResult);
717             rOverlayManager.add(*pNewOverlayObject);
718             addToOverlayObjectList(*pNewOverlayObject);
719         }
720 
721         if(aResultTransparent.hasElements())
722         {
723             drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparencePrimitive2D(new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(aResultTransparent, 0.5));
724             aResultTransparent = drawinglayer::primitive2d::Primitive2DSequence(&aUnifiedTransparencePrimitive2D, 1);
725 
726             sdr::overlay::OverlayObject* pNewOverlayObject = new sdr::overlay::OverlayPrimitive2DSequenceObject(aResultTransparent);
727             rOverlayManager.add(*pNewOverlayObject);
728             addToOverlayObjectList(*pNewOverlayObject);
729         }
730     }
731 
732     // evtl add DragStripes (help lines cross the page when dragging)
733     if(getSdrDragView().IsDragStripes())
734     {
735         Rectangle aActionRectangle;
736         getSdrDragView().TakeActionRect(aActionRectangle);
737 
738         const basegfx::B2DPoint aTopLeft(aActionRectangle.Left(), aActionRectangle.Top());
739         const basegfx::B2DPoint aBottomRight(aActionRectangle.Right(), aActionRectangle.Bottom());
740         sdr::overlay::OverlayRollingRectangleStriped* pNew = new sdr::overlay::OverlayRollingRectangleStriped(
741             aTopLeft, aBottomRight, true, false);
742 
743         rOverlayManager.add(*pNew);
744         addToOverlayObjectList(*pNew);
745     }
746 }
747 
748 void SdrDragMethod::destroyOverlayGeometry()
749 {
750     clearOverlayObjectList();
751 }
752 
753 bool SdrDragMethod::DoAddConnectorOverlays()
754 {
755     // these conditions are translated from SdrDragView::ImpDrawEdgeXor
756     const SdrMarkList& rMarkedNodes = getSdrDragView().GetEdgesOfMarkedNodes();
757 
758     if(!rMarkedNodes.GetMarkCount())
759     {
760         return false;
761     }
762 
763     if(!getSdrDragView().IsRubberEdgeDragging() && !getSdrDragView().IsDetailedEdgeDragging())
764     {
765         return false;
766     }
767 
768     if(getSdrDragView().IsDraggingPoints() || getSdrDragView().IsDraggingGluePoints())
769     {
770         return false;
771     }
772 
773     if(!getMoveOnly() && !(
774         IS_TYPE(SdrDragMove, this) || IS_TYPE(SdrDragResize, this) ||
775         IS_TYPE(SdrDragRotate,this) || IS_TYPE(SdrDragMirror,this)))
776     {
777         return false;
778     }
779 
780     const bool bDetail(getSdrDragView().IsDetailedEdgeDragging() && getMoveOnly());
781 
782     if(!bDetail && !getSdrDragView().IsRubberEdgeDragging())
783     {
784         return false;
785     }
786 
787     // one more migrated from SdrEdgeObj::NspToggleEdgeXor
788     if(IS_TYPE(SdrDragObjOwn, this) || IS_TYPE(SdrDragMovHdl, this))
789     {
790         return false;
791     }
792 
793     return true;
794 }
795 
796 drawinglayer::primitive2d::Primitive2DSequence SdrDragMethod::AddConnectorOverlays()
797 {
798     drawinglayer::primitive2d::Primitive2DSequence aRetval;
799     const bool bDetail(getSdrDragView().IsDetailedEdgeDragging() && getMoveOnly());
800     const SdrMarkList& rMarkedNodes = getSdrDragView().GetEdgesOfMarkedNodes();
801 
802     for(sal_uInt16 a(0); a < rMarkedNodes.GetMarkCount(); a++)
803     {
804         SdrMark* pEM = rMarkedNodes.GetMark(a);
805 
806         if(pEM && pEM->GetMarkedSdrObj())
807         {
808             SdrEdgeObj* pEdge = dynamic_cast< SdrEdgeObj* >(pEM->GetMarkedSdrObj());
809 
810             if(pEdge)
811             {
812                 const basegfx::B2DPolygon aEdgePolygon(pEdge->ImplAddConnectorOverlay(*this, pEM->IsCon1(), pEM->IsCon2(), bDetail));
813 
814                 if(aEdgePolygon.count())
815                 {
816                     // this polygon is a temporary calculated connector path, so it is not possible to fetch
817                     // the needed primitives directly from the pEdge object which does not get changed. If full
818                     // drag is on, use the SdrObjects ItemSet to create a adequate representation
819                     bool bUseSolidDragging(getSolidDraggingActive());
820 
821                     if(bUseSolidDragging)
822                     {
823                         // switch off solid dragging if connector is not visible
824                         if(!pEdge->HasLineStyle())
825                         {
826                             bUseSolidDragging = false;
827                         }
828                     }
829 
830                     if(bUseSolidDragging)
831                     {
832                         const SfxItemSet& rItemSet = pEdge->GetMergedItemSet();
833                         const drawinglayer::attribute::SdrLineAttribute aLine(
834                             drawinglayer::primitive2d::createNewSdrLineAttribute(rItemSet));
835 
836                         if(!aLine.isDefault())
837                         {
838                             const drawinglayer::attribute::SdrLineStartEndAttribute aLineStartEnd(
839                                 drawinglayer::primitive2d::createNewSdrLineStartEndAttribute(
840                                     rItemSet,
841                                     aLine.getWidth()));
842 
843                             drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(
844                                 aRetval, drawinglayer::primitive2d::createPolygonLinePrimitive(
845                                     aEdgePolygon,
846                                     basegfx::B2DHomMatrix(),
847                                     aLine,
848                                     aLineStartEnd));
849                         }
850                     }
851                     else
852                     {
853                         const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
854                         basegfx::BColor aColA(aSvtOptionsDrawinglayer.GetStripeColorA().getBColor());
855                         basegfx::BColor aColB(aSvtOptionsDrawinglayer.GetStripeColorB().getBColor());
856                         const double fStripeLength(aSvtOptionsDrawinglayer.GetStripeLength());
857 
858                         if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
859                         {
860                             aColA = aColB = Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
861                             aColB.invert();
862                         }
863 
864                         drawinglayer::primitive2d::Primitive2DReference aPolyPolygonMarkerPrimitive2D(
865                             new drawinglayer::primitive2d::PolyPolygonMarkerPrimitive2D(
866                                 basegfx::B2DPolyPolygon(aEdgePolygon), aColA, aColB, fStripeLength));
867                         drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aPolyPolygonMarkerPrimitive2D);
868                     }
869                 }
870             }
871         }
872     }
873 
874     return aRetval;
875 }
876 
877 ////////////////////////////////////////////////////////////////////////////////////////////////////
878 
879 TYPEINIT1(SdrDragMovHdl,SdrDragMethod);
880 
881 SdrDragMovHdl::SdrDragMovHdl(SdrDragView& rNewView)
882 :   SdrDragMethod(rNewView),
883     bMirrObjShown(false)
884 {
885 }
886 
887 void SdrDragMovHdl::createSdrDragEntries()
888 {
889     // SdrDragMovHdl does not use the default drags,
890     // but creates nothing
891 }
892 
893 void SdrDragMovHdl::TakeSdrDragComment(XubString& rStr) const
894 {
895     rStr=ImpGetResStr(STR_DragMethMovHdl);
896     if (getSdrDragView().IsDragWithCopy()) rStr+=ImpGetResStr(STR_EditWithCopy);
897 }
898 
899 bool SdrDragMovHdl::BeginSdrDrag()
900 {
901     if( !GetDragHdl() )
902         return false;
903 
904     DragStat().Ref1()=GetDragHdl()->GetPos();
905     DragStat().SetShown(!DragStat().IsShown());
906     SdrHdlKind eKind=GetDragHdl()->GetKind();
907     SdrHdl* pH1=GetHdlList().GetHdl(HDL_REF1);
908     SdrHdl* pH2=GetHdlList().GetHdl(HDL_REF2);
909 
910     if (eKind==HDL_MIRX)
911     {
912         if (pH1==NULL || pH2==NULL)
913         {
914             DBG_ERROR("SdrDragMovHdl::BeginSdrDrag(): Verschieben der Spiegelachse: Referenzhandles nicht gefunden");
915             return false;
916         }
917 
918         DragStat().SetActionRect(Rectangle(pH1->GetPos(),pH2->GetPos()));
919     }
920     else
921     {
922         Point aPt(GetDragHdl()->GetPos());
923         DragStat().SetActionRect(Rectangle(aPt,aPt));
924     }
925 
926     return true;
927 }
928 
929 void SdrDragMovHdl::MoveSdrDrag(const Point& rNoSnapPnt)
930 {
931     Point aPnt(rNoSnapPnt);
932 
933     if ( GetDragHdl() && DragStat().CheckMinMoved(rNoSnapPnt))
934     {
935         if (GetDragHdl()->GetKind()==HDL_MIRX)
936         {
937             SdrHdl* pH1=GetHdlList().GetHdl(HDL_REF1);
938             SdrHdl* pH2=GetHdlList().GetHdl(HDL_REF2);
939 
940             if (pH1==NULL || pH2==NULL)
941                 return;
942 
943             if (!DragStat().IsNoSnap())
944             {
945                 long nBestXSnap=0;
946                 long nBestYSnap=0;
947                 bool bXSnapped=false;
948                 bool bYSnapped=false;
949                 Point aDif(aPnt-DragStat().GetStart());
950                 getSdrDragView().CheckSnap(Ref1()+aDif,NULL,nBestXSnap,nBestYSnap,bXSnapped,bYSnapped);
951                 getSdrDragView().CheckSnap(Ref2()+aDif,NULL,nBestXSnap,nBestYSnap,bXSnapped,bYSnapped);
952                 aPnt.X()+=nBestXSnap;
953                 aPnt.Y()+=nBestYSnap;
954             }
955 
956             if (aPnt!=DragStat().GetNow())
957             {
958                 Hide();
959                 DragStat().NextMove(aPnt);
960                 Point aDif(DragStat().GetNow()-DragStat().GetStart());
961                 pH1->SetPos(Ref1()+aDif);
962                 pH2->SetPos(Ref2()+aDif);
963 
964                 SdrHdl* pHM = GetHdlList().GetHdl(HDL_MIRX);
965 
966                 if(pHM)
967                     pHM->Touch();
968 
969                 Show();
970                 DragStat().SetActionRect(Rectangle(pH1->GetPos(),pH2->GetPos()));
971             }
972         }
973         else
974         {
975             if (!DragStat().IsNoSnap()) SnapPos(aPnt);
976             long nSA=0;
977 
978             if (getSdrDragView().IsAngleSnapEnabled())
979                 nSA=getSdrDragView().GetSnapAngle();
980 
981             if (getSdrDragView().IsMirrorAllowed(true,true))
982             { // eingeschraenkt
983                 if (!getSdrDragView().IsMirrorAllowed(false,false)) nSA=4500;
984                 if (!getSdrDragView().IsMirrorAllowed(true,false)) nSA=9000;
985             }
986 
987             if (getSdrDragView().IsOrtho() && nSA!=9000)
988                 nSA=4500;
989 
990             if (nSA!=0)
991             { // Winkelfang
992                 SdrHdlKind eRef=HDL_REF1;
993 
994                 if (GetDragHdl()->GetKind()==HDL_REF1)
995                     eRef=HDL_REF2;
996 
997                 SdrHdl* pH=GetHdlList().GetHdl(eRef);
998 
999                 if (pH!=NULL)
1000                 {
1001                     Point aRef(pH->GetPos());
1002                     long nWink=NormAngle360(GetAngle(aPnt-aRef));
1003                     long nNeuWink=nWink;
1004                     nNeuWink+=nSA/2;
1005                     nNeuWink/=nSA;
1006                     nNeuWink*=nSA;
1007                     nNeuWink=NormAngle360(nNeuWink);
1008                     double a=(nNeuWink-nWink)*nPi180;
1009                     double nSin=sin(a);
1010                     double nCos=cos(a);
1011                     RotatePoint(aPnt,aRef,nSin,nCos);
1012 
1013                     // Bei bestimmten Werten Rundungsfehler ausschliessen:
1014                     if (nSA==9000)
1015                     {
1016                         if (nNeuWink==0    || nNeuWink==18000) aPnt.Y()=aRef.Y();
1017                         if (nNeuWink==9000 || nNeuWink==27000) aPnt.X()=aRef.X();
1018                     }
1019 
1020                     if (nSA==4500)
1021                         OrthoDistance8(aRef,aPnt,true);
1022                 }
1023             }
1024 
1025             if (aPnt!=DragStat().GetNow())
1026             {
1027                 Hide();
1028                 DragStat().NextMove(aPnt);
1029                 GetDragHdl()->SetPos(DragStat().GetNow());
1030                 SdrHdl* pHM = GetHdlList().GetHdl(HDL_MIRX);
1031 
1032                 if(pHM)
1033                     pHM->Touch();
1034 
1035                 Show();
1036                 DragStat().SetActionRect(Rectangle(aPnt,aPnt));
1037             }
1038         }
1039     }
1040 }
1041 
1042 bool SdrDragMovHdl::EndSdrDrag(bool /*bCopy*/)
1043 {
1044     if( GetDragHdl() )
1045     {
1046         switch (GetDragHdl()->GetKind())
1047         {
1048             case HDL_REF1:
1049                 Ref1()=DragStat().GetNow();
1050                 break;
1051 
1052             case HDL_REF2:
1053                 Ref2()=DragStat().GetNow();
1054                 break;
1055 
1056             case HDL_MIRX:
1057                 Ref1()+=DragStat().GetNow()-DragStat().GetStart();
1058                 Ref2()+=DragStat().GetNow()-DragStat().GetStart();
1059                 break;
1060 
1061             default: break;
1062         }
1063     }
1064 
1065     return true;
1066 }
1067 
1068 void SdrDragMovHdl::CancelSdrDrag()
1069 {
1070     Hide();
1071 
1072     SdrHdl* pHdl = GetDragHdl();
1073     if( pHdl )
1074         pHdl->SetPos(DragStat().GetRef1());
1075 
1076     SdrHdl* pHM = GetHdlList().GetHdl(HDL_MIRX);
1077 
1078     if(pHM)
1079         pHM->Touch();
1080 }
1081 
1082 Pointer SdrDragMovHdl::GetSdrDragPointer() const
1083 {
1084     const SdrHdl* pHdl = GetDragHdl();
1085 
1086     if (pHdl!=NULL)
1087     {
1088         return pHdl->GetPointer();
1089     }
1090 
1091     return Pointer(POINTER_REFHAND);
1092 }
1093 
1094 ////////////////////////////////////////////////////////////////////////////////////////////////////
1095 
1096 TYPEINIT1(SdrDragObjOwn,SdrDragMethod);
1097 
1098 SdrDragObjOwn::SdrDragObjOwn(SdrDragView& rNewView)
1099 :   SdrDragMethod(rNewView),
1100     mpClone(0)
1101 {
1102     const SdrObject* pObj = GetDragObj();
1103 
1104     if(pObj)
1105     {
1106         // suppress full drag for some object types
1107         setSolidDraggingActive(pObj->supportsFullDrag());
1108     }
1109 }
1110 
1111 SdrDragObjOwn::~SdrDragObjOwn()
1112 {
1113     if(mpClone)
1114     {
1115         SdrObject::Free(mpClone);
1116     }
1117 }
1118 
1119 void SdrDragObjOwn::createSdrDragEntries()
1120 {
1121     if(mpClone)
1122     {
1123         basegfx::B2DPolyPolygon aDragPolyPolygon;
1124         bool bAddWireframe(true);
1125 
1126         if(getSolidDraggingActive())
1127         {
1128             SdrPageView* pPV = getSdrDragView().GetSdrPageView();
1129 
1130             if(pPV && pPV->PageWindowCount())
1131             {
1132                 sdr::contact::ObjectContact& rOC = pPV->GetPageWindow(0)->GetObjectContact();
1133                 addSdrDragEntry(new SdrDragEntrySdrObject(*mpClone, rOC, false));
1134 
1135                 // potentially no wireframe needed, full drag works
1136                 bAddWireframe = false;
1137             }
1138         }
1139 
1140         if(!bAddWireframe)
1141         {
1142             // check for extra conditions for wireframe, e.g. no border at
1143             // objects
1144             if(!mpClone->HasLineStyle())
1145             {
1146                 bAddWireframe = true;
1147             }
1148         }
1149 
1150         if(bAddWireframe)
1151         {
1152             // use wireframe poly when full drag is off or did not work
1153             aDragPolyPolygon = mpClone->TakeXorPoly();
1154         }
1155 
1156         // add evtl. extra DragPolyPolygon
1157         const basegfx::B2DPolyPolygon aSpecialDragPolyPolygon(mpClone->getSpecialDragPoly(DragStat()));
1158 
1159         if(aSpecialDragPolyPolygon.count())
1160         {
1161             aDragPolyPolygon.append(aSpecialDragPolyPolygon);
1162         }
1163 
1164         if(aDragPolyPolygon.count())
1165         {
1166             addSdrDragEntry(new SdrDragEntryPolyPolygon(aDragPolyPolygon));
1167         }
1168     }
1169 }
1170 
1171 void SdrDragObjOwn::TakeSdrDragComment(XubString& rStr) const
1172 {
1173     // #i103058# get info string from the clone preferred, the original will
1174     // not be changed. For security, use original as fallback
1175     if(mpClone)
1176     {
1177         rStr = mpClone->getSpecialDragComment(DragStat());
1178     }
1179     else
1180     {
1181         const SdrObject* pObj = GetDragObj();
1182 
1183         if(pObj)
1184         {
1185             rStr = pObj->getSpecialDragComment(DragStat());
1186         }
1187     }
1188 }
1189 
1190 bool SdrDragObjOwn::BeginSdrDrag()
1191 {
1192     if(!mpClone)
1193     {
1194         const SdrObject* pObj = GetDragObj();
1195 
1196         if(pObj && !pObj->IsResizeProtect())
1197         {
1198             if(pObj->beginSpecialDrag(DragStat()))
1199             {
1200                 // create nitial clone to have a start visualisation
1201                 mpClone = pObj->getFullDragClone();
1202                 mpClone->applySpecialDrag(DragStat());
1203 
1204                 return true;
1205             }
1206         }
1207     }
1208 
1209     return false;
1210 }
1211 
1212 void SdrDragObjOwn::MoveSdrDrag(const Point& rNoSnapPnt)
1213 {
1214     const SdrObject* pObj = GetDragObj();
1215 
1216     if(pObj)
1217     {
1218         Point aPnt(rNoSnapPnt);
1219         SdrPageView* pPV = GetDragPV();
1220 
1221         if(pPV)
1222         {
1223             if(!DragStat().IsNoSnap())
1224             {
1225                 SnapPos(aPnt);
1226             }
1227 
1228             if(getSdrDragView().IsOrtho())
1229             {
1230                 if (DragStat().IsOrtho8Possible())
1231                 {
1232                     OrthoDistance8(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho());
1233                 }
1234                 else if (DragStat().IsOrtho4Possible())
1235                 {
1236                     OrthoDistance4(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho());
1237                 }
1238             }
1239 
1240             if(DragStat().CheckMinMoved(rNoSnapPnt))
1241             {
1242                 if(aPnt != DragStat().GetNow())
1243                 {
1244                     Hide();
1245                     DragStat().NextMove(aPnt);
1246 
1247                     // since SdrDragObjOwn currently supports no transformation of
1248                     // existing SdrDragEntries but only their recreation, a recreation
1249                     // after every move is needed in this mode. Delete existing
1250                     // SdrDragEntries here  to force their recreation in the following Show().
1251                     clearSdrDragEntries();
1252 
1253                     // delete current clone (after the last reference to it is deleted above)
1254                     if(mpClone)
1255                     {
1256                         SdrObject::Free(mpClone);
1257                         mpClone = 0;
1258                     }
1259 
1260                     // create a new clone and modify to current drag state
1261                     if(!mpClone)
1262                     {
1263                         mpClone = pObj->getFullDragClone();
1264                         mpClone->applySpecialDrag(DragStat());
1265                     }
1266 
1267                     Show();
1268                 }
1269             }
1270         }
1271     }
1272 }
1273 
1274 bool SdrDragObjOwn::EndSdrDrag(bool /*bCopy*/)
1275 {
1276     Hide();
1277     SdrUndoAction* pUndo = NULL;
1278     SdrUndoAction* pUndo2 = NULL;
1279     std::vector< SdrUndoAction* > vConnectorUndoActions;
1280     bool bRet = false;
1281     SdrObject* pObj = GetDragObj();
1282 
1283     if(pObj)
1284     {
1285         const bool bUndo = getSdrDragView().IsUndoEnabled();
1286 
1287         if( bUndo )
1288         {
1289             if(!getSdrDragView().IsInsObjPoint() && pObj->IsInserted() )
1290             {
1291                 if (DragStat().IsEndDragChangesAttributes())
1292                 {
1293                     pUndo=getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj);
1294 
1295                     if (DragStat().IsEndDragChangesGeoAndAttributes())
1296                     {
1297                         vConnectorUndoActions = getSdrDragView().CreateConnectorUndo( *pObj );
1298                         pUndo2 = getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj);
1299                     }
1300                 }
1301                 else
1302                 {
1303                     vConnectorUndoActions = getSdrDragView().CreateConnectorUndo( *pObj );
1304                     pUndo= getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj);
1305                 }
1306             }
1307 
1308             if( pUndo )
1309             {
1310                 getSdrDragView().BegUndo( pUndo->GetComment() );
1311             }
1312             else
1313             {
1314                 getSdrDragView().BegUndo();
1315             }
1316         }
1317 
1318         // evtl. use opertator= for setting changed object data (do not change selection in
1319         // view, this will destroy the interactor). This is possible since a clone is now
1320         // directly modified by the modifiers. Only SdrTableObj is adding own UNDOs
1321         // in it's SdrTableObj::endSpecialDrag, so currently not possible. OTOH it uses
1322         // a CreateUndoGeoObject() so maybe setting SetEndDragChangesAttributes is okay. I
1323         // will test this now
1324         Rectangle aBoundRect0;
1325 
1326         if(pObj->GetUserCall())
1327         {
1328             aBoundRect0 = pObj->GetLastBoundRect();
1329         }
1330 
1331         bRet = pObj->applySpecialDrag(DragStat());
1332 
1333         if(bRet)
1334         {
1335             pObj->SetChanged();
1336             pObj->BroadcastObjectChange();
1337             pObj->SendUserCall( SDRUSERCALL_RESIZE, aBoundRect0 );
1338         }
1339 
1340         if(bRet)
1341         {
1342             if( bUndo )
1343             {
1344                 getSdrDragView().AddUndoActions( vConnectorUndoActions );
1345 
1346                 if ( pUndo )
1347                 {
1348                     getSdrDragView().AddUndo(pUndo);
1349                 }
1350 
1351                 if ( pUndo2 )
1352                 {
1353                     getSdrDragView().AddUndo(pUndo2);
1354                 }
1355             }
1356         }
1357         else
1358         {
1359             if( bUndo )
1360             {
1361                 std::vector< SdrUndoAction* >::iterator vConnectorUndoIter( vConnectorUndoActions.begin() );
1362 
1363                 while( vConnectorUndoIter != vConnectorUndoActions.end() )
1364                 {
1365                     delete *vConnectorUndoIter++;
1366                 }
1367 
1368                 delete pUndo;
1369                 delete pUndo2;
1370             }
1371         }
1372 
1373         if( bUndo )
1374             getSdrDragView().EndUndo();
1375     }
1376 
1377     return bRet;
1378 }
1379 
1380 Pointer SdrDragObjOwn::GetSdrDragPointer() const
1381 {
1382     const SdrHdl* pHdl=GetDragHdl();
1383 
1384     if (pHdl)
1385     {
1386         return pHdl->GetPointer();
1387     }
1388 
1389     return Pointer(POINTER_MOVE);
1390 }
1391 
1392 ////////////////////////////////////////////////////////////////////////////////////////////////////
1393 
1394 TYPEINIT1(SdrDragMove,SdrDragMethod);
1395 
1396 void SdrDragMove::createSdrDragEntryForSdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact, bool /*bModify*/)
1397 {
1398     // for SdrDragMove, use current Primitive2DSequence of SdrObject visualisation
1399     // in given ObjectContact directly
1400     sdr::contact::ViewContact& rVC = rOriginal.GetViewContact();
1401     sdr::contact::ViewObjectContact& rVOC = rVC.GetViewObjectContact(rObjectContact);
1402     sdr::contact::DisplayInfo aDisplayInfo;
1403 
1404     // Do not use the last ViewPort set at the OC from the last ProcessDisplay(),
1405     // here we want the complete primitive sequence without visibility clippings
1406     rObjectContact.resetViewPort();
1407 
1408     addSdrDragEntry(new SdrDragEntryPrimitive2DSequence(rVOC.getPrimitive2DSequenceHierarchy(aDisplayInfo), true));
1409 }
1410 
1411 void SdrDragMove::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
1412 {
1413     rTarget.Move(Size(DragStat().GetDX(), DragStat().GetDY()));
1414 }
1415 
1416 SdrDragMove::SdrDragMove(SdrDragView& rNewView)
1417 :   SdrDragMethod(rNewView)
1418 {
1419     setMoveOnly(true);
1420 }
1421 
1422 void SdrDragMove::TakeSdrDragComment(XubString& rStr) const
1423 {
1424     XubString aStr;
1425 
1426     ImpTakeDescriptionStr(STR_DragMethMove, rStr);
1427     rStr.AppendAscii(" (x=");
1428     getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDX(), aStr);
1429     rStr += aStr;
1430     rStr.AppendAscii(" y=");
1431     getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDY(), aStr);
1432     rStr += aStr;
1433     rStr += sal_Unicode(')');
1434 
1435     if(getSdrDragView().IsDragWithCopy())
1436     {
1437         if(!getSdrDragView().IsInsObjPoint() && !getSdrDragView().IsInsGluePoint())
1438         {
1439             rStr += ImpGetResStr(STR_EditWithCopy);
1440         }
1441     }
1442 }
1443 
1444 bool SdrDragMove::BeginSdrDrag()
1445 {
1446     DragStat().SetActionRect(GetMarkedRect());
1447     Show();
1448 
1449     return true;
1450 }
1451 
1452 basegfx::B2DHomMatrix SdrDragMove::getCurrentTransformation()
1453 {
1454     return basegfx::tools::createTranslateB2DHomMatrix(DragStat().GetDX(), DragStat().GetDY());
1455 }
1456 
1457 void SdrDragMove::ImpCheckSnap(const Point& rPt)
1458 {
1459     Point aPt(rPt);
1460     sal_uInt16 nRet=SnapPos(aPt);
1461     aPt-=rPt;
1462 
1463     if ((nRet & SDRSNAP_XSNAPPED) !=0)
1464     {
1465         if (bXSnapped)
1466         {
1467             if (Abs(aPt.X())<Abs(nBestXSnap))
1468             {
1469                 nBestXSnap=aPt.X();
1470             }
1471         }
1472         else
1473         {
1474             nBestXSnap=aPt.X();
1475             bXSnapped=true;
1476         }
1477     }
1478 
1479     if ((nRet & SDRSNAP_YSNAPPED) !=0)
1480     {
1481         if (bYSnapped)
1482         {
1483             if (Abs(aPt.Y())<Abs(nBestYSnap))
1484             {
1485                 nBestYSnap=aPt.Y();
1486             }
1487         }
1488         else
1489         {
1490             nBestYSnap=aPt.Y();
1491             bYSnapped=true;
1492         }
1493     }
1494 }
1495 
1496 void SdrDragMove::MoveSdrDrag(const Point& rNoSnapPnt_)
1497 {
1498     nBestXSnap=0;
1499     nBestYSnap=0;
1500     bXSnapped=false;
1501     bYSnapped=false;
1502     Point aNoSnapPnt(rNoSnapPnt_);
1503     const Rectangle& aSR=GetMarkedRect();
1504     long nMovedx=aNoSnapPnt.X()-DragStat().GetStart().X();
1505     long nMovedy=aNoSnapPnt.Y()-DragStat().GetStart().Y();
1506     Point aLO(aSR.TopLeft());      aLO.X()+=nMovedx; aLO.Y()+=nMovedy;
1507     Point aRU(aSR.BottomRight());  aRU.X()+=nMovedx; aRU.Y()+=nMovedy;
1508     Point aLU(aLO.X(),aRU.Y());
1509     Point aRO(aRU.X(),aLO.Y());
1510     ImpCheckSnap(aLO);
1511 
1512     if (!getSdrDragView().IsMoveSnapOnlyTopLeft())
1513     {
1514         ImpCheckSnap(aRO);
1515         ImpCheckSnap(aLU);
1516         ImpCheckSnap(aRU);
1517     }
1518 
1519     Point aPnt(aNoSnapPnt.X()+nBestXSnap,aNoSnapPnt.Y()+nBestYSnap);
1520     bool bOrtho=getSdrDragView().IsOrtho();
1521 
1522     if (bOrtho)
1523         OrthoDistance8(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho());
1524 
1525     if (DragStat().CheckMinMoved(aNoSnapPnt))
1526     {
1527         Point aPt1(aPnt);
1528         Rectangle aLR(getSdrDragView().GetWorkArea());
1529         bool bWorkArea=!aLR.IsEmpty();
1530         bool bDragLimit=IsDragLimit();
1531 
1532         if (bDragLimit || bWorkArea)
1533         {
1534             Rectangle aSR2(GetMarkedRect());
1535             Point aD(aPt1-DragStat().GetStart());
1536 
1537             if (bDragLimit)
1538             {
1539                 Rectangle aR2(GetDragLimitRect());
1540 
1541                 if (bWorkArea)
1542                     aLR.Intersection(aR2);
1543                 else
1544                     aLR=aR2;
1545             }
1546 
1547             if (aSR2.Left()>aLR.Left() || aSR2.Right()<aLR.Right())
1548             { // ist ueberhaupt Platz zum verschieben?
1549                 aSR2.Move(aD.X(),0);
1550 
1551                 if (aSR2.Left()<aLR.Left())
1552                 {
1553                     aPt1.X()-=aSR2.Left()-aLR.Left();
1554                 }
1555                 else if (aSR2.Right()>aLR.Right())
1556                 {
1557                     aPt1.X()-=aSR2.Right()-aLR.Right();
1558                 }
1559             }
1560             else
1561                 aPt1.X()=DragStat().GetStart().X(); // kein Platz zum verschieben
1562 
1563             if (aSR2.Top()>aLR.Top() || aSR2.Bottom()<aLR.Bottom())
1564             { // ist ueberhaupt Platz zum verschieben?
1565                 aSR2.Move(0,aD.Y());
1566 
1567                 if (aSR2.Top()<aLR.Top())
1568                 {
1569                     aPt1.Y()-=aSR2.Top()-aLR.Top();
1570                 }
1571                 else if (aSR2.Bottom()>aLR.Bottom())
1572                 {
1573                     aPt1.Y()-=aSR2.Bottom()-aLR.Bottom();
1574                 }
1575             }
1576             else
1577                 aPt1.Y()=DragStat().GetStart().Y(); // kein Platz zum verschieben
1578         }
1579 
1580         if (getSdrDragView().IsDraggingGluePoints())
1581         { // Klebepunkte aufs BoundRect des Obj limitieren
1582             aPt1-=DragStat().GetStart();
1583             const SdrMarkList& rML=GetMarkedObjectList();
1584             sal_uLong nMarkAnz=rML.GetMarkCount();
1585 
1586             for (sal_uLong nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++)
1587             {
1588                 const SdrMark* pM=rML.GetMark(nMarkNum);
1589                 const SdrUShortCont* pPts=pM->GetMarkedGluePoints();
1590                 sal_uLong nPtAnz=pPts==NULL ? 0 : pPts->GetCount();
1591 
1592                 if (nPtAnz!=0)
1593                 {
1594                     const SdrObject* pObj=pM->GetMarkedSdrObj();
1595                     const SdrGluePointList* pGPL=pObj->GetGluePointList();
1596                     Rectangle aBound(pObj->GetCurrentBoundRect());
1597 
1598                     for (sal_uLong nPtNum=0; nPtNum<nPtAnz; nPtNum++)
1599                     {
1600                         sal_uInt16 nId=pPts->GetObject(nPtNum);
1601                         sal_uInt16 nGlueNum=pGPL->FindGluePoint(nId);
1602 
1603                         if (nGlueNum!=SDRGLUEPOINT_NOTFOUND)
1604                         {
1605                             Point aPt((*pGPL)[nGlueNum].GetAbsolutePos(*pObj));
1606                             aPt+=aPt1; // soviel soll verschoben werden
1607                             if (aPt.X()<aBound.Left()  ) aPt1.X()-=aPt.X()-aBound.Left()  ;
1608                             if (aPt.X()>aBound.Right() ) aPt1.X()-=aPt.X()-aBound.Right() ;
1609                             if (aPt.Y()<aBound.Top()   ) aPt1.Y()-=aPt.Y()-aBound.Top()   ;
1610                             if (aPt.Y()>aBound.Bottom()) aPt1.Y()-=aPt.Y()-aBound.Bottom();
1611                         }
1612                     }
1613                 }
1614             }
1615 
1616             aPt1+=DragStat().GetStart();
1617         }
1618 
1619         if (bOrtho)
1620             OrthoDistance8(DragStat().GetStart(),aPt1,false);
1621 
1622         if (aPt1!=DragStat().GetNow())
1623         {
1624             Hide();
1625             DragStat().NextMove(aPt1);
1626             Rectangle aAction(GetMarkedRect());
1627             aAction.Move(DragStat().GetDX(),DragStat().GetDY());
1628             DragStat().SetActionRect(aAction);
1629             Show();
1630         }
1631     }
1632 }
1633 
1634 bool SdrDragMove::EndSdrDrag(bool bCopy)
1635 {
1636     Hide();
1637 
1638     if (getSdrDragView().IsInsObjPoint() || getSdrDragView().IsInsGluePoint())
1639         bCopy=false;
1640 
1641     if (IsDraggingPoints())
1642     {
1643         getSdrDragView().MoveMarkedPoints(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy);
1644     }
1645     else if (IsDraggingGluePoints())
1646     {
1647         getSdrDragView().MoveMarkedGluePoints(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy);
1648     }
1649     else
1650     {
1651         getSdrDragView().MoveMarkedObj(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy);
1652     }
1653 
1654     return true;
1655 }
1656 
1657 Pointer SdrDragMove::GetSdrDragPointer() const
1658 {
1659     if (IsDraggingPoints() || IsDraggingGluePoints())
1660     {
1661         return Pointer(POINTER_MOVEPOINT);
1662     }
1663     else
1664     {
1665         return Pointer(POINTER_MOVE);
1666     }
1667 }
1668 
1669 ////////////////////////////////////////////////////////////////////////////////////////////////////
1670 
1671 TYPEINIT1(SdrDragResize,SdrDragMethod);
1672 
1673 SdrDragResize::SdrDragResize(SdrDragView& rNewView)
1674 :   SdrDragMethod(rNewView),
1675     aXFact(1,1),
1676     aYFact(1,1)
1677 {
1678 }
1679 
1680 void SdrDragResize::TakeSdrDragComment(XubString& rStr) const
1681 {
1682     ImpTakeDescriptionStr(STR_DragMethResize, rStr);
1683     bool bEqual(aXFact == aYFact);
1684     Fraction aFact1(1,1);
1685     Point aStart(DragStat().GetStart());
1686     Point aRef(DragStat().GetRef1());
1687     sal_Int32 nXDiv(aStart.X() - aRef.X());
1688 
1689     if(!nXDiv)
1690         nXDiv = 1;
1691 
1692     sal_Int32 nYDiv(aStart.Y() - aRef.Y());
1693 
1694     if(!nYDiv)
1695         nYDiv = 1;
1696 
1697     bool bX(aXFact != aFact1 && Abs(nXDiv) > 1);
1698     bool bY(aYFact != aFact1 && Abs(nYDiv) > 1);
1699 
1700     if(bX || bY)
1701     {
1702         XubString aStr;
1703 
1704         rStr.AppendAscii(" (");
1705 
1706         if(bX)
1707         {
1708             if(!bEqual)
1709                 rStr.AppendAscii("x=");
1710 
1711             getSdrDragView().GetModel()->TakePercentStr(aXFact, aStr);
1712             rStr += aStr;
1713         }
1714 
1715         if(bY && !bEqual)
1716         {
1717             if(bX)
1718                 rStr += sal_Unicode(' ');
1719 
1720             rStr.AppendAscii("y=");
1721             getSdrDragView().GetModel()->TakePercentStr(aYFact, aStr);
1722             rStr += aStr;
1723         }
1724 
1725         rStr += sal_Unicode(')');
1726     }
1727 
1728     if(getSdrDragView().IsDragWithCopy())
1729         rStr += ImpGetResStr(STR_EditWithCopy);
1730 }
1731 
1732 bool SdrDragResize::BeginSdrDrag()
1733 {
1734     SdrHdlKind eRefHdl=HDL_MOVE;
1735     SdrHdl* pRefHdl=NULL;
1736 
1737     switch (GetDragHdlKind())
1738     {
1739         case HDL_UPLFT: eRefHdl=HDL_LWRGT; break;
1740         case HDL_UPPER: eRefHdl=HDL_LOWER; DragStat().SetHorFixed(true); break;
1741         case HDL_UPRGT: eRefHdl=HDL_LWLFT; break;
1742         case HDL_LEFT : eRefHdl=HDL_RIGHT; DragStat().SetVerFixed(true); break;
1743         case HDL_RIGHT: eRefHdl=HDL_LEFT ; DragStat().SetVerFixed(true); break;
1744         case HDL_LWLFT: eRefHdl=HDL_UPRGT; break;
1745         case HDL_LOWER: eRefHdl=HDL_UPPER; DragStat().SetHorFixed(true); break;
1746         case HDL_LWRGT: eRefHdl=HDL_UPLFT; break;
1747         default: break;
1748     }
1749 
1750     if (eRefHdl!=HDL_MOVE)
1751         pRefHdl=GetHdlList().GetHdl(eRefHdl);
1752 
1753     if (pRefHdl!=NULL && !getSdrDragView().IsResizeAtCenter())
1754     {
1755         DragStat().Ref1()=pRefHdl->GetPos();
1756     }
1757     else
1758     {
1759         SdrHdl* pRef1=GetHdlList().GetHdl(HDL_UPLFT);
1760         SdrHdl* pRef2=GetHdlList().GetHdl(HDL_LWRGT);
1761 
1762         if (pRef1!=NULL && pRef2!=NULL)
1763         {
1764             DragStat().Ref1()=Rectangle(pRef1->GetPos(),pRef2->GetPos()).Center();
1765         }
1766         else
1767         {
1768             DragStat().Ref1()=GetMarkedRect().Center();
1769         }
1770     }
1771 
1772     Show();
1773 
1774     return true;
1775 }
1776 
1777 basegfx::B2DHomMatrix SdrDragResize::getCurrentTransformation()
1778 {
1779     basegfx::B2DHomMatrix aRetval(basegfx::tools::createTranslateB2DHomMatrix(
1780         -DragStat().Ref1().X(), -DragStat().Ref1().Y()));
1781     aRetval.scale(aXFact, aYFact);
1782     aRetval.translate(DragStat().Ref1().X(), DragStat().Ref1().Y());
1783 
1784     return aRetval;
1785 }
1786 
1787 void SdrDragResize::MoveSdrDrag(const Point& rNoSnapPnt)
1788 {
1789     Point aPnt(GetSnapPos(rNoSnapPnt));
1790     Point aStart(DragStat().GetStart());
1791     Point aRef(DragStat().GetRef1());
1792     Fraction aMaxFact(0x7FFFFFFF,1);
1793     Rectangle aLR(getSdrDragView().GetWorkArea());
1794     bool bWorkArea=!aLR.IsEmpty();
1795     bool bDragLimit=IsDragLimit();
1796 
1797     if (bDragLimit || bWorkArea)
1798     {
1799         Rectangle aSR(GetMarkedRect());
1800 
1801         if (bDragLimit)
1802         {
1803             Rectangle aR2(GetDragLimitRect());
1804 
1805             if (bWorkArea)
1806                 aLR.Intersection(aR2);
1807             else
1808                 aLR=aR2;
1809         }
1810 
1811         if (aPnt.X()<aLR.Left())
1812             aPnt.X()=aLR.Left();
1813         else if (aPnt.X()>aLR.Right())
1814             aPnt.X()=aLR.Right();
1815 
1816         if (aPnt.Y()<aLR.Top())
1817             aPnt.Y()=aLR.Top();
1818         else if (aPnt.Y()>aLR.Bottom())
1819             aPnt.Y()=aLR.Bottom();
1820 
1821         if (aRef.X()>aSR.Left())
1822         {
1823             Fraction aMax(aRef.X()-aLR.Left(),aRef.X()-aSR.Left());
1824 
1825             if (aMax<aMaxFact)
1826                 aMaxFact=aMax;
1827         }
1828 
1829         if (aRef.X()<aSR.Right())
1830         {
1831             Fraction aMax(aLR.Right()-aRef.X(),aSR.Right()-aRef.X());
1832 
1833             if (aMax<aMaxFact)
1834                 aMaxFact=aMax;
1835         }
1836 
1837         if (aRef.Y()>aSR.Top())
1838         {
1839             Fraction aMax(aRef.Y()-aLR.Top(),aRef.Y()-aSR.Top());
1840 
1841             if (aMax<aMaxFact)
1842                 aMaxFact=aMax;
1843         }
1844 
1845         if (aRef.Y()<aSR.Bottom())
1846         {
1847             Fraction aMax(aLR.Bottom()-aRef.Y(),aSR.Bottom()-aRef.Y());
1848 
1849             if (aMax<aMaxFact)
1850                 aMaxFact=aMax;
1851         }
1852     }
1853 
1854     long nXDiv=aStart.X()-aRef.X(); if (nXDiv==0) nXDiv=1;
1855     long nYDiv=aStart.Y()-aRef.Y(); if (nYDiv==0) nYDiv=1;
1856     long nXMul=aPnt.X()-aRef.X();
1857     long nYMul=aPnt.Y()-aRef.Y();
1858 
1859     if (nXDiv<0)
1860     {
1861         nXDiv=-nXDiv;
1862         nXMul=-nXMul;
1863     }
1864 
1865     if (nYDiv<0)
1866     {
1867         nYDiv=-nYDiv;
1868         nYMul=-nYMul;
1869     }
1870 
1871     bool bXNeg=nXMul<0; if (bXNeg) nXMul=-nXMul;
1872     bool bYNeg=nYMul<0; if (bYNeg) nYMul=-nYMul;
1873     bool bOrtho=getSdrDragView().IsOrtho() || !getSdrDragView().IsResizeAllowed(false);
1874 
1875     if (!DragStat().IsHorFixed() && !DragStat().IsVerFixed())
1876     {
1877         if (Abs(nXDiv)<=1 || Abs(nYDiv)<=1)
1878             bOrtho=false;
1879 
1880         if (bOrtho)
1881         {
1882             if ((Fraction(nXMul,nXDiv)>Fraction(nYMul,nYDiv)) !=getSdrDragView().IsBigOrtho())
1883             {
1884                 nXMul=nYMul;
1885                 nXDiv=nYDiv;
1886             }
1887             else
1888             {
1889                 nYMul=nXMul;
1890                 nYDiv=nXDiv;
1891             }
1892         }
1893     }
1894     else
1895     {
1896         if (bOrtho)
1897         {
1898             if (DragStat().IsHorFixed())
1899             {
1900                 bXNeg=false;
1901                 nXMul=nYMul;
1902                 nXDiv=nYDiv;
1903             }
1904 
1905             if (DragStat().IsVerFixed())
1906             {
1907                 bYNeg=false;
1908                 nYMul=nXMul;
1909                 nYDiv=nXDiv;
1910             }
1911         }
1912         else
1913         {
1914             if (DragStat().IsHorFixed())
1915             {
1916                 bXNeg=false;
1917                 nXMul=1;
1918                 nXDiv=1;
1919             }
1920 
1921             if (DragStat().IsVerFixed())
1922             {
1923                 bYNeg=false;
1924                 nYMul=1;
1925                 nYDiv=1;
1926             }
1927         }
1928     }
1929 
1930     Fraction aNeuXFact(nXMul,nXDiv);
1931     Fraction aNeuYFact(nYMul,nYDiv);
1932 
1933     if (bOrtho)
1934     {
1935         if (aNeuXFact>aMaxFact)
1936         {
1937             aNeuXFact=aMaxFact;
1938             aNeuYFact=aMaxFact;
1939         }
1940 
1941         if (aNeuYFact>aMaxFact)
1942         {
1943             aNeuXFact=aMaxFact;
1944             aNeuYFact=aMaxFact;
1945         }
1946     }
1947 
1948     if (bXNeg)
1949         aNeuXFact=Fraction(-aNeuXFact.GetNumerator(),aNeuXFact.GetDenominator());
1950 
1951     if (bYNeg)
1952         aNeuYFact=Fraction(-aNeuYFact.GetNumerator(),aNeuYFact.GetDenominator());
1953 
1954     if (DragStat().CheckMinMoved(aPnt))
1955     {
1956         if ((!DragStat().IsHorFixed() && aPnt.X()!=DragStat().GetNow().X()) ||
1957             (!DragStat().IsVerFixed() && aPnt.Y()!=DragStat().GetNow().Y()))
1958         {
1959             Hide();
1960             DragStat().NextMove(aPnt);
1961             aXFact=aNeuXFact;
1962             aYFact=aNeuYFact;
1963             Show();
1964         }
1965     }
1966 }
1967 
1968 void SdrDragResize::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
1969 {
1970     rTarget.Resize(DragStat().Ref1(),aXFact,aYFact);
1971 }
1972 
1973 bool SdrDragResize::EndSdrDrag(bool bCopy)
1974 {
1975     Hide();
1976 
1977     if (IsDraggingPoints())
1978     {
1979         getSdrDragView().ResizeMarkedPoints(DragStat().Ref1(),aXFact,aYFact,bCopy);
1980     }
1981     else if (IsDraggingGluePoints())
1982     {
1983         getSdrDragView().ResizeMarkedGluePoints(DragStat().Ref1(),aXFact,aYFact,bCopy);
1984     }
1985     else
1986     {
1987         getSdrDragView().ResizeMarkedObj(DragStat().Ref1(),aXFact,aYFact,bCopy);
1988     }
1989 
1990     return true;
1991 }
1992 
1993 Pointer SdrDragResize::GetSdrDragPointer() const
1994 {
1995     const SdrHdl* pHdl=GetDragHdl();
1996 
1997     if (pHdl!=NULL)
1998     {
1999         return pHdl->GetPointer();
2000     }
2001 
2002     return Pointer(POINTER_MOVE);
2003 }
2004 
2005 ////////////////////////////////////////////////////////////////////////////////////////////////////
2006 
2007 TYPEINIT1(SdrDragRotate,SdrDragMethod);
2008 
2009 void SdrDragRotate::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
2010 {
2011     rTarget.Rotate(DragStat().GetRef1(), nWink, sin(nWink*nPi180), cos(nWink*nPi180));
2012 }
2013 
2014 SdrDragRotate::SdrDragRotate(SdrDragView& rNewView)
2015 :   SdrDragMethod(rNewView),
2016     nSin(0.0),
2017     nCos(1.0),
2018     nWink0(0),
2019     nWink(0),
2020     bRight(false)
2021 {
2022 }
2023 
2024 void SdrDragRotate::TakeSdrDragComment(XubString& rStr) const
2025 {
2026     ImpTakeDescriptionStr(STR_DragMethRotate, rStr);
2027     rStr.AppendAscii(" (");
2028     XubString aStr;
2029     sal_Int32 nTmpWink(NormAngle360(nWink));
2030 
2031     if(bRight && nWink)
2032     {
2033         nTmpWink -= 36000;
2034     }
2035 
2036     getSdrDragView().GetModel()->TakeWinkStr(nTmpWink, aStr);
2037     rStr += aStr;
2038     rStr += sal_Unicode(')');
2039 
2040     if(getSdrDragView().IsDragWithCopy())
2041         rStr += ImpGetResStr(STR_EditWithCopy);
2042 }
2043 
2044 bool SdrDragRotate::BeginSdrDrag()
2045 {
2046     SdrHdl* pH=GetHdlList().GetHdl(HDL_REF1);
2047 
2048     if (pH!=NULL)
2049     {
2050         Show();
2051         DragStat().Ref1()=pH->GetPos();
2052         nWink0=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
2053         return true;
2054     }
2055     else
2056     {
2057         DBG_ERROR("SdrDragRotate::BeginSdrDrag(): Kein Referenzpunkt-Handle gefunden");
2058         return false;
2059     }
2060 }
2061 
2062 basegfx::B2DHomMatrix SdrDragRotate::getCurrentTransformation()
2063 {
2064     return basegfx::tools::createRotateAroundPoint(
2065         DragStat().GetRef1().X(), DragStat().GetRef1().Y(),
2066         -atan2(nSin, nCos));
2067 }
2068 
2069 void SdrDragRotate::MoveSdrDrag(const Point& rPnt_)
2070 {
2071     Point aPnt(rPnt_);
2072     if (DragStat().CheckMinMoved(aPnt))
2073     {
2074         long nNeuWink=NormAngle360(GetAngle(aPnt-DragStat().GetRef1())-nWink0);
2075         long nSA=0;
2076 
2077         if (getSdrDragView().IsAngleSnapEnabled())
2078             nSA=getSdrDragView().GetSnapAngle();
2079 
2080         if (!getSdrDragView().IsRotateAllowed(false))
2081             nSA=9000;
2082 
2083         if (nSA!=0)
2084         { // Winkelfang
2085             nNeuWink+=nSA/2;
2086             nNeuWink/=nSA;
2087             nNeuWink*=nSA;
2088         }
2089 
2090         nNeuWink=NormAngle180(nNeuWink);
2091 
2092         if (nWink!=nNeuWink)
2093         {
2094             sal_uInt16 nSekt0=GetAngleSector(nWink);
2095             sal_uInt16 nSekt1=GetAngleSector(nNeuWink);
2096 
2097             if (nSekt0==0 && nSekt1==3)
2098                 bRight=true;
2099 
2100             if (nSekt0==3 && nSekt1==0)
2101                 bRight=false;
2102 
2103             nWink=nNeuWink;
2104             double a=nWink*nPi180;
2105             double nSin1=sin(a); // schonmal berechnen, damit mgl. wenig Zeit
2106             double nCos1=cos(a); // zwischen Hide() und Show() vergeht
2107             Hide();
2108             nSin=nSin1;
2109             nCos=nCos1;
2110             DragStat().NextMove(aPnt);
2111             Show();
2112         }
2113     }
2114 }
2115 
2116 bool SdrDragRotate::EndSdrDrag(bool bCopy)
2117 {
2118     Hide();
2119 
2120     if (nWink!=0)
2121     {
2122         if (IsDraggingPoints())
2123         {
2124             getSdrDragView().RotateMarkedPoints(DragStat().GetRef1(),nWink,bCopy);
2125         }
2126         else if (IsDraggingGluePoints())
2127         {
2128             getSdrDragView().RotateMarkedGluePoints(DragStat().GetRef1(),nWink,bCopy);
2129         }
2130         else
2131         {
2132             getSdrDragView().RotateMarkedObj(DragStat().GetRef1(),nWink,bCopy);
2133         }
2134     }
2135     return true;
2136 }
2137 
2138 Pointer SdrDragRotate::GetSdrDragPointer() const
2139 {
2140     return Pointer(POINTER_ROTATE);
2141 }
2142 
2143 ////////////////////////////////////////////////////////////////////////////////////////////////////
2144 
2145 TYPEINIT1(SdrDragShear,SdrDragMethod);
2146 
2147 SdrDragShear::SdrDragShear(SdrDragView& rNewView, bool bSlant1)
2148 :   SdrDragMethod(rNewView),
2149     aFact(1,1),
2150     nWink0(0),
2151     nWink(0),
2152     nTan(0.0),
2153     bVertical(false),
2154     bResize(false),
2155     bUpSideDown(false),
2156     bSlant(bSlant1)
2157 {
2158 }
2159 
2160 void SdrDragShear::TakeSdrDragComment(XubString& rStr) const
2161 {
2162     ImpTakeDescriptionStr(STR_DragMethShear, rStr);
2163     rStr.AppendAscii(" (");
2164 
2165     sal_Int32 nTmpWink(nWink);
2166 
2167     if(bUpSideDown)
2168         nTmpWink += 18000;
2169 
2170     nTmpWink = NormAngle180(nTmpWink);
2171 
2172     XubString aStr;
2173 
2174     getSdrDragView().GetModel()->TakeWinkStr(nTmpWink, aStr);
2175     rStr += aStr;
2176     rStr += sal_Unicode(')');
2177 
2178     if(getSdrDragView().IsDragWithCopy())
2179         rStr += ImpGetResStr(STR_EditWithCopy);
2180 }
2181 
2182 bool SdrDragShear::BeginSdrDrag()
2183 {
2184     SdrHdlKind eRefHdl=HDL_MOVE;
2185     SdrHdl* pRefHdl=NULL;
2186 
2187     switch (GetDragHdlKind())
2188     {
2189         case HDL_UPPER: eRefHdl=HDL_LOWER; break;
2190         case HDL_LOWER: eRefHdl=HDL_UPPER; break;
2191         case HDL_LEFT : eRefHdl=HDL_RIGHT; bVertical=true; break;
2192         case HDL_RIGHT: eRefHdl=HDL_LEFT ; bVertical=true; break;
2193         default: break;
2194     }
2195 
2196     if (eRefHdl!=HDL_MOVE)
2197         pRefHdl=GetHdlList().GetHdl(eRefHdl);
2198 
2199     if (pRefHdl!=NULL)
2200     {
2201         DragStat().Ref1()=pRefHdl->GetPos();
2202         nWink0=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
2203     }
2204     else
2205     {
2206         DBG_ERROR("SdrDragShear::BeginSdrDrag(): Kein Referenzpunkt-Handle fuer Shear gefunden");
2207         return false;
2208     }
2209 
2210     Show();
2211     return true;
2212 }
2213 
2214 basegfx::B2DHomMatrix SdrDragShear::getCurrentTransformation()
2215 {
2216     basegfx::B2DHomMatrix aRetval(basegfx::tools::createTranslateB2DHomMatrix(
2217         -DragStat().GetRef1().X(), -DragStat().GetRef1().Y()));
2218 
2219     if (bResize)
2220     {
2221         if (bVertical)
2222         {
2223             aRetval.scale(aFact, 1.0);
2224             aRetval.shearY(-nTan);
2225         }
2226         else
2227         {
2228             aRetval.scale(1.0, aFact);
2229             aRetval.shearX(-nTan);
2230         }
2231     }
2232 
2233     aRetval.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y());
2234 
2235     return aRetval;
2236 }
2237 
2238 void SdrDragShear::MoveSdrDrag(const Point& rPnt)
2239 {
2240     if (DragStat().CheckMinMoved(rPnt))
2241     {
2242         bResize=!getSdrDragView().IsOrtho();
2243         long nSA=0;
2244 
2245         if (getSdrDragView().IsAngleSnapEnabled())
2246             nSA=getSdrDragView().GetSnapAngle();
2247 
2248         Point aP0(DragStat().GetStart());
2249         Point aPnt(rPnt);
2250         Fraction aNeuFact(1,1);
2251 
2252         // Wenn kein Winkelfang, dann ggf. Rasterfang (ausser bei Slant)
2253         if (nSA==0 && !bSlant)
2254             aPnt=GetSnapPos(aPnt);
2255 
2256         if (!bSlant && !bResize)
2257         { // Shear ohne Resize
2258             if (bVertical)
2259                 aPnt.X()=aP0.X();
2260             else
2261                 aPnt.Y()=aP0.Y();
2262         }
2263 
2264         Point aRef(DragStat().GetRef1());
2265         Point aDif(aPnt-aRef);
2266 
2267         long nNeuWink=0;
2268 
2269         if (bSlant)
2270         {
2271             nNeuWink=NormAngle180(-(GetAngle(aDif)-nWink0));
2272 
2273             if (bVertical)
2274                 nNeuWink=NormAngle180(-nNeuWink);
2275         }
2276         else
2277         {
2278             if (bVertical)
2279                 nNeuWink=NormAngle180(GetAngle(aDif));
2280             else
2281                 nNeuWink=NormAngle180(-(GetAngle(aDif)-9000));
2282 
2283             if (nNeuWink<-9000 || nNeuWink>9000)
2284                 nNeuWink=NormAngle180(nNeuWink+18000);
2285 
2286             if (bResize)
2287             {
2288                 Point aPt2(aPnt);
2289 
2290                 if (nSA!=0)
2291                     aPt2=GetSnapPos(aPnt); // den also in jedem Falle fangen
2292 
2293                 if (bVertical)
2294                 {
2295                     aNeuFact=Fraction(aPt2.X()-aRef.X(),aP0.X()-aRef.X());
2296                 }
2297                 else
2298                 {
2299                     aNeuFact=Fraction(aPt2.Y()-aRef.Y(),aP0.Y()-aRef.Y());
2300                 }
2301             }
2302         }
2303 
2304         bool bNeg=nNeuWink<0;
2305 
2306         if (bNeg)
2307             nNeuWink=-nNeuWink;
2308 
2309         if (nSA!=0)
2310         { // Winkelfang
2311             nNeuWink+=nSA/2;
2312             nNeuWink/=nSA;
2313             nNeuWink*=nSA;
2314         }
2315 
2316         nNeuWink=NormAngle360(nNeuWink);
2317         bUpSideDown=nNeuWink>9000 && nNeuWink<27000;
2318 
2319         if (bSlant)
2320         { // Resize fuer Slant berechnen
2321             // Mit Winkelfang jedoch ohne 89deg Begrenzung
2322             long nTmpWink=nNeuWink;
2323             if (bUpSideDown) nNeuWink-=18000;
2324             if (bNeg) nTmpWink=-nTmpWink;
2325             bResize=true;
2326             double nCos=cos(nTmpWink*nPi180);
2327             aNeuFact=nCos;
2328             Kuerzen(aFact,10); // 3 Dezimalstellen sollten reichen
2329         }
2330 
2331         if (nNeuWink>8900)
2332             nNeuWink=8900;
2333 
2334         if (bNeg)
2335             nNeuWink=-nNeuWink;
2336 
2337         if (nWink!=nNeuWink || aFact!=aNeuFact)
2338         {
2339             nWink=nNeuWink;
2340             aFact=aNeuFact;
2341             double a=nWink*nPi180;
2342             double nTan1=0.0;
2343             nTan1=tan(a); // schonmal berechnen, damit mgl. wenig Zeit zwischen Hide() und Show() vergeht
2344             Hide();
2345             nTan=nTan1;
2346             DragStat().NextMove(rPnt);
2347             Show();
2348         }
2349     }
2350 }
2351 
2352 void SdrDragShear::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
2353 {
2354     if (bResize)
2355     {
2356         if (bVertical)
2357         {
2358             rTarget.Resize(DragStat().GetRef1(),aFact,Fraction(1,1));
2359         }
2360         else
2361         {
2362             rTarget.Resize(DragStat().GetRef1(),Fraction(1,1),aFact);
2363         }
2364     }
2365 
2366     if (nWink!=0)
2367     {
2368         rTarget.Shear(DragStat().GetRef1(),nWink,tan(nWink*nPi180),bVertical);
2369     }
2370 }
2371 
2372 bool SdrDragShear::EndSdrDrag(bool bCopy)
2373 {
2374     Hide();
2375 
2376     if (bResize && aFact==Fraction(1,1))
2377         bResize=false;
2378 
2379     if (nWink!=0 || bResize)
2380     {
2381         if (nWink!=0 && bResize)
2382         {
2383             XubString aStr;
2384             ImpTakeDescriptionStr(STR_EditShear,aStr);
2385 
2386             if (bCopy)
2387                 aStr+=ImpGetResStr(STR_EditWithCopy);
2388 
2389             getSdrDragView().BegUndo(aStr);
2390         }
2391 
2392         if (bResize)
2393         {
2394             if (bVertical)
2395             {
2396                 getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),aFact,Fraction(1,1),bCopy);
2397             }
2398             else
2399             {
2400                 getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),Fraction(1,1),aFact,bCopy);
2401             }
2402 
2403             bCopy=false;
2404         }
2405 
2406         if (nWink!=0)
2407         {
2408             getSdrDragView().ShearMarkedObj(DragStat().GetRef1(),nWink,bVertical,bCopy);
2409         }
2410 
2411         if (nWink!=0 && bResize)
2412             getSdrDragView().EndUndo();
2413 
2414         return true;
2415     }
2416 
2417     return false;
2418 }
2419 
2420 Pointer SdrDragShear::GetSdrDragPointer() const
2421 {
2422     if (bVertical)
2423         return Pointer(POINTER_VSHEAR);
2424     else
2425         return Pointer(POINTER_HSHEAR);
2426 }
2427 
2428 ////////////////////////////////////////////////////////////////////////////////////////////////////
2429 
2430 TYPEINIT1(SdrDragMirror,SdrDragMethod);
2431 
2432 void SdrDragMirror::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
2433 {
2434     if(bMirrored)
2435     {
2436         rTarget.Mirror(DragStat().GetRef1(), DragStat().GetRef2());
2437     }
2438 }
2439 
2440 SdrDragMirror::SdrDragMirror(SdrDragView& rNewView)
2441 :   SdrDragMethod(rNewView),
2442     nWink(0),
2443     bMirrored(false),
2444     bSide0(false)
2445 {
2446 }
2447 
2448 bool SdrDragMirror::ImpCheckSide(const Point& rPnt) const
2449 {
2450     long nWink1=GetAngle(rPnt-DragStat().GetRef1());
2451     nWink1-=nWink;
2452     nWink1=NormAngle360(nWink1);
2453 
2454     return nWink1<18000;
2455 }
2456 
2457 void SdrDragMirror::TakeSdrDragComment(XubString& rStr) const
2458 {
2459     if (aDif.X()==0)
2460         ImpTakeDescriptionStr(STR_DragMethMirrorHori,rStr);
2461     else if (aDif.Y()==0)
2462         ImpTakeDescriptionStr(STR_DragMethMirrorVert,rStr);
2463     else if (Abs(aDif.X())==Abs(aDif.Y()))
2464         ImpTakeDescriptionStr(STR_DragMethMirrorDiag,rStr);
2465     else
2466         ImpTakeDescriptionStr(STR_DragMethMirrorFree,rStr);
2467 
2468     if (getSdrDragView().IsDragWithCopy())
2469         rStr+=ImpGetResStr(STR_EditWithCopy);
2470 }
2471 
2472 bool SdrDragMirror::BeginSdrDrag()
2473 {
2474     SdrHdl* pH1=GetHdlList().GetHdl(HDL_REF1);
2475     SdrHdl* pH2=GetHdlList().GetHdl(HDL_REF2);
2476 
2477     if (pH1!=NULL && pH2!=NULL)
2478     {
2479         DragStat().Ref1()=pH1->GetPos();
2480         DragStat().Ref2()=pH2->GetPos();
2481         Ref1()=pH1->GetPos();
2482         Ref2()=pH2->GetPos();
2483         aDif=pH2->GetPos()-pH1->GetPos();
2484         bool b90=(aDif.X()==0) || aDif.Y()==0;
2485         bool b45=b90 || (Abs(aDif.X())==Abs(aDif.Y()));
2486         nWink=NormAngle360(GetAngle(aDif));
2487 
2488         if (!getSdrDragView().IsMirrorAllowed(false,false) && !b45)
2489             return false; // freier Achsenwinkel nicht erlaubt
2490 
2491         if (!getSdrDragView().IsMirrorAllowed(true,false) && !b90)
2492             return false;  // 45deg auch nicht erlaubt
2493 
2494         bSide0=ImpCheckSide(DragStat().GetStart());
2495         Show();
2496         return true;
2497     }
2498     else
2499     {
2500         DBG_ERROR("SdrDragMirror::BeginSdrDrag(): Spiegelachse nicht gefunden");
2501         return false;
2502     }
2503 }
2504 
2505 basegfx::B2DHomMatrix SdrDragMirror::getCurrentTransformation()
2506 {
2507     basegfx::B2DHomMatrix aRetval;
2508 
2509     if (bMirrored)
2510     {
2511         const double fDeltaX(DragStat().GetRef2().X() - DragStat().GetRef1().X());
2512         const double fDeltaY(DragStat().GetRef2().Y() - DragStat().GetRef1().Y());
2513         const double fRotation(atan2(fDeltaY, fDeltaX));
2514 
2515         aRetval = basegfx::tools::createTranslateB2DHomMatrix(-DragStat().GetRef1().X(), -DragStat().GetRef1().Y());
2516         aRetval.rotate(-fRotation);
2517         aRetval.scale(1.0, -1.0);
2518         aRetval.rotate(fRotation);
2519         aRetval.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y());
2520     }
2521 
2522     return aRetval;
2523 }
2524 
2525 void SdrDragMirror::MoveSdrDrag(const Point& rPnt)
2526 {
2527     if (DragStat().CheckMinMoved(rPnt))
2528     {
2529         bool bNeuSide=ImpCheckSide(rPnt);
2530         bool bNeuMirr=bSide0!=bNeuSide;
2531 
2532         if (bMirrored!=bNeuMirr)
2533         {
2534             Hide();
2535             bMirrored=bNeuMirr;
2536             DragStat().NextMove(rPnt);
2537             Show();
2538         }
2539     }
2540 }
2541 
2542 bool SdrDragMirror::EndSdrDrag(bool bCopy)
2543 {
2544     Hide();
2545 
2546     if (bMirrored)
2547     {
2548         getSdrDragView().MirrorMarkedObj(DragStat().GetRef1(),DragStat().GetRef2(),bCopy);
2549     }
2550 
2551     return true;
2552 }
2553 
2554 Pointer SdrDragMirror::GetSdrDragPointer() const
2555 {
2556     return Pointer(POINTER_MIRROR);
2557 }
2558 
2559 ////////////////////////////////////////////////////////////////////////////////////////////////////
2560 
2561 TYPEINIT1(SdrDragGradient, SdrDragMethod);
2562 
2563 SdrDragGradient::SdrDragGradient(SdrDragView& rNewView, bool bGrad)
2564 :   SdrDragMethod(rNewView),
2565     pIAOHandle(NULL),
2566     bIsGradient(bGrad)
2567 {
2568 }
2569 
2570 void SdrDragGradient::TakeSdrDragComment(XubString& rStr) const
2571 {
2572     if(IsGradient())
2573         ImpTakeDescriptionStr(STR_DragMethGradient, rStr);
2574     else
2575         ImpTakeDescriptionStr(STR_DragMethTransparence, rStr);
2576 }
2577 
2578 bool SdrDragGradient::BeginSdrDrag()
2579 {
2580     bool bRetval(false);
2581 
2582     pIAOHandle = (SdrHdlGradient*)GetHdlList().GetHdl(IsGradient() ? HDL_GRAD : HDL_TRNS);
2583 
2584     if(pIAOHandle)
2585     {
2586         // save old values
2587         DragStat().Ref1() = pIAOHandle->GetPos();
2588         DragStat().Ref2() = pIAOHandle->Get2ndPos();
2589 
2590         // what was hit?
2591         bool bHit(false);
2592         SdrHdlColor* pColHdl = pIAOHandle->GetColorHdl1();
2593 
2594         // init handling flags
2595         pIAOHandle->SetMoveSingleHandle(false);
2596         pIAOHandle->SetMoveFirstHandle(false);
2597 
2598         // test first color handle
2599         if(pColHdl)
2600         {
2601             basegfx::B2DPoint aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2602 
2603             if(pColHdl->getOverlayObjectList().isHitLogic(aPosition))
2604             {
2605                 bHit = true;
2606                 pIAOHandle->SetMoveSingleHandle(true);
2607                 pIAOHandle->SetMoveFirstHandle(true);
2608             }
2609         }
2610 
2611         // test second color handle
2612         pColHdl = pIAOHandle->GetColorHdl2();
2613 
2614         if(!bHit && pColHdl)
2615         {
2616             basegfx::B2DPoint aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2617 
2618             if(pColHdl->getOverlayObjectList().isHitLogic(aPosition))
2619             {
2620                 bHit = true;
2621                 pIAOHandle->SetMoveSingleHandle(true);
2622             }
2623         }
2624 
2625         // test gradient handle itself
2626         if(!bHit)
2627         {
2628             basegfx::B2DPoint aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2629 
2630             if(pIAOHandle->getOverlayObjectList().isHitLogic(aPosition))
2631             {
2632                 bHit = true;
2633             }
2634         }
2635 
2636         // everything up and running :o}
2637         bRetval = bHit;
2638     }
2639     else
2640     {
2641         DBG_ERROR("SdrDragGradient::BeginSdrDrag(): IAOGradient nicht gefunden");
2642     }
2643 
2644     return bRetval;
2645 }
2646 
2647 void SdrDragGradient::MoveSdrDrag(const Point& rPnt)
2648 {
2649     if(pIAOHandle && DragStat().CheckMinMoved(rPnt))
2650     {
2651         DragStat().NextMove(rPnt);
2652 
2653         // Do the Move here!!! DragStat().GetStart()
2654         Point aMoveDiff = rPnt - DragStat().GetStart();
2655 
2656         if(pIAOHandle->IsMoveSingleHandle())
2657         {
2658             if(pIAOHandle->IsMoveFirstHandle())
2659             {
2660                 pIAOHandle->SetPos(DragStat().Ref1() + aMoveDiff);
2661                 if(pIAOHandle->GetColorHdl1())
2662                     pIAOHandle->GetColorHdl1()->SetPos(DragStat().Ref1() + aMoveDiff);
2663             }
2664             else
2665             {
2666                 pIAOHandle->Set2ndPos(DragStat().Ref2() + aMoveDiff);
2667                 if(pIAOHandle->GetColorHdl2())
2668                     pIAOHandle->GetColorHdl2()->SetPos(DragStat().Ref2() + aMoveDiff);
2669             }
2670         }
2671         else
2672         {
2673             pIAOHandle->SetPos(DragStat().Ref1() + aMoveDiff);
2674             pIAOHandle->Set2ndPos(DragStat().Ref2() + aMoveDiff);
2675 
2676             if(pIAOHandle->GetColorHdl1())
2677                 pIAOHandle->GetColorHdl1()->SetPos(DragStat().Ref1() + aMoveDiff);
2678 
2679             if(pIAOHandle->GetColorHdl2())
2680                 pIAOHandle->GetColorHdl2()->SetPos(DragStat().Ref2() + aMoveDiff);
2681         }
2682 
2683         // new state
2684         pIAOHandle->FromIAOToItem(getSdrDragView().GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(), false, false);
2685     }
2686 }
2687 
2688 bool SdrDragGradient::EndSdrDrag(bool /*bCopy*/)
2689 {
2690     // here the result is clear, do something with the values
2691     Ref1() = pIAOHandle->GetPos();
2692     Ref2() = pIAOHandle->Get2ndPos();
2693 
2694     // new state
2695     pIAOHandle->FromIAOToItem(getSdrDragView().GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(), true, true);
2696 
2697     return true;
2698 }
2699 
2700 void SdrDragGradient::CancelSdrDrag()
2701 {
2702     // restore old values
2703     pIAOHandle->SetPos(DragStat().Ref1());
2704     pIAOHandle->Set2ndPos(DragStat().Ref2());
2705 
2706     if(pIAOHandle->GetColorHdl1())
2707         pIAOHandle->GetColorHdl1()->SetPos(DragStat().Ref1());
2708 
2709     if(pIAOHandle->GetColorHdl2())
2710         pIAOHandle->GetColorHdl2()->SetPos(DragStat().Ref2());
2711 
2712     // new state
2713     pIAOHandle->FromIAOToItem(getSdrDragView().GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(), true, false);
2714 }
2715 
2716 Pointer SdrDragGradient::GetSdrDragPointer() const
2717 {
2718     return Pointer(POINTER_REFHAND);
2719 }
2720 
2721 ////////////////////////////////////////////////////////////////////////////////////////////////////
2722 
2723 TYPEINIT1(SdrDragCrook,SdrDragMethod);
2724 
2725 SdrDragCrook::SdrDragCrook(SdrDragView& rNewView)
2726 :   SdrDragMethod(rNewView),
2727     aFact(1,1),
2728     bContortionAllowed(false),
2729     bNoContortionAllowed(false),
2730     bContortion(false),
2731     bResizeAllowed(false),
2732     bResize(false),
2733     bRotateAllowed(false),
2734     bRotate(false),
2735     bVertical(false),
2736     bValid(false),
2737     bLft(false),
2738     bRgt(false),
2739     bUpr(false),
2740     bLwr(false),
2741     bAtCenter(false),
2742     nWink(0),
2743     nMarkSize(0),
2744     eMode(SDRCROOK_ROTATE)
2745 {
2746 }
2747 
2748 void SdrDragCrook::TakeSdrDragComment(XubString& rStr) const
2749 {
2750     ImpTakeDescriptionStr(!bContortion ? STR_DragMethCrook : STR_DragMethCrookContortion, rStr);
2751 
2752     if(bValid)
2753     {
2754         rStr.AppendAscii(" (");
2755 
2756         XubString aStr;
2757         sal_Int32 nVal(nWink);
2758 
2759         if(bAtCenter)
2760             nVal *= 2;
2761 
2762         nVal = Abs(nVal);
2763         getSdrDragView().GetModel()->TakeWinkStr(nVal, aStr);
2764         rStr += aStr;
2765         rStr += sal_Unicode(')');
2766     }
2767 
2768     if(getSdrDragView().IsDragWithCopy())
2769         rStr += ImpGetResStr(STR_EditWithCopy);
2770 }
2771 
2772 // #96920# These defines parametrise the created raster
2773 // for interactions
2774 #define DRAG_CROOK_RASTER_MINIMUM   (4)
2775 #define DRAG_CROOK_RASTER_MAXIMUM   (15)
2776 #define DRAG_CROOK_RASTER_DISTANCE  (30)
2777 
2778 basegfx::B2DPolyPolygon impCreateDragRaster(SdrPageView& rPageView, const Rectangle& rMarkRect)
2779 {
2780     basegfx::B2DPolyPolygon aRetval;
2781 
2782     if(rPageView.PageWindowCount())
2783     {
2784         OutputDevice& rOut = (rPageView.GetPageWindow(0)->GetPaintWindow().GetOutputDevice());
2785         Rectangle aPixelSize = rOut.LogicToPixel(rMarkRect);
2786         sal_uInt32 nHorDiv(aPixelSize.GetWidth() / DRAG_CROOK_RASTER_DISTANCE);
2787         sal_uInt32 nVerDiv(aPixelSize.GetHeight() / DRAG_CROOK_RASTER_DISTANCE);
2788 
2789         if(nHorDiv > DRAG_CROOK_RASTER_MAXIMUM)
2790             nHorDiv = DRAG_CROOK_RASTER_MAXIMUM;
2791         if(nHorDiv < DRAG_CROOK_RASTER_MINIMUM)
2792             nHorDiv = DRAG_CROOK_RASTER_MINIMUM;
2793 
2794         if(nVerDiv > DRAG_CROOK_RASTER_MAXIMUM)
2795             nVerDiv = DRAG_CROOK_RASTER_MAXIMUM;
2796         if(nVerDiv < DRAG_CROOK_RASTER_MINIMUM)
2797             nVerDiv = DRAG_CROOK_RASTER_MINIMUM;
2798 
2799         const double fXLen(rMarkRect.GetWidth() / (double)nHorDiv);
2800         const double fYLen(rMarkRect.GetHeight() / (double)nVerDiv);
2801         double fYPos(rMarkRect.Top());
2802         sal_uInt32 a, b;
2803 
2804         for(a = 0; a <= nVerDiv; a++)
2805         {
2806             // hor lines
2807             for(b = 0; b < nHorDiv; b++)
2808             {
2809                 basegfx::B2DPolygon aHorLineSegment;
2810 
2811                 const double fNewX(rMarkRect.Left() + (b * fXLen));
2812                 aHorLineSegment.append(basegfx::B2DPoint(fNewX, fYPos));
2813                 aHorLineSegment.appendBezierSegment(
2814                     basegfx::B2DPoint(fNewX + (fXLen * (1.0 / 3.0)), fYPos),
2815                     basegfx::B2DPoint(fNewX + (fXLen * (2.0 / 3.0)), fYPos),
2816                     basegfx::B2DPoint(fNewX + fXLen, fYPos));
2817                 aRetval.append(aHorLineSegment);
2818             }
2819 
2820             // increments
2821             fYPos += fYLen;
2822         }
2823 
2824         double fXPos(rMarkRect.Left());
2825 
2826         for(a = 0; a <= nHorDiv; a++)
2827         {
2828             // ver lines
2829             for(b = 0; b < nVerDiv; b++)
2830             {
2831                 basegfx::B2DPolygon aVerLineSegment;
2832 
2833                 const double fNewY(rMarkRect.Top() + (b * fYLen));
2834                 aVerLineSegment.append(basegfx::B2DPoint(fXPos, fNewY));
2835                 aVerLineSegment.appendBezierSegment(
2836                     basegfx::B2DPoint(fXPos, fNewY + (fYLen * (1.0 / 3.0))),
2837                     basegfx::B2DPoint(fXPos, fNewY + (fYLen * (2.0 / 3.0))),
2838                     basegfx::B2DPoint(fXPos, fNewY + fYLen));
2839                 aRetval.append(aVerLineSegment);
2840             }
2841 
2842             // increments
2843             fXPos += fXLen;
2844         }
2845     }
2846 
2847     return aRetval;
2848 }
2849 
2850 void SdrDragCrook::createSdrDragEntries()
2851 {
2852     // Add extended frame raster first, so it will be behind objects
2853     if(getSdrDragView().GetSdrPageView())
2854     {
2855         const basegfx::B2DPolyPolygon aDragRaster(impCreateDragRaster(*getSdrDragView().GetSdrPageView(), GetMarkedRect()));
2856 
2857         if(aDragRaster.count())
2858         {
2859             addSdrDragEntry(new SdrDragEntryPolyPolygon(aDragRaster));
2860         }
2861     }
2862 
2863     // call parent
2864     SdrDragMethod::createSdrDragEntries();
2865 }
2866 
2867 bool SdrDragCrook::BeginSdrDrag()
2868 {
2869     bContortionAllowed=getSdrDragView().IsCrookAllowed(false);
2870     bNoContortionAllowed=getSdrDragView().IsCrookAllowed(true);
2871     bResizeAllowed=getSdrDragView().IsResizeAllowed(false);
2872     bRotateAllowed=getSdrDragView().IsRotateAllowed(false);
2873 
2874     if (bContortionAllowed || bNoContortionAllowed)
2875     {
2876         bVertical=(GetDragHdlKind()==HDL_LOWER || GetDragHdlKind()==HDL_UPPER);
2877         aMarkRect=GetMarkedRect();
2878         aMarkCenter=aMarkRect.Center();
2879         nMarkSize=bVertical ? (aMarkRect.GetHeight()-1) : (aMarkRect.GetWidth()-1);
2880         aCenter=aMarkCenter;
2881         aStart=DragStat().GetStart();
2882         Show();
2883         return true;
2884     }
2885     else
2886     {
2887         return false;
2888     }
2889 }
2890 
2891 void SdrDragCrook::_MovAllPoints(basegfx::B2DPolyPolygon& rTarget)
2892 {
2893     SdrPageView* pPV = getSdrDragView().GetSdrPageView();
2894 
2895     if(pPV)
2896     {
2897         XPolyPolygon aTempPolyPoly(rTarget);
2898 
2899         if (pPV->HasMarkedObjPageView())
2900         {
2901             sal_uInt16 nPolyAnz=aTempPolyPoly.Count();
2902 
2903             if (!bContortion && !getSdrDragView().IsNoDragXorPolys())
2904             {
2905                 sal_uInt16 n1st=0,nLast=0;
2906                 Point aC(aCenter);
2907 
2908                 while (n1st<nPolyAnz)
2909                 {
2910                     nLast=n1st;
2911                     while (nLast<nPolyAnz && aTempPolyPoly[nLast].GetPointCount()!=0) nLast++;
2912                     Rectangle aBound(aTempPolyPoly[n1st].GetBoundRect());
2913                     sal_uInt16 i;
2914 
2915                     for (i=n1st+1; i<nLast; i++)
2916                     {
2917                         aBound.Union(aTempPolyPoly[n1st].GetBoundRect());
2918                     }
2919 
2920                     Point aCtr0(aBound.Center());
2921                     Point aCtr1(aCtr0);
2922 
2923                     if (bResize)
2924                     {
2925                         Fraction aFact1(1,1);
2926 
2927                         if (bVertical)
2928                         {
2929                             ResizePoint(aCtr1,aC,aFact1,aFact);
2930                         }
2931                         else
2932                         {
2933                             ResizePoint(aCtr1,aC,aFact,aFact1);
2934                         }
2935                     }
2936 
2937                     bool bRotOk=false;
2938                     double nSin=0,nCos=0;
2939 
2940                     if (aRad.X()!=0 && aRad.Y()!=0)
2941                     {
2942                         bRotOk=bRotate;
2943 
2944                         switch (eMode)
2945                         {
2946                             case SDRCROOK_ROTATE : CrookRotateXPoint (aCtr1,NULL,NULL,aC,aRad,nSin,nCos,bVertical);           break;
2947                             case SDRCROOK_SLANT  : CrookSlantXPoint  (aCtr1,NULL,NULL,aC,aRad,nSin,nCos,bVertical);           break;
2948                             case SDRCROOK_STRETCH: CrookStretchXPoint(aCtr1,NULL,NULL,aC,aRad,nSin,nCos,bVertical,aMarkRect); break;
2949                         } // switch
2950                     }
2951 
2952                     aCtr1-=aCtr0;
2953 
2954                     for (i=n1st; i<nLast; i++)
2955                     {
2956                         if (bRotOk)
2957                         {
2958                             RotateXPoly(aTempPolyPoly[i],aCtr0,nSin,nCos);
2959                         }
2960 
2961                         aTempPolyPoly[i].Move(aCtr1.X(),aCtr1.Y());
2962                     }
2963 
2964                     n1st=nLast+1;
2965                 }
2966             }
2967             else
2968             {
2969                 sal_uInt16 i,j;
2970 
2971                 for (j=0; j<nPolyAnz; j++)
2972                 {
2973                     XPolygon& aPol=aTempPolyPoly[j];
2974                     sal_uInt16 nPtAnz=aPol.GetPointCount();
2975                     i=0;
2976 
2977                     while (i<nPtAnz)
2978                     {
2979                         Point* pPnt=&aPol[i];
2980                         Point* pC1=NULL;
2981                         Point* pC2=NULL;
2982 
2983                         if (i+1<nPtAnz && aPol.IsControl(i))
2984                         { // Kontrollpunkt links
2985                             pC1=pPnt;
2986                             i++;
2987                             pPnt=&aPol[i];
2988                         }
2989 
2990                         i++;
2991 
2992                         if (i<nPtAnz && aPol.IsControl(i))
2993                         { // Kontrollpunkt rechts
2994                             pC2=&aPol[i];
2995                             i++;
2996                         }
2997 
2998                         _MovCrookPoint(*pPnt,pC1,pC2);
2999                     }
3000                 }
3001             }
3002         }
3003 
3004         rTarget = aTempPolyPoly.getB2DPolyPolygon();
3005     }
3006 }
3007 
3008 void SdrDragCrook::_MovCrookPoint(Point& rPnt, Point* pC1, Point* pC2)
3009 {
3010     bool bVert=bVertical;
3011     bool bC1=pC1!=NULL;
3012     bool bC2=pC2!=NULL;
3013     Point aC(aCenter);
3014 
3015     if (bResize)
3016     {
3017         Fraction aFact1(1,1);
3018 
3019         if (bVert)
3020         {
3021             ResizePoint(rPnt,aC,aFact1,aFact);
3022 
3023             if (bC1)
3024                 ResizePoint(*pC1,aC,aFact1,aFact);
3025 
3026             if (bC2)
3027                 ResizePoint(*pC2,aC,aFact1,aFact);
3028         }
3029         else
3030         {
3031             ResizePoint(rPnt,aC,aFact,aFact1);
3032 
3033             if (bC1)
3034                 ResizePoint(*pC1,aC,aFact,aFact1);
3035 
3036             if (bC2)
3037                 ResizePoint(*pC2,aC,aFact,aFact1);
3038         }
3039     }
3040 
3041     if (aRad.X()!=0 && aRad.Y()!=0)
3042     {
3043         double nSin,nCos;
3044 
3045         switch (eMode)
3046         {
3047             case SDRCROOK_ROTATE : CrookRotateXPoint (rPnt,pC1,pC2,aC,aRad,nSin,nCos,bVert);           break;
3048             case SDRCROOK_SLANT  : CrookSlantXPoint  (rPnt,pC1,pC2,aC,aRad,nSin,nCos,bVert);           break;
3049             case SDRCROOK_STRETCH: CrookStretchXPoint(rPnt,pC1,pC2,aC,aRad,nSin,nCos,bVert,aMarkRect); break;
3050         } // switch
3051     }
3052 }
3053 
3054 void SdrDragCrook::MoveSdrDrag(const Point& rPnt)
3055 {
3056     if (DragStat().CheckMinMoved(rPnt))
3057     {
3058         Point aPnt(rPnt);
3059         bool bNeuMoveOnly=getSdrDragView().IsMoveOnlyDragging();
3060         bAtCenter=false;
3061         SdrCrookMode eNeuMode=getSdrDragView().GetCrookMode();
3062         bool bNeuContortion=!bNeuMoveOnly && ((bContortionAllowed && !getSdrDragView().IsCrookNoContortion()) || !bNoContortionAllowed);
3063         bResize=!getSdrDragView().IsOrtho() && bResizeAllowed && !bNeuMoveOnly;
3064         bool bNeuRotate=bRotateAllowed && !bNeuContortion && !bNeuMoveOnly && eNeuMode==SDRCROOK_ROTATE;
3065         long nSA=0;
3066 
3067         if (nSA==0)
3068             aPnt=GetSnapPos(aPnt);
3069 
3070         Point aNeuCenter(aMarkCenter.X(),aStart.Y());
3071 
3072         if (bVertical)
3073         {
3074             aNeuCenter.X()=aStart.X();
3075             aNeuCenter.Y()=aMarkCenter.Y();
3076         }
3077 
3078         if (!getSdrDragView().IsCrookAtCenter())
3079         {
3080             switch (GetDragHdlKind())
3081             {
3082                 case HDL_UPLFT: aNeuCenter.X()=aMarkRect.Right();  bLft=true; break;
3083                 case HDL_UPPER: aNeuCenter.Y()=aMarkRect.Bottom(); bUpr=true; break;
3084                 case HDL_UPRGT: aNeuCenter.X()=aMarkRect.Left();   bRgt=true; break;
3085                 case HDL_LEFT : aNeuCenter.X()=aMarkRect.Right();  bLft=true; break;
3086                 case HDL_RIGHT: aNeuCenter.X()=aMarkRect.Left();   bRgt=true; break;
3087                 case HDL_LWLFT: aNeuCenter.X()=aMarkRect.Right();  bLft=true; break;
3088                 case HDL_LOWER: aNeuCenter.Y()=aMarkRect.Top();    bLwr=true; break;
3089                 case HDL_LWRGT: aNeuCenter.X()=aMarkRect.Left();   bRgt=true; break;
3090                 default: bAtCenter=true;
3091             }
3092         }
3093         else
3094             bAtCenter=true;
3095 
3096         Fraction aNeuFact(1,1);
3097         long dx1=aPnt.X()-aNeuCenter.X();
3098         long dy1=aPnt.Y()-aNeuCenter.Y();
3099         bValid=bVertical ? dx1!=0 : dy1!=0;
3100 
3101         if (bValid)
3102         {
3103             if (bVertical)
3104                 bValid=Abs(dx1)*100>Abs(dy1);
3105             else
3106                 bValid=Abs(dy1)*100>Abs(dx1);
3107         }
3108 
3109         long nNeuRad=0;
3110         nWink=0;
3111 
3112         if (bValid)
3113         {
3114             double a=0; // Steigung des Radius
3115             long nPntWink=0;
3116 
3117             if (bVertical)
3118             {
3119                 a=((double)dy1)/((double)dx1); // Steigung des Radius
3120                 nNeuRad=((long)(dy1*a)+dx1) /2;
3121                 aNeuCenter.X()+=nNeuRad;
3122                 nPntWink=GetAngle(aPnt-aNeuCenter);
3123             }
3124             else
3125             {
3126                 a=((double)dx1)/((double)dy1); // Steigung des Radius
3127                 nNeuRad=((long)(dx1*a)+dy1) /2;
3128                 aNeuCenter.Y()+=nNeuRad;
3129                 nPntWink=GetAngle(aPnt-aNeuCenter)-9000;
3130             }
3131 
3132             if (!bAtCenter)
3133             {
3134                 if (nNeuRad<0)
3135                 {
3136                     if (bRgt) nPntWink+=18000;
3137                     if (bLft) nPntWink=18000-nPntWink;
3138                     if (bLwr) nPntWink=-nPntWink;
3139                 }
3140                 else
3141                 {
3142                     if (bRgt) nPntWink=-nPntWink;
3143                     if (bUpr) nPntWink=18000-nPntWink;
3144                     if (bLwr) nPntWink+=18000;
3145                 }
3146 
3147                 nPntWink=NormAngle360(nPntWink);
3148             }
3149             else
3150             {
3151                 if (nNeuRad<0) nPntWink+=18000;
3152                 if (bVertical) nPntWink=18000-nPntWink;
3153                 nPntWink=NormAngle180(nPntWink);
3154                 nPntWink=Abs(nPntWink);
3155             }
3156 
3157             double nUmfang=2*Abs(nNeuRad)*nPi;
3158 
3159             if (bResize)
3160             {
3161                 if (nSA!=0)
3162                 { // Winkelfang
3163                     long nWink0=nPntWink;
3164                     nPntWink+=nSA/2;
3165                     nPntWink/=nSA;
3166                     nPntWink*=nSA;
3167                     BigInt a2(nNeuRad);
3168                     a2*=BigInt(nWink);
3169                     a2/=BigInt(nWink0);
3170                     nNeuRad=long(a2);
3171 
3172                     if (bVertical)
3173                         aNeuCenter.X()=aStart.X()+nNeuRad;
3174                     else
3175                         aNeuCenter.Y()=aStart.Y()+nNeuRad;
3176                 }
3177 
3178                 long nMul=(long)(nUmfang*NormAngle360(nPntWink)/36000);
3179 
3180                 if (bAtCenter)
3181                     nMul*=2;
3182 
3183                 aNeuFact=Fraction(nMul,nMarkSize);
3184                 nWink=nPntWink;
3185             }
3186             else
3187             {
3188                 nWink=(long)((nMarkSize*360/nUmfang)*100)/2;
3189 
3190                 if (nWink==0)
3191                     bValid=false;
3192 
3193                 if (bValid && nSA!=0)
3194                 { // Winkelfang
3195                     long nWink0=nWink;
3196                     nWink+=nSA/2;
3197                     nWink/=nSA;
3198                     nWink*=nSA;
3199                     BigInt a2(nNeuRad);
3200                     a2*=BigInt(nWink);
3201                     a2/=BigInt(nWink0);
3202                     nNeuRad=long(a2);
3203 
3204                     if (bVertical)
3205                         aNeuCenter.X()=aStart.X()+nNeuRad;
3206                     else
3207                         aNeuCenter.Y()=aStart.Y()+nNeuRad;
3208                 }
3209             }
3210         }
3211 
3212         if (nWink==0 || nNeuRad==0)
3213             bValid=false;
3214 
3215         if (!bValid)
3216             nNeuRad=0;
3217 
3218         if (!bValid && bResize)
3219         {
3220             long nMul=bVertical ? dy1 : dx1;
3221 
3222             if (bLft || bUpr)
3223                 nMul=-nMul;
3224 
3225             long nDiv=nMarkSize;
3226 
3227             if (bAtCenter)
3228             {
3229                 nMul*=2;
3230                 nMul=Abs(nMul);
3231             }
3232 
3233             aNeuFact=Fraction(nMul,nDiv);
3234         }
3235 
3236         if (aNeuCenter!=aCenter || bNeuContortion!=bContortion || aNeuFact!=aFact ||
3237             bNeuMoveOnly != getMoveOnly() || bNeuRotate!=bRotate || eNeuMode!=eMode)
3238         {
3239             Hide();
3240             setMoveOnly(bNeuMoveOnly);
3241             bRotate=bNeuRotate;
3242             eMode=eNeuMode;
3243             bContortion=bNeuContortion;
3244             aCenter=aNeuCenter;
3245             aFact=aNeuFact;
3246             aRad=Point(nNeuRad,nNeuRad);
3247             bResize=aFact!=Fraction(1,1) && aFact.GetDenominator()!=0 && aFact.IsValid();
3248             DragStat().NextMove(aPnt);
3249             Show();
3250         }
3251     }
3252 }
3253 
3254 void SdrDragCrook::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
3255 {
3256     const bool bDoResize(aFact!=Fraction(1,1));
3257     const bool bDoCrook(aCenter!=aMarkCenter && aRad.X()!=0 && aRad.Y()!=0);
3258 
3259     if (bDoCrook || bDoResize)
3260     {
3261         if (bDoResize)
3262         {
3263             Fraction aFact1(1,1);
3264 
3265             if (bContortion)
3266             {
3267                 if (bVertical)
3268                 {
3269                     rTarget.Resize(aCenter,aFact1,aFact);
3270                 }
3271                 else
3272                 {
3273                     rTarget.Resize(aCenter,aFact,aFact1);
3274                 }
3275             }
3276             else
3277             {
3278                 Point aCtr0(rTarget.GetSnapRect().Center());
3279                 Point aCtr1(aCtr0);
3280 
3281                 if (bVertical)
3282                 {
3283                     ResizePoint(aCtr1,aCenter,aFact1,aFact);
3284                 }
3285                 else
3286                 {
3287                     ResizePoint(aCtr1,aCenter,aFact,aFact1);
3288                 }
3289 
3290                 Size aSiz(aCtr1.X()-aCtr0.X(),aCtr1.Y()-aCtr0.Y());
3291 
3292                 rTarget.Move(aSiz);
3293             }
3294         }
3295 
3296         if (bDoCrook)
3297         {
3298             const Rectangle aLocalMarkRect(getSdrDragView().GetMarkedObjRect());
3299             const bool bLocalRotate(!bContortion && eMode == SDRCROOK_ROTATE && getSdrDragView().IsRotateAllowed(false));
3300 
3301             getSdrDragView().ImpCrookObj(&rTarget,aCenter,aRad,eMode,bVertical,!bContortion,bLocalRotate,aLocalMarkRect);
3302         }
3303     }
3304 }
3305 
3306 void SdrDragCrook::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon& rTarget)
3307 {
3308     // use helper derived from old stuff
3309     _MovAllPoints(rTarget);
3310 }
3311 
3312 bool SdrDragCrook::EndSdrDrag(bool bCopy)
3313 {
3314     Hide();
3315 
3316     if (bResize && aFact==Fraction(1,1))
3317         bResize=false;
3318 
3319     const bool bUndo = getSdrDragView().IsUndoEnabled();
3320 
3321     bool bDoCrook=aCenter!=aMarkCenter && aRad.X()!=0 && aRad.Y()!=0;
3322 
3323     if (bDoCrook || bResize)
3324     {
3325         if (bResize && bUndo)
3326         {
3327             XubString aStr;
3328             ImpTakeDescriptionStr(!bContortion?STR_EditCrook:STR_EditCrookContortion,aStr);
3329 
3330             if (bCopy)
3331                 aStr+=ImpGetResStr(STR_EditWithCopy);
3332 
3333             getSdrDragView().BegUndo(aStr);
3334         }
3335 
3336         if (bResize)
3337         {
3338             Fraction aFact1(1,1);
3339 
3340             if (bContortion)
3341             {
3342                 if (bVertical)
3343                     getSdrDragView().ResizeMarkedObj(aCenter,aFact1,aFact,bCopy);
3344                 else
3345                     getSdrDragView().ResizeMarkedObj(aCenter,aFact,aFact1,bCopy);
3346             }
3347             else
3348             {
3349                 if (bCopy)
3350                     getSdrDragView().CopyMarkedObj();
3351 
3352                 sal_uLong nMarkAnz=getSdrDragView().GetMarkedObjectList().GetMarkCount();
3353 
3354                 for (sal_uLong nm=0; nm<nMarkAnz; nm++)
3355                 {
3356                     SdrMark* pM=getSdrDragView().GetMarkedObjectList().GetMark(nm);
3357                     SdrObject* pO=pM->GetMarkedSdrObj();
3358                     Point aCtr0(pO->GetSnapRect().Center());
3359                     Point aCtr1(aCtr0);
3360 
3361                     if (bVertical)
3362                         ResizePoint(aCtr1,aCenter,aFact1,aFact);
3363                     else
3364                         ResizePoint(aCtr1,aCenter,aFact,aFact1);
3365 
3366                     Size aSiz(aCtr1.X()-aCtr0.X(),aCtr1.Y()-aCtr0.Y());
3367                     if( bUndo )
3368                         AddUndo(getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pO,aSiz));
3369                     pO->Move(aSiz);
3370                 }
3371             }
3372 
3373             bCopy=false;
3374         }
3375 
3376         if (bDoCrook)
3377         {
3378             getSdrDragView().CrookMarkedObj(aCenter,aRad,eMode,bVertical,!bContortion,bCopy);
3379             getSdrDragView().SetLastCrookCenter(aCenter);
3380         }
3381 
3382         if (bResize && bUndo)
3383             getSdrDragView().EndUndo();
3384 
3385         return true;
3386     }
3387 
3388     return false;
3389 }
3390 
3391 Pointer SdrDragCrook::GetSdrDragPointer() const
3392 {
3393     return Pointer(POINTER_CROOK);
3394 }
3395 
3396 ////////////////////////////////////////////////////////////////////////////////////////////////////
3397 
3398 TYPEINIT1(SdrDragDistort,SdrDragMethod);
3399 
3400 SdrDragDistort::SdrDragDistort(SdrDragView& rNewView)
3401 :   SdrDragMethod(rNewView),
3402     nPolyPt(0),
3403     bContortionAllowed(false),
3404     bNoContortionAllowed(false),
3405     bContortion(false)
3406 {
3407 }
3408 
3409 void SdrDragDistort::TakeSdrDragComment(XubString& rStr) const
3410 {
3411     ImpTakeDescriptionStr(STR_DragMethDistort, rStr);
3412 
3413     XubString aStr;
3414 
3415     rStr.AppendAscii(" (x=");
3416     getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDX(), aStr);
3417     rStr += aStr;
3418     rStr.AppendAscii(" y=");
3419     getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDY(), aStr);
3420     rStr += aStr;
3421     rStr += sal_Unicode(')');
3422 
3423     if(getSdrDragView().IsDragWithCopy())
3424         rStr += ImpGetResStr(STR_EditWithCopy);
3425 }
3426 
3427 void SdrDragDistort::createSdrDragEntries()
3428 {
3429     // Add extended frame raster first, so it will be behind objects
3430     if(getSdrDragView().GetSdrPageView())
3431     {
3432         const basegfx::B2DPolyPolygon aDragRaster(impCreateDragRaster(*getSdrDragView().GetSdrPageView(), GetMarkedRect()));
3433 
3434         if(aDragRaster.count())
3435         {
3436             addSdrDragEntry(new SdrDragEntryPolyPolygon(aDragRaster));
3437         }
3438     }
3439 
3440     // call parent
3441     SdrDragMethod::createSdrDragEntries();
3442 }
3443 
3444 bool SdrDragDistort::BeginSdrDrag()
3445 {
3446     bContortionAllowed=getSdrDragView().IsDistortAllowed(false);
3447     bNoContortionAllowed=getSdrDragView().IsDistortAllowed(true);
3448 
3449     if (bContortionAllowed || bNoContortionAllowed)
3450     {
3451         SdrHdlKind eKind=GetDragHdlKind();
3452         nPolyPt=0xFFFF;
3453 
3454         if (eKind==HDL_UPLFT) nPolyPt=0;
3455         if (eKind==HDL_UPRGT) nPolyPt=1;
3456         if (eKind==HDL_LWRGT) nPolyPt=2;
3457         if (eKind==HDL_LWLFT) nPolyPt=3;
3458         if (nPolyPt>3) return false;
3459 
3460         aMarkRect=GetMarkedRect();
3461         aDistortedRect=XPolygon(aMarkRect);
3462         Show();
3463         return true;
3464     }
3465     else
3466     {
3467         return false;
3468     }
3469 }
3470 
3471 void SdrDragDistort::_MovAllPoints(basegfx::B2DPolyPolygon& rTarget)
3472 {
3473     if (bContortion)
3474     {
3475         SdrPageView* pPV = getSdrDragView().GetSdrPageView();
3476 
3477         if(pPV)
3478         {
3479             if (pPV->HasMarkedObjPageView())
3480             {
3481                 basegfx::B2DPolyPolygon aDragPolygon(rTarget);
3482                 const basegfx::B2DRange aOriginalRange(aMarkRect.Left(), aMarkRect.Top(), aMarkRect.Right(), aMarkRect.Bottom());
3483                 const basegfx::B2DPoint aTopLeft(aDistortedRect[0].X(), aDistortedRect[0].Y());
3484                 const basegfx::B2DPoint aTopRight(aDistortedRect[1].X(), aDistortedRect[1].Y());
3485                 const basegfx::B2DPoint aBottomLeft(aDistortedRect[3].X(), aDistortedRect[3].Y());
3486                 const basegfx::B2DPoint aBottomRight(aDistortedRect[2].X(), aDistortedRect[2].Y());
3487 
3488                 aDragPolygon = basegfx::tools::distort(aDragPolygon, aOriginalRange, aTopLeft, aTopRight, aBottomLeft, aBottomRight);
3489                 rTarget = aDragPolygon;
3490             }
3491         }
3492     }
3493 }
3494 
3495 void SdrDragDistort::MoveSdrDrag(const Point& rPnt)
3496 {
3497     if (DragStat().CheckMinMoved(rPnt))
3498     {
3499         Point aPnt(GetSnapPos(rPnt));
3500 
3501         if (getSdrDragView().IsOrtho())
3502             OrthoDistance8(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho());
3503 
3504         bool bNeuContortion=(bContortionAllowed && !getSdrDragView().IsCrookNoContortion()) || !bNoContortionAllowed;
3505 
3506         if (bNeuContortion!=bContortion || aDistortedRect[nPolyPt]!=aPnt)
3507         {
3508             Hide();
3509             aDistortedRect[nPolyPt]=aPnt;
3510             bContortion=bNeuContortion;
3511             DragStat().NextMove(aPnt);
3512             Show();
3513         }
3514     }
3515 }
3516 
3517 bool SdrDragDistort::EndSdrDrag(bool bCopy)
3518 {
3519     Hide();
3520     bool bDoDistort=DragStat().GetDX()!=0 || DragStat().GetDY()!=0;
3521 
3522     if (bDoDistort)
3523     {
3524         getSdrDragView().DistortMarkedObj(aMarkRect,aDistortedRect,!bContortion,bCopy);
3525         return true;
3526     }
3527 
3528     return false;
3529 }
3530 
3531 Pointer SdrDragDistort::GetSdrDragPointer() const
3532 {
3533     return Pointer(POINTER_REFHAND);
3534 }
3535 
3536 void SdrDragDistort::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
3537 {
3538     const bool bDoDistort(DragStat().GetDX()!=0 || DragStat().GetDY()!=0);
3539 
3540     if (bDoDistort)
3541     {
3542         getSdrDragView().ImpDistortObj(&rTarget, aMarkRect, aDistortedRect, !bContortion);
3543     }
3544 }
3545 
3546 void SdrDragDistort::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon& rTarget)
3547 {
3548     // use helper derived from old stuff
3549     _MovAllPoints(rTarget);
3550 }
3551 
3552 ////////////////////////////////////////////////////////////////////////////////////////////////////
3553 
3554 TYPEINIT1(SdrDragCrop,SdrDragResize);
3555 
3556 SdrDragCrop::SdrDragCrop(SdrDragView& rNewView)
3557 :   SdrDragResize(rNewView)
3558 {
3559     // switch off solid dragging for crop; it just makes no sense since showing
3560     // a 50% transparent object above the original will not be visible
3561     setSolidDraggingActive(false);
3562 }
3563 
3564 void SdrDragCrop::TakeSdrDragComment(XubString& rStr) const
3565 {
3566     ImpTakeDescriptionStr(STR_DragMethCrop, rStr);
3567 
3568     XubString aStr;
3569 
3570     rStr.AppendAscii(" (x=");
3571     getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDX(), aStr);
3572     rStr += aStr;
3573     rStr.AppendAscii(" y=");
3574     getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDY(), aStr);
3575     rStr += aStr;
3576     rStr += sal_Unicode(')');
3577 
3578     if(getSdrDragView().IsDragWithCopy())
3579         rStr += ImpGetResStr(STR_EditWithCopy);
3580 }
3581 
3582 bool SdrDragCrop::EndSdrDrag(bool bCopy)
3583 {
3584     Hide();
3585 
3586     if( DragStat().GetDX()==0 && DragStat().GetDY()==0 )
3587         return false;
3588 
3589     const SdrMarkList& rMarkList = getSdrDragView().GetMarkedObjectList();
3590 
3591     if( rMarkList.GetMarkCount() != 1 )
3592         return false;
3593 
3594     SdrGrafObj* pObj = dynamic_cast<SdrGrafObj*>( rMarkList.GetMark( 0 )->GetMarkedSdrObj() );
3595 
3596     if( !pObj || (pObj->GetGraphicType() == GRAPHIC_NONE) || (pObj->GetGraphicType() == GRAPHIC_DEFAULT) )
3597         return false;
3598 
3599     const GraphicObject& rGraphicObject = pObj->GetGraphicObject();
3600     const MapMode aMapMode100thmm(MAP_100TH_MM);
3601     Size aGraphicSize(rGraphicObject.GetPrefSize());
3602 
3603     if( MAP_PIXEL == rGraphicObject.GetPrefMapMode().GetMapUnit() )
3604         aGraphicSize = Application::GetDefaultDevice()->PixelToLogic( aGraphicSize, aMapMode100thmm );
3605     else
3606         aGraphicSize = Application::GetDefaultDevice()->LogicToLogic( aGraphicSize, rGraphicObject.GetPrefMapMode(), aMapMode100thmm);
3607 
3608     if( aGraphicSize.nA == 0 || aGraphicSize.nB == 0 )
3609         return false;
3610 
3611     const SdrGrafCropItem& rOldCrop = (const SdrGrafCropItem&)pObj->GetMergedItem(SDRATTR_GRAFCROP);
3612 
3613     const bool bUndo = getSdrDragView().IsUndoEnabled();
3614 
3615     if( bUndo )
3616     {
3617         String aUndoStr;
3618         ImpTakeDescriptionStr(STR_DragMethCrop, aUndoStr);
3619 
3620         getSdrDragView().BegUndo( aUndoStr );
3621         getSdrDragView().AddUndo( getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject( *pObj ) );
3622     }
3623 
3624     Rectangle aOldRect( pObj->GetLogicRect() );
3625     getSdrDragView().ResizeMarkedObj(DragStat().Ref1(),aXFact,aYFact,bCopy);
3626     Rectangle aNewRect( pObj->GetLogicRect() );
3627 
3628     double fScaleX = ( aGraphicSize.Width() - rOldCrop.GetLeft() - rOldCrop.GetRight() ) / (double)aOldRect.GetWidth();
3629     double fScaleY = ( aGraphicSize.Height() - rOldCrop.GetTop() - rOldCrop.GetBottom() ) / (double)aOldRect.GetHeight();
3630 
3631     // to correct the never working combination of cropped images and mirroring
3632     // I have to correct the rectangles the calculation is based on here. In the current
3633     // core geometry stuff a vertical mirror is expressed as 180 degree rotation. All
3634     // this can be removed again when aw080 will have cleaned up the old
3635     // (non-)transformation mess in the core.
3636     if(18000 == pObj->GetGeoStat().nDrehWink)
3637     {
3638         // old notation of vertical mirror, need to correct diffs since both rects
3639         // are rotated by 180 degrees
3640         aOldRect = Rectangle(aOldRect.TopLeft() - (aOldRect.BottomRight() - aOldRect.TopLeft()), aOldRect.TopLeft());
3641         aNewRect = Rectangle(aNewRect.TopLeft() - (aNewRect.BottomRight() - aNewRect.TopLeft()), aNewRect.TopLeft());
3642     }
3643 
3644     sal_Int32 nDiffLeft = aNewRect.nLeft - aOldRect.nLeft;
3645     sal_Int32 nDiffTop = aNewRect.nTop - aOldRect.nTop;
3646     sal_Int32 nDiffRight = aNewRect.nRight - aOldRect.nRight;
3647     sal_Int32 nDiffBottom = aNewRect.nBottom - aOldRect.nBottom;
3648 
3649     sal_Int32 nLeftCrop = static_cast<sal_Int32>( rOldCrop.GetLeft() + nDiffLeft * fScaleX );
3650     sal_Int32 nTopCrop = static_cast<sal_Int32>( rOldCrop.GetTop() + nDiffTop * fScaleY );
3651     sal_Int32 nRightCrop = static_cast<sal_Int32>( rOldCrop.GetRight() - nDiffRight * fScaleX );
3652     sal_Int32 nBottomCrop = static_cast<sal_Int32>( rOldCrop.GetBottom() - nDiffBottom * fScaleY );
3653 
3654     SfxItemPool& rPool = getSdrDragView().GetModel()->GetItemPool();
3655     SfxItemSet aSet( rPool, SDRATTR_GRAFCROP, SDRATTR_GRAFCROP );
3656     aSet.Put( SdrGrafCropItem( nLeftCrop, nTopCrop, nRightCrop, nBottomCrop ) );
3657     getSdrDragView().SetAttributes( aSet, false );
3658 
3659     if( bUndo )
3660         getSdrDragView().EndUndo();
3661 
3662     return true;
3663 }
3664 
3665 Pointer SdrDragCrop::GetSdrDragPointer() const
3666 {
3667     return Pointer(POINTER_CROP);
3668 }
3669 
3670 ////////////////////////////////////////////////////////////////////////////////////////////////////
3671 // eof
3672