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