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