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