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