xref: /AOO41X/main/svx/source/svdraw/svddrgmt.cxx (revision 7b6b9ddb4b63a97ea0214b9472b5270bbf674949)
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 
1369                     Show();
1370                 }
1371             }
1372         }
1373     }
1374 }
1375 
1376 bool SdrDragObjOwn::EndSdrDrag(bool /*bCopy*/)
1377 {
1378     Hide();
1379     SdrUndoAction* pUndo = NULL;
1380     SdrUndoAction* pUndo2 = NULL;
1381     std::vector< SdrUndoAction* > vConnectorUndoActions;
1382     bool bRet = false;
1383     SdrObject* pObj = GetDragObj();
1384 
1385     if(pObj)
1386     {
1387         const bool bUndo = getSdrDragView().IsUndoEnabled();
1388 
1389         if( bUndo )
1390         {
1391             if(!getSdrDragView().IsInsObjPoint() && pObj->IsInserted() )
1392             {
1393                 if (DragStat().IsEndDragChangesAttributes())
1394                 {
1395                     pUndo=getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj);
1396 
1397                     if (DragStat().IsEndDragChangesGeoAndAttributes())
1398                     {
1399                         vConnectorUndoActions = getSdrDragView().CreateConnectorUndo( *pObj );
1400                         pUndo2 = getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj);
1401                     }
1402                 }
1403                 else
1404                 {
1405                     vConnectorUndoActions = getSdrDragView().CreateConnectorUndo( *pObj );
1406                     pUndo= getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj);
1407                 }
1408             }
1409 
1410             if( pUndo )
1411             {
1412                 getSdrDragView().BegUndo( pUndo->GetComment() );
1413             }
1414             else
1415             {
1416                 getSdrDragView().BegUndo();
1417             }
1418         }
1419 
1420         // evtl. use opertator= for setting changed object data (do not change selection in
1421         // view, this will destroy the interactor). This is possible since a clone is now
1422         // directly modified by the modifiers. Only SdrTableObj is adding own UNDOs
1423         // in it's SdrTableObj::endSpecialDrag, so currently not possible. OTOH it uses
1424         // a CreateUndoGeoObject() so maybe setting SetEndDragChangesAttributes is okay. I
1425         // will test this now
1426         Rectangle aBoundRect0;
1427 
1428         if(pObj->GetUserCall())
1429         {
1430             aBoundRect0 = pObj->GetLastBoundRect();
1431         }
1432 
1433         bRet = pObj->applySpecialDrag(DragStat());
1434 
1435         if(bRet)
1436         {
1437             pObj->SetChanged();
1438             pObj->BroadcastObjectChange();
1439             pObj->SendUserCall( SDRUSERCALL_RESIZE, aBoundRect0 );
1440         }
1441 
1442         if(bRet)
1443         {
1444             if( bUndo )
1445             {
1446                 getSdrDragView().AddUndoActions( vConnectorUndoActions );
1447 
1448                 if ( pUndo )
1449                 {
1450                     getSdrDragView().AddUndo(pUndo);
1451                 }
1452 
1453                 if ( pUndo2 )
1454                 {
1455                     getSdrDragView().AddUndo(pUndo2);
1456                 }
1457             }
1458         }
1459         else
1460         {
1461             if( bUndo )
1462             {
1463                 std::vector< SdrUndoAction* >::iterator vConnectorUndoIter( vConnectorUndoActions.begin() );
1464 
1465                 while( vConnectorUndoIter != vConnectorUndoActions.end() )
1466                 {
1467                     delete *vConnectorUndoIter++;
1468                 }
1469 
1470                 delete pUndo;
1471                 delete pUndo2;
1472             }
1473         }
1474 
1475         if( bUndo )
1476             getSdrDragView().EndUndo();
1477     }
1478 
1479     return bRet;
1480 }
1481 
1482 Pointer SdrDragObjOwn::GetSdrDragPointer() const
1483 {
1484     const SdrHdl* pHdl=GetDragHdl();
1485 
1486     if (pHdl)
1487     {
1488         return pHdl->GetPointer();
1489     }
1490 
1491     return Pointer(POINTER_MOVE);
1492 }
1493 
1494 ////////////////////////////////////////////////////////////////////////////////////////////////////
1495 
1496 TYPEINIT1(SdrDragMove,SdrDragMethod);
1497 
1498 void SdrDragMove::createSdrDragEntryForSdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact, bool /*bModify*/)
1499 {
1500     // for SdrDragMove, use current Primitive2DSequence of SdrObject visualisation
1501     // in given ObjectContact directly
1502     sdr::contact::ViewContact& rVC = rOriginal.GetViewContact();
1503     sdr::contact::ViewObjectContact& rVOC = rVC.GetViewObjectContact(rObjectContact);
1504     sdr::contact::DisplayInfo aDisplayInfo;
1505 
1506     // Do not use the last ViewPort set at the OC from the last ProcessDisplay(),
1507     // here we want the complete primitive sequence without visibility clippings
1508     rObjectContact.resetViewPort();
1509 
1510     addSdrDragEntry(new SdrDragEntryPrimitive2DSequence(rVOC.getPrimitive2DSequenceHierarchy(aDisplayInfo), true));
1511 }
1512 
1513 void SdrDragMove::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
1514 {
1515     rTarget.Move(Size(DragStat().GetDX(), DragStat().GetDY()));
1516 }
1517 
1518 SdrDragMove::SdrDragMove(SdrDragView& rNewView)
1519 :   SdrDragMethod(rNewView)
1520 {
1521     setMoveOnly(true);
1522 }
1523 
1524 void SdrDragMove::TakeSdrDragComment(XubString& rStr) const
1525 {
1526     XubString aStr;
1527 
1528     ImpTakeDescriptionStr(STR_DragMethMove, rStr);
1529     rStr.AppendAscii(" (x=");
1530     getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDX(), aStr);
1531     rStr += aStr;
1532     rStr.AppendAscii(" y=");
1533     getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDY(), aStr);
1534     rStr += aStr;
1535     rStr += sal_Unicode(')');
1536 
1537     if(getSdrDragView().IsDragWithCopy())
1538     {
1539         if(!getSdrDragView().IsInsObjPoint() && !getSdrDragView().IsInsGluePoint())
1540         {
1541             rStr += ImpGetResStr(STR_EditWithCopy);
1542         }
1543     }
1544 }
1545 
1546 bool SdrDragMove::BeginSdrDrag()
1547 {
1548     DragStat().SetActionRect(GetMarkedRect());
1549     Show();
1550 
1551     return true;
1552 }
1553 
1554 basegfx::B2DHomMatrix SdrDragMove::getCurrentTransformation()
1555 {
1556     return basegfx::tools::createTranslateB2DHomMatrix(DragStat().GetDX(), DragStat().GetDY());
1557 }
1558 
1559 void SdrDragMove::ImpCheckSnap(const Point& rPt)
1560 {
1561     Point aPt(rPt);
1562     sal_uInt16 nRet=SnapPos(aPt);
1563     aPt-=rPt;
1564 
1565     if ((nRet & SDRSNAP_XSNAPPED) !=0)
1566     {
1567         if (bXSnapped)
1568         {
1569             if (Abs(aPt.X())<Abs(nBestXSnap))
1570             {
1571                 nBestXSnap=aPt.X();
1572             }
1573         }
1574         else
1575         {
1576             nBestXSnap=aPt.X();
1577             bXSnapped=true;
1578         }
1579     }
1580 
1581     if ((nRet & SDRSNAP_YSNAPPED) !=0)
1582     {
1583         if (bYSnapped)
1584         {
1585             if (Abs(aPt.Y())<Abs(nBestYSnap))
1586             {
1587                 nBestYSnap=aPt.Y();
1588             }
1589         }
1590         else
1591         {
1592             nBestYSnap=aPt.Y();
1593             bYSnapped=true;
1594         }
1595     }
1596 }
1597 
1598 void SdrDragMove::MoveSdrDrag(const Point& rNoSnapPnt_)
1599 {
1600     nBestXSnap=0;
1601     nBestYSnap=0;
1602     bXSnapped=false;
1603     bYSnapped=false;
1604     Point aNoSnapPnt(rNoSnapPnt_);
1605     const Rectangle& aSR=GetMarkedRect();
1606     long nMovedx=aNoSnapPnt.X()-DragStat().GetStart().X();
1607     long nMovedy=aNoSnapPnt.Y()-DragStat().GetStart().Y();
1608     Point aLO(aSR.TopLeft());      aLO.X()+=nMovedx; aLO.Y()+=nMovedy;
1609     Point aRU(aSR.BottomRight());  aRU.X()+=nMovedx; aRU.Y()+=nMovedy;
1610     Point aLU(aLO.X(),aRU.Y());
1611     Point aRO(aRU.X(),aLO.Y());
1612     ImpCheckSnap(aLO);
1613 
1614     if (!getSdrDragView().IsMoveSnapOnlyTopLeft())
1615     {
1616         ImpCheckSnap(aRO);
1617         ImpCheckSnap(aLU);
1618         ImpCheckSnap(aRU);
1619     }
1620 
1621     Point aPnt(aNoSnapPnt.X()+nBestXSnap,aNoSnapPnt.Y()+nBestYSnap);
1622     bool bOrtho=getSdrDragView().IsOrtho();
1623 
1624     if (bOrtho)
1625         OrthoDistance8(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho());
1626 
1627     if (DragStat().CheckMinMoved(aNoSnapPnt))
1628     {
1629         Point aPt1(aPnt);
1630         Rectangle aLR(getSdrDragView().GetWorkArea());
1631         bool bWorkArea=!aLR.IsEmpty();
1632         bool bDragLimit=IsDragLimit();
1633 
1634         if (bDragLimit || bWorkArea)
1635         {
1636             Rectangle aSR2(GetMarkedRect());
1637             Point aD(aPt1-DragStat().GetStart());
1638 
1639             if (bDragLimit)
1640             {
1641                 Rectangle aR2(GetDragLimitRect());
1642 
1643                 if (bWorkArea)
1644                     aLR.Intersection(aR2);
1645                 else
1646                     aLR=aR2;
1647             }
1648 
1649             if (aSR2.Left()>aLR.Left() || aSR2.Right()<aLR.Right())
1650             { // ist ueberhaupt Platz zum verschieben?
1651                 aSR2.Move(aD.X(),0);
1652 
1653                 if (aSR2.Left()<aLR.Left())
1654                 {
1655                     aPt1.X()-=aSR2.Left()-aLR.Left();
1656                 }
1657                 else if (aSR2.Right()>aLR.Right())
1658                 {
1659                     aPt1.X()-=aSR2.Right()-aLR.Right();
1660                 }
1661             }
1662             else
1663                 aPt1.X()=DragStat().GetStart().X(); // kein Platz zum verschieben
1664 
1665             if (aSR2.Top()>aLR.Top() || aSR2.Bottom()<aLR.Bottom())
1666             { // ist ueberhaupt Platz zum verschieben?
1667                 aSR2.Move(0,aD.Y());
1668 
1669                 if (aSR2.Top()<aLR.Top())
1670                 {
1671                     aPt1.Y()-=aSR2.Top()-aLR.Top();
1672                 }
1673                 else if (aSR2.Bottom()>aLR.Bottom())
1674                 {
1675                     aPt1.Y()-=aSR2.Bottom()-aLR.Bottom();
1676                 }
1677             }
1678             else
1679                 aPt1.Y()=DragStat().GetStart().Y(); // kein Platz zum verschieben
1680         }
1681 
1682         if (getSdrDragView().IsDraggingGluePoints())
1683         { // Klebepunkte aufs BoundRect des Obj limitieren
1684             aPt1-=DragStat().GetStart();
1685             const SdrMarkList& rML=GetMarkedObjectList();
1686             sal_uLong nMarkAnz=rML.GetMarkCount();
1687 
1688             for (sal_uLong nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++)
1689             {
1690                 const SdrMark* pM=rML.GetMark(nMarkNum);
1691                 const SdrUShortCont* pPts=pM->GetMarkedGluePoints();
1692                 sal_uLong nPtAnz=pPts==NULL ? 0 : pPts->GetCount();
1693 
1694                 if (nPtAnz!=0)
1695                 {
1696                     const SdrObject* pObj=pM->GetMarkedSdrObj();
1697                     const SdrGluePointList* pGPL=pObj->GetGluePointList();
1698                     Rectangle aBound(pObj->GetCurrentBoundRect());
1699 
1700                     for (sal_uLong nPtNum=0; nPtNum<nPtAnz; nPtNum++)
1701                     {
1702                         sal_uInt16 nId=pPts->GetObject(nPtNum);
1703                         sal_uInt16 nGlueNum=pGPL->FindGluePoint(nId);
1704 
1705                         if (nGlueNum!=SDRGLUEPOINT_NOTFOUND)
1706                         {
1707                             Point aPt((*pGPL)[nGlueNum].GetAbsolutePos(*pObj));
1708                             aPt+=aPt1; // soviel soll verschoben werden
1709                             if (aPt.X()<aBound.Left()  ) aPt1.X()-=aPt.X()-aBound.Left()  ;
1710                             if (aPt.X()>aBound.Right() ) aPt1.X()-=aPt.X()-aBound.Right() ;
1711                             if (aPt.Y()<aBound.Top()   ) aPt1.Y()-=aPt.Y()-aBound.Top()   ;
1712                             if (aPt.Y()>aBound.Bottom()) aPt1.Y()-=aPt.Y()-aBound.Bottom();
1713                         }
1714                     }
1715                 }
1716             }
1717 
1718             aPt1+=DragStat().GetStart();
1719         }
1720 
1721         if (bOrtho)
1722             OrthoDistance8(DragStat().GetStart(),aPt1,false);
1723 
1724         if (aPt1!=DragStat().GetNow())
1725         {
1726             Hide();
1727             DragStat().NextMove(aPt1);
1728             Rectangle aAction(GetMarkedRect());
1729             aAction.Move(DragStat().GetDX(),DragStat().GetDY());
1730             DragStat().SetActionRect(aAction);
1731             Show();
1732         }
1733     }
1734 }
1735 
1736 bool SdrDragMove::EndSdrDrag(bool bCopy)
1737 {
1738     Hide();
1739 
1740     if (getSdrDragView().IsInsObjPoint() || getSdrDragView().IsInsGluePoint())
1741         bCopy=false;
1742 
1743     if (IsDraggingPoints())
1744     {
1745         getSdrDragView().MoveMarkedPoints(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy);
1746     }
1747     else if (IsDraggingGluePoints())
1748     {
1749         getSdrDragView().MoveMarkedGluePoints(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy);
1750     }
1751     else
1752     {
1753         getSdrDragView().MoveMarkedObj(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy);
1754     }
1755 
1756     return true;
1757 }
1758 
1759 Pointer SdrDragMove::GetSdrDragPointer() const
1760 {
1761     if (IsDraggingPoints() || IsDraggingGluePoints())
1762     {
1763         return Pointer(POINTER_MOVEPOINT);
1764     }
1765     else
1766     {
1767         return Pointer(POINTER_MOVE);
1768     }
1769 }
1770 
1771 ////////////////////////////////////////////////////////////////////////////////////////////////////
1772 
1773 TYPEINIT1(SdrDragResize,SdrDragMethod);
1774 
1775 SdrDragResize::SdrDragResize(SdrDragView& rNewView)
1776 :   SdrDragMethod(rNewView),
1777     aXFact(1,1),
1778     aYFact(1,1)
1779 {
1780 }
1781 
1782 void SdrDragResize::TakeSdrDragComment(XubString& rStr) const
1783 {
1784     ImpTakeDescriptionStr(STR_DragMethResize, rStr);
1785     bool bEqual(aXFact == aYFact);
1786     Fraction aFact1(1,1);
1787     Point aStart(DragStat().GetStart());
1788     Point aRef(DragStat().GetRef1());
1789     sal_Int32 nXDiv(aStart.X() - aRef.X());
1790 
1791     if(!nXDiv)
1792         nXDiv = 1;
1793 
1794     sal_Int32 nYDiv(aStart.Y() - aRef.Y());
1795 
1796     if(!nYDiv)
1797         nYDiv = 1;
1798 
1799     bool bX(aXFact != aFact1 && Abs(nXDiv) > 1);
1800     bool bY(aYFact != aFact1 && Abs(nYDiv) > 1);
1801 
1802     if(bX || bY)
1803     {
1804         XubString aStr;
1805 
1806         rStr.AppendAscii(" (");
1807 
1808         if(bX)
1809         {
1810             if(!bEqual)
1811                 rStr.AppendAscii("x=");
1812 
1813             getSdrDragView().GetModel()->TakePercentStr(aXFact, aStr);
1814             rStr += aStr;
1815         }
1816 
1817         if(bY && !bEqual)
1818         {
1819             if(bX)
1820                 rStr += sal_Unicode(' ');
1821 
1822             rStr.AppendAscii("y=");
1823             getSdrDragView().GetModel()->TakePercentStr(aYFact, aStr);
1824             rStr += aStr;
1825         }
1826 
1827         rStr += sal_Unicode(')');
1828     }
1829 
1830     if(getSdrDragView().IsDragWithCopy())
1831         rStr += ImpGetResStr(STR_EditWithCopy);
1832 }
1833 
1834 bool SdrDragResize::BeginSdrDrag()
1835 {
1836     SdrHdlKind eRefHdl=HDL_MOVE;
1837     SdrHdl* pRefHdl=NULL;
1838 
1839     switch (GetDragHdlKind())
1840     {
1841         case HDL_UPLFT: eRefHdl=HDL_LWRGT; break;
1842         case HDL_UPPER: eRefHdl=HDL_LOWER; DragStat().SetHorFixed(true); break;
1843         case HDL_UPRGT: eRefHdl=HDL_LWLFT; break;
1844         case HDL_LEFT : eRefHdl=HDL_RIGHT; DragStat().SetVerFixed(true); break;
1845         case HDL_RIGHT: eRefHdl=HDL_LEFT ; DragStat().SetVerFixed(true); break;
1846         case HDL_LWLFT: eRefHdl=HDL_UPRGT; break;
1847         case HDL_LOWER: eRefHdl=HDL_UPPER; DragStat().SetHorFixed(true); break;
1848         case HDL_LWRGT: eRefHdl=HDL_UPLFT; break;
1849         default: break;
1850     }
1851 
1852     if (eRefHdl!=HDL_MOVE)
1853         pRefHdl=GetHdlList().GetHdl(eRefHdl);
1854 
1855     if (pRefHdl!=NULL && !getSdrDragView().IsResizeAtCenter())
1856     {
1857         DragStat().Ref1()=pRefHdl->GetPos();
1858     }
1859     else
1860     {
1861         SdrHdl* pRef1=GetHdlList().GetHdl(HDL_UPLFT);
1862         SdrHdl* pRef2=GetHdlList().GetHdl(HDL_LWRGT);
1863 
1864         if (pRef1!=NULL && pRef2!=NULL)
1865         {
1866             DragStat().Ref1()=Rectangle(pRef1->GetPos(),pRef2->GetPos()).Center();
1867         }
1868         else
1869         {
1870             DragStat().Ref1()=GetMarkedRect().Center();
1871         }
1872     }
1873 
1874     Show();
1875 
1876     return true;
1877 }
1878 
1879 basegfx::B2DHomMatrix SdrDragResize::getCurrentTransformation()
1880 {
1881     basegfx::B2DHomMatrix aRetval(basegfx::tools::createTranslateB2DHomMatrix(
1882         -DragStat().Ref1().X(), -DragStat().Ref1().Y()));
1883     aRetval.scale(aXFact, aYFact);
1884     aRetval.translate(DragStat().Ref1().X(), DragStat().Ref1().Y());
1885 
1886     return aRetval;
1887 }
1888 
1889 void SdrDragResize::MoveSdrDrag(const Point& rNoSnapPnt)
1890 {
1891     Point aPnt(GetSnapPos(rNoSnapPnt));
1892     Point aStart(DragStat().GetStart());
1893     Point aRef(DragStat().GetRef1());
1894     Fraction aMaxFact(0x7FFFFFFF,1);
1895     Rectangle aLR(getSdrDragView().GetWorkArea());
1896     bool bWorkArea=!aLR.IsEmpty();
1897     bool bDragLimit=IsDragLimit();
1898 
1899     if (bDragLimit || bWorkArea)
1900     {
1901         Rectangle aSR(GetMarkedRect());
1902 
1903         if (bDragLimit)
1904         {
1905             Rectangle aR2(GetDragLimitRect());
1906 
1907             if (bWorkArea)
1908                 aLR.Intersection(aR2);
1909             else
1910                 aLR=aR2;
1911         }
1912 
1913         if (aPnt.X()<aLR.Left())
1914             aPnt.X()=aLR.Left();
1915         else if (aPnt.X()>aLR.Right())
1916             aPnt.X()=aLR.Right();
1917 
1918         if (aPnt.Y()<aLR.Top())
1919             aPnt.Y()=aLR.Top();
1920         else if (aPnt.Y()>aLR.Bottom())
1921             aPnt.Y()=aLR.Bottom();
1922 
1923         if (aRef.X()>aSR.Left())
1924         {
1925             Fraction aMax(aRef.X()-aLR.Left(),aRef.X()-aSR.Left());
1926 
1927             if (aMax<aMaxFact)
1928                 aMaxFact=aMax;
1929         }
1930 
1931         if (aRef.X()<aSR.Right())
1932         {
1933             Fraction aMax(aLR.Right()-aRef.X(),aSR.Right()-aRef.X());
1934 
1935             if (aMax<aMaxFact)
1936                 aMaxFact=aMax;
1937         }
1938 
1939         if (aRef.Y()>aSR.Top())
1940         {
1941             Fraction aMax(aRef.Y()-aLR.Top(),aRef.Y()-aSR.Top());
1942 
1943             if (aMax<aMaxFact)
1944                 aMaxFact=aMax;
1945         }
1946 
1947         if (aRef.Y()<aSR.Bottom())
1948         {
1949             Fraction aMax(aLR.Bottom()-aRef.Y(),aSR.Bottom()-aRef.Y());
1950 
1951             if (aMax<aMaxFact)
1952                 aMaxFact=aMax;
1953         }
1954     }
1955 
1956     long nXDiv=aStart.X()-aRef.X(); if (nXDiv==0) nXDiv=1;
1957     long nYDiv=aStart.Y()-aRef.Y(); if (nYDiv==0) nYDiv=1;
1958     long nXMul=aPnt.X()-aRef.X();
1959     long nYMul=aPnt.Y()-aRef.Y();
1960 
1961     if (nXDiv<0)
1962     {
1963         nXDiv=-nXDiv;
1964         nXMul=-nXMul;
1965     }
1966 
1967     if (nYDiv<0)
1968     {
1969         nYDiv=-nYDiv;
1970         nYMul=-nYMul;
1971     }
1972 
1973     bool bXNeg=nXMul<0; if (bXNeg) nXMul=-nXMul;
1974     bool bYNeg=nYMul<0; if (bYNeg) nYMul=-nYMul;
1975     bool bOrtho=getSdrDragView().IsOrtho() || !getSdrDragView().IsResizeAllowed(false);
1976 
1977     if (!DragStat().IsHorFixed() && !DragStat().IsVerFixed())
1978     {
1979         if (Abs(nXDiv)<=1 || Abs(nYDiv)<=1)
1980             bOrtho=false;
1981 
1982         if (bOrtho)
1983         {
1984             if ((Fraction(nXMul,nXDiv)>Fraction(nYMul,nYDiv)) !=getSdrDragView().IsBigOrtho())
1985             {
1986                 nXMul=nYMul;
1987                 nXDiv=nYDiv;
1988             }
1989             else
1990             {
1991                 nYMul=nXMul;
1992                 nYDiv=nXDiv;
1993             }
1994         }
1995     }
1996     else
1997     {
1998         if (bOrtho)
1999         {
2000             if (DragStat().IsHorFixed())
2001             {
2002                 bXNeg=false;
2003                 nXMul=nYMul;
2004                 nXDiv=nYDiv;
2005             }
2006 
2007             if (DragStat().IsVerFixed())
2008             {
2009                 bYNeg=false;
2010                 nYMul=nXMul;
2011                 nYDiv=nXDiv;
2012             }
2013         }
2014         else
2015         {
2016             if (DragStat().IsHorFixed())
2017             {
2018                 bXNeg=false;
2019                 nXMul=1;
2020                 nXDiv=1;
2021             }
2022 
2023             if (DragStat().IsVerFixed())
2024             {
2025                 bYNeg=false;
2026                 nYMul=1;
2027                 nYDiv=1;
2028             }
2029         }
2030     }
2031 
2032     Fraction aNeuXFact(nXMul,nXDiv);
2033     Fraction aNeuYFact(nYMul,nYDiv);
2034 
2035     if (bOrtho)
2036     {
2037         if (aNeuXFact>aMaxFact)
2038         {
2039             aNeuXFact=aMaxFact;
2040             aNeuYFact=aMaxFact;
2041         }
2042 
2043         if (aNeuYFact>aMaxFact)
2044         {
2045             aNeuXFact=aMaxFact;
2046             aNeuYFact=aMaxFact;
2047         }
2048     }
2049 
2050     if (bXNeg)
2051         aNeuXFact=Fraction(-aNeuXFact.GetNumerator(),aNeuXFact.GetDenominator());
2052 
2053     if (bYNeg)
2054         aNeuYFact=Fraction(-aNeuYFact.GetNumerator(),aNeuYFact.GetDenominator());
2055 
2056     if (DragStat().CheckMinMoved(aPnt))
2057     {
2058         if ((!DragStat().IsHorFixed() && aPnt.X()!=DragStat().GetNow().X()) ||
2059             (!DragStat().IsVerFixed() && aPnt.Y()!=DragStat().GetNow().Y()))
2060         {
2061             Hide();
2062             DragStat().NextMove(aPnt);
2063             aXFact=aNeuXFact;
2064             aYFact=aNeuYFact;
2065             Show();
2066         }
2067     }
2068 }
2069 
2070 void SdrDragResize::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
2071 {
2072     rTarget.Resize(DragStat().Ref1(),aXFact,aYFact);
2073 }
2074 
2075 bool SdrDragResize::EndSdrDrag(bool bCopy)
2076 {
2077     Hide();
2078 
2079     if (IsDraggingPoints())
2080     {
2081         getSdrDragView().ResizeMarkedPoints(DragStat().Ref1(),aXFact,aYFact,bCopy);
2082     }
2083     else if (IsDraggingGluePoints())
2084     {
2085         getSdrDragView().ResizeMarkedGluePoints(DragStat().Ref1(),aXFact,aYFact,bCopy);
2086     }
2087     else
2088     {
2089         getSdrDragView().ResizeMarkedObj(DragStat().Ref1(),aXFact,aYFact,bCopy);
2090     }
2091 
2092     return true;
2093 }
2094 
2095 Pointer SdrDragResize::GetSdrDragPointer() const
2096 {
2097     const SdrHdl* pHdl=GetDragHdl();
2098 
2099     if (pHdl!=NULL)
2100     {
2101         return pHdl->GetPointer();
2102     }
2103 
2104     return Pointer(POINTER_MOVE);
2105 }
2106 
2107 ////////////////////////////////////////////////////////////////////////////////////////////////////
2108 
2109 TYPEINIT1(SdrDragRotate,SdrDragMethod);
2110 
2111 void SdrDragRotate::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
2112 {
2113     rTarget.Rotate(DragStat().GetRef1(), nWink, sin(nWink*nPi180), cos(nWink*nPi180));
2114 }
2115 
2116 SdrDragRotate::SdrDragRotate(SdrDragView& rNewView)
2117 :   SdrDragMethod(rNewView),
2118     nSin(0.0),
2119     nCos(1.0),
2120     nWink0(0),
2121     nWink(0),
2122     bRight(false)
2123 {
2124 }
2125 
2126 void SdrDragRotate::TakeSdrDragComment(XubString& rStr) const
2127 {
2128     ImpTakeDescriptionStr(STR_DragMethRotate, rStr);
2129     rStr.AppendAscii(" (");
2130     XubString aStr;
2131     sal_Int32 nTmpWink(NormAngle360(nWink));
2132 
2133     if(bRight && nWink)
2134     {
2135         nTmpWink -= 36000;
2136     }
2137 
2138     getSdrDragView().GetModel()->TakeWinkStr(nTmpWink, aStr);
2139     rStr += aStr;
2140     rStr += sal_Unicode(')');
2141 
2142     if(getSdrDragView().IsDragWithCopy())
2143         rStr += ImpGetResStr(STR_EditWithCopy);
2144 }
2145 
2146 bool SdrDragRotate::BeginSdrDrag()
2147 {
2148     SdrHdl* pH=GetHdlList().GetHdl(HDL_REF1);
2149 
2150     if (pH!=NULL)
2151     {
2152         Show();
2153         DragStat().Ref1()=pH->GetPos();
2154         nWink0=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
2155         return true;
2156     }
2157     else
2158     {
2159         DBG_ERROR("SdrDragRotate::BeginSdrDrag(): Kein Referenzpunkt-Handle gefunden");
2160         return false;
2161     }
2162 }
2163 
2164 basegfx::B2DHomMatrix SdrDragRotate::getCurrentTransformation()
2165 {
2166     return basegfx::tools::createRotateAroundPoint(
2167         DragStat().GetRef1().X(), DragStat().GetRef1().Y(),
2168         -atan2(nSin, nCos));
2169 }
2170 
2171 void SdrDragRotate::MoveSdrDrag(const Point& rPnt_)
2172 {
2173     Point aPnt(rPnt_);
2174     if (DragStat().CheckMinMoved(aPnt))
2175     {
2176         long nNeuWink=NormAngle360(GetAngle(aPnt-DragStat().GetRef1())-nWink0);
2177         long nSA=0;
2178 
2179         if (getSdrDragView().IsAngleSnapEnabled())
2180             nSA=getSdrDragView().GetSnapAngle();
2181 
2182         if (!getSdrDragView().IsRotateAllowed(false))
2183             nSA=9000;
2184 
2185         if (nSA!=0)
2186         { // Winkelfang
2187             nNeuWink+=nSA/2;
2188             nNeuWink/=nSA;
2189             nNeuWink*=nSA;
2190         }
2191 
2192         nNeuWink=NormAngle180(nNeuWink);
2193 
2194         if (nWink!=nNeuWink)
2195         {
2196             sal_uInt16 nSekt0=GetAngleSector(nWink);
2197             sal_uInt16 nSekt1=GetAngleSector(nNeuWink);
2198 
2199             if (nSekt0==0 && nSekt1==3)
2200                 bRight=true;
2201 
2202             if (nSekt0==3 && nSekt1==0)
2203                 bRight=false;
2204 
2205             nWink=nNeuWink;
2206             double a=nWink*nPi180;
2207             double nSin1=sin(a); // schonmal berechnen, damit mgl. wenig Zeit
2208             double nCos1=cos(a); // zwischen Hide() und Show() vergeht
2209             Hide();
2210             nSin=nSin1;
2211             nCos=nCos1;
2212             DragStat().NextMove(aPnt);
2213             Show();
2214         }
2215     }
2216 }
2217 
2218 bool SdrDragRotate::EndSdrDrag(bool bCopy)
2219 {
2220     Hide();
2221 
2222     if (nWink!=0)
2223     {
2224         if (IsDraggingPoints())
2225         {
2226             getSdrDragView().RotateMarkedPoints(DragStat().GetRef1(),nWink,bCopy);
2227         }
2228         else if (IsDraggingGluePoints())
2229         {
2230             getSdrDragView().RotateMarkedGluePoints(DragStat().GetRef1(),nWink,bCopy);
2231         }
2232         else
2233         {
2234             getSdrDragView().RotateMarkedObj(DragStat().GetRef1(),nWink,bCopy);
2235         }
2236     }
2237     return true;
2238 }
2239 
2240 Pointer SdrDragRotate::GetSdrDragPointer() const
2241 {
2242     return Pointer(POINTER_ROTATE);
2243 }
2244 
2245 ////////////////////////////////////////////////////////////////////////////////////////////////////
2246 
2247 TYPEINIT1(SdrDragShear,SdrDragMethod);
2248 
2249 SdrDragShear::SdrDragShear(SdrDragView& rNewView, bool bSlant1)
2250 :   SdrDragMethod(rNewView),
2251     aFact(1,1),
2252     nWink0(0),
2253     nWink(0),
2254     nTan(0.0),
2255     bVertical(false),
2256     bResize(false),
2257     bUpSideDown(false),
2258     bSlant(bSlant1)
2259 {
2260 }
2261 
2262 void SdrDragShear::TakeSdrDragComment(XubString& rStr) const
2263 {
2264     ImpTakeDescriptionStr(STR_DragMethShear, rStr);
2265     rStr.AppendAscii(" (");
2266 
2267     sal_Int32 nTmpWink(nWink);
2268 
2269     if(bUpSideDown)
2270         nTmpWink += 18000;
2271 
2272     nTmpWink = NormAngle180(nTmpWink);
2273 
2274     XubString aStr;
2275 
2276     getSdrDragView().GetModel()->TakeWinkStr(nTmpWink, aStr);
2277     rStr += aStr;
2278     rStr += sal_Unicode(')');
2279 
2280     if(getSdrDragView().IsDragWithCopy())
2281         rStr += ImpGetResStr(STR_EditWithCopy);
2282 }
2283 
2284 bool SdrDragShear::BeginSdrDrag()
2285 {
2286     SdrHdlKind eRefHdl=HDL_MOVE;
2287     SdrHdl* pRefHdl=NULL;
2288 
2289     switch (GetDragHdlKind())
2290     {
2291         case HDL_UPPER: eRefHdl=HDL_LOWER; break;
2292         case HDL_LOWER: eRefHdl=HDL_UPPER; break;
2293         case HDL_LEFT : eRefHdl=HDL_RIGHT; bVertical=true; break;
2294         case HDL_RIGHT: eRefHdl=HDL_LEFT ; bVertical=true; break;
2295         default: break;
2296     }
2297 
2298     if (eRefHdl!=HDL_MOVE)
2299         pRefHdl=GetHdlList().GetHdl(eRefHdl);
2300 
2301     if (pRefHdl!=NULL)
2302     {
2303         DragStat().Ref1()=pRefHdl->GetPos();
2304         nWink0=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
2305     }
2306     else
2307     {
2308         DBG_ERROR("SdrDragShear::BeginSdrDrag(): Kein Referenzpunkt-Handle fuer Shear gefunden");
2309         return false;
2310     }
2311 
2312     Show();
2313     return true;
2314 }
2315 
2316 basegfx::B2DHomMatrix SdrDragShear::getCurrentTransformation()
2317 {
2318     basegfx::B2DHomMatrix aRetval(basegfx::tools::createTranslateB2DHomMatrix(
2319         -DragStat().GetRef1().X(), -DragStat().GetRef1().Y()));
2320 
2321     if (bResize)
2322     {
2323         if (bVertical)
2324         {
2325             aRetval.scale(aFact, 1.0);
2326             aRetval.shearY(-nTan);
2327         }
2328         else
2329         {
2330             aRetval.scale(1.0, aFact);
2331             aRetval.shearX(-nTan);
2332         }
2333     }
2334 
2335     aRetval.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y());
2336 
2337     return aRetval;
2338 }
2339 
2340 void SdrDragShear::MoveSdrDrag(const Point& rPnt)
2341 {
2342     if (DragStat().CheckMinMoved(rPnt))
2343     {
2344         bResize=!getSdrDragView().IsOrtho();
2345         long nSA=0;
2346 
2347         if (getSdrDragView().IsAngleSnapEnabled())
2348             nSA=getSdrDragView().GetSnapAngle();
2349 
2350         Point aP0(DragStat().GetStart());
2351         Point aPnt(rPnt);
2352         Fraction aNeuFact(1,1);
2353 
2354         // Wenn kein Winkelfang, dann ggf. Rasterfang (ausser bei Slant)
2355         if (nSA==0 && !bSlant)
2356             aPnt=GetSnapPos(aPnt);
2357 
2358         if (!bSlant && !bResize)
2359         { // Shear ohne Resize
2360             if (bVertical)
2361                 aPnt.X()=aP0.X();
2362             else
2363                 aPnt.Y()=aP0.Y();
2364         }
2365 
2366         Point aRef(DragStat().GetRef1());
2367         Point aDif(aPnt-aRef);
2368 
2369         long nNeuWink=0;
2370 
2371         if (bSlant)
2372         {
2373             nNeuWink=NormAngle180(-(GetAngle(aDif)-nWink0));
2374 
2375             if (bVertical)
2376                 nNeuWink=NormAngle180(-nNeuWink);
2377         }
2378         else
2379         {
2380             if (bVertical)
2381                 nNeuWink=NormAngle180(GetAngle(aDif));
2382             else
2383                 nNeuWink=NormAngle180(-(GetAngle(aDif)-9000));
2384 
2385             if (nNeuWink<-9000 || nNeuWink>9000)
2386                 nNeuWink=NormAngle180(nNeuWink+18000);
2387 
2388             if (bResize)
2389             {
2390                 Point aPt2(aPnt);
2391 
2392                 if (nSA!=0)
2393                     aPt2=GetSnapPos(aPnt); // den also in jedem Falle fangen
2394 
2395                 if (bVertical)
2396                 {
2397                     aNeuFact=Fraction(aPt2.X()-aRef.X(),aP0.X()-aRef.X());
2398                 }
2399                 else
2400                 {
2401                     aNeuFact=Fraction(aPt2.Y()-aRef.Y(),aP0.Y()-aRef.Y());
2402                 }
2403             }
2404         }
2405 
2406         bool bNeg=nNeuWink<0;
2407 
2408         if (bNeg)
2409             nNeuWink=-nNeuWink;
2410 
2411         if (nSA!=0)
2412         { // Winkelfang
2413             nNeuWink+=nSA/2;
2414             nNeuWink/=nSA;
2415             nNeuWink*=nSA;
2416         }
2417 
2418         nNeuWink=NormAngle360(nNeuWink);
2419         bUpSideDown=nNeuWink>9000 && nNeuWink<27000;
2420 
2421         if (bSlant)
2422         { // Resize fuer Slant berechnen
2423             // Mit Winkelfang jedoch ohne 89deg Begrenzung
2424             long nTmpWink=nNeuWink;
2425             if (bUpSideDown) nNeuWink-=18000;
2426             if (bNeg) nTmpWink=-nTmpWink;
2427             bResize=true;
2428             double nCos=cos(nTmpWink*nPi180);
2429             aNeuFact=nCos;
2430             Kuerzen(aFact,10); // 3 Dezimalstellen sollten reichen
2431         }
2432 
2433         if (nNeuWink>8900)
2434             nNeuWink=8900;
2435 
2436         if (bNeg)
2437             nNeuWink=-nNeuWink;
2438 
2439         if (nWink!=nNeuWink || aFact!=aNeuFact)
2440         {
2441             nWink=nNeuWink;
2442             aFact=aNeuFact;
2443             double a=nWink*nPi180;
2444             double nTan1=0.0;
2445             nTan1=tan(a); // schonmal berechnen, damit mgl. wenig Zeit zwischen Hide() und Show() vergeht
2446             Hide();
2447             nTan=nTan1;
2448             DragStat().NextMove(rPnt);
2449             Show();
2450         }
2451     }
2452 }
2453 
2454 void SdrDragShear::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
2455 {
2456     if (bResize)
2457     {
2458         if (bVertical)
2459         {
2460             rTarget.Resize(DragStat().GetRef1(),aFact,Fraction(1,1));
2461         }
2462         else
2463         {
2464             rTarget.Resize(DragStat().GetRef1(),Fraction(1,1),aFact);
2465         }
2466     }
2467 
2468     if (nWink!=0)
2469     {
2470         rTarget.Shear(DragStat().GetRef1(),nWink,tan(nWink*nPi180),bVertical);
2471     }
2472 }
2473 
2474 bool SdrDragShear::EndSdrDrag(bool bCopy)
2475 {
2476     Hide();
2477 
2478     if (bResize && aFact==Fraction(1,1))
2479         bResize=false;
2480 
2481     if (nWink!=0 || bResize)
2482     {
2483         if (nWink!=0 && bResize)
2484         {
2485             XubString aStr;
2486             ImpTakeDescriptionStr(STR_EditShear,aStr);
2487 
2488             if (bCopy)
2489                 aStr+=ImpGetResStr(STR_EditWithCopy);
2490 
2491             getSdrDragView().BegUndo(aStr);
2492         }
2493 
2494         if (bResize)
2495         {
2496             if (bVertical)
2497             {
2498                 getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),aFact,Fraction(1,1),bCopy);
2499             }
2500             else
2501             {
2502                 getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),Fraction(1,1),aFact,bCopy);
2503             }
2504 
2505             bCopy=false;
2506         }
2507 
2508         if (nWink!=0)
2509         {
2510             getSdrDragView().ShearMarkedObj(DragStat().GetRef1(),nWink,bVertical,bCopy);
2511         }
2512 
2513         if (nWink!=0 && bResize)
2514             getSdrDragView().EndUndo();
2515 
2516         return true;
2517     }
2518 
2519     return false;
2520 }
2521 
2522 Pointer SdrDragShear::GetSdrDragPointer() const
2523 {
2524     if (bVertical)
2525         return Pointer(POINTER_VSHEAR);
2526     else
2527         return Pointer(POINTER_HSHEAR);
2528 }
2529 
2530 ////////////////////////////////////////////////////////////////////////////////////////////////////
2531 
2532 TYPEINIT1(SdrDragMirror,SdrDragMethod);
2533 
2534 void SdrDragMirror::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
2535 {
2536     if(bMirrored)
2537     {
2538         rTarget.Mirror(DragStat().GetRef1(), DragStat().GetRef2());
2539     }
2540 }
2541 
2542 SdrDragMirror::SdrDragMirror(SdrDragView& rNewView)
2543 :   SdrDragMethod(rNewView),
2544     nWink(0),
2545     bMirrored(false),
2546     bSide0(false)
2547 {
2548 }
2549 
2550 bool SdrDragMirror::ImpCheckSide(const Point& rPnt) const
2551 {
2552     long nWink1=GetAngle(rPnt-DragStat().GetRef1());
2553     nWink1-=nWink;
2554     nWink1=NormAngle360(nWink1);
2555 
2556     return nWink1<18000;
2557 }
2558 
2559 void SdrDragMirror::TakeSdrDragComment(XubString& rStr) const
2560 {
2561     if (aDif.X()==0)
2562         ImpTakeDescriptionStr(STR_DragMethMirrorHori,rStr);
2563     else if (aDif.Y()==0)
2564         ImpTakeDescriptionStr(STR_DragMethMirrorVert,rStr);
2565     else if (Abs(aDif.X())==Abs(aDif.Y()))
2566         ImpTakeDescriptionStr(STR_DragMethMirrorDiag,rStr);
2567     else
2568         ImpTakeDescriptionStr(STR_DragMethMirrorFree,rStr);
2569 
2570     if (getSdrDragView().IsDragWithCopy())
2571         rStr+=ImpGetResStr(STR_EditWithCopy);
2572 }
2573 
2574 bool SdrDragMirror::BeginSdrDrag()
2575 {
2576     SdrHdl* pH1=GetHdlList().GetHdl(HDL_REF1);
2577     SdrHdl* pH2=GetHdlList().GetHdl(HDL_REF2);
2578 
2579     if (pH1!=NULL && pH2!=NULL)
2580     {
2581         DragStat().Ref1()=pH1->GetPos();
2582         DragStat().Ref2()=pH2->GetPos();
2583         Ref1()=pH1->GetPos();
2584         Ref2()=pH2->GetPos();
2585         aDif=pH2->GetPos()-pH1->GetPos();
2586         bool b90=(aDif.X()==0) || aDif.Y()==0;
2587         bool b45=b90 || (Abs(aDif.X())==Abs(aDif.Y()));
2588         nWink=NormAngle360(GetAngle(aDif));
2589 
2590         if (!getSdrDragView().IsMirrorAllowed(false,false) && !b45)
2591             return false; // freier Achsenwinkel nicht erlaubt
2592 
2593         if (!getSdrDragView().IsMirrorAllowed(true,false) && !b90)
2594             return false;  // 45deg auch nicht erlaubt
2595 
2596         bSide0=ImpCheckSide(DragStat().GetStart());
2597         Show();
2598         return true;
2599     }
2600     else
2601     {
2602         DBG_ERROR("SdrDragMirror::BeginSdrDrag(): Spiegelachse nicht gefunden");
2603         return false;
2604     }
2605 }
2606 
2607 basegfx::B2DHomMatrix SdrDragMirror::getCurrentTransformation()
2608 {
2609     basegfx::B2DHomMatrix aRetval;
2610 
2611     if (bMirrored)
2612     {
2613         const double fDeltaX(DragStat().GetRef2().X() - DragStat().GetRef1().X());
2614         const double fDeltaY(DragStat().GetRef2().Y() - DragStat().GetRef1().Y());
2615         const double fRotation(atan2(fDeltaY, fDeltaX));
2616 
2617         aRetval = basegfx::tools::createTranslateB2DHomMatrix(-DragStat().GetRef1().X(), -DragStat().GetRef1().Y());
2618         aRetval.rotate(-fRotation);
2619         aRetval.scale(1.0, -1.0);
2620         aRetval.rotate(fRotation);
2621         aRetval.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y());
2622     }
2623 
2624     return aRetval;
2625 }
2626 
2627 void SdrDragMirror::MoveSdrDrag(const Point& rPnt)
2628 {
2629     if (DragStat().CheckMinMoved(rPnt))
2630     {
2631         bool bNeuSide=ImpCheckSide(rPnt);
2632         bool bNeuMirr=bSide0!=bNeuSide;
2633 
2634         if (bMirrored!=bNeuMirr)
2635         {
2636             Hide();
2637             bMirrored=bNeuMirr;
2638             DragStat().NextMove(rPnt);
2639             Show();
2640         }
2641     }
2642 }
2643 
2644 bool SdrDragMirror::EndSdrDrag(bool bCopy)
2645 {
2646     Hide();
2647 
2648     if (bMirrored)
2649     {
2650         getSdrDragView().MirrorMarkedObj(DragStat().GetRef1(),DragStat().GetRef2(),bCopy);
2651     }
2652 
2653     return true;
2654 }
2655 
2656 Pointer SdrDragMirror::GetSdrDragPointer() const
2657 {
2658     return Pointer(POINTER_MIRROR);
2659 }
2660 
2661 ////////////////////////////////////////////////////////////////////////////////////////////////////
2662 
2663 TYPEINIT1(SdrDragGradient, SdrDragMethod);
2664 
2665 SdrDragGradient::SdrDragGradient(SdrDragView& rNewView, bool bGrad)
2666 :   SdrDragMethod(rNewView),
2667     pIAOHandle(NULL),
2668     bIsGradient(bGrad)
2669 {
2670 }
2671 
2672 void SdrDragGradient::TakeSdrDragComment(XubString& rStr) const
2673 {
2674     if(IsGradient())
2675         ImpTakeDescriptionStr(STR_DragMethGradient, rStr);
2676     else
2677         ImpTakeDescriptionStr(STR_DragMethTransparence, rStr);
2678 }
2679 
2680 bool SdrDragGradient::BeginSdrDrag()
2681 {
2682     bool bRetval(false);
2683 
2684     pIAOHandle = (SdrHdlGradient*)GetHdlList().GetHdl(IsGradient() ? HDL_GRAD : HDL_TRNS);
2685 
2686     if(pIAOHandle)
2687     {
2688         // save old values
2689         DragStat().Ref1() = pIAOHandle->GetPos();
2690         DragStat().Ref2() = pIAOHandle->Get2ndPos();
2691 
2692         // what was hit?
2693         bool bHit(false);
2694         SdrHdlColor* pColHdl = pIAOHandle->GetColorHdl1();
2695 
2696         // init handling flags
2697         pIAOHandle->SetMoveSingleHandle(false);
2698         pIAOHandle->SetMoveFirstHandle(false);
2699 
2700         // test first color handle
2701         if(pColHdl)
2702         {
2703             basegfx::B2DPoint aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2704 
2705             if(pColHdl->getOverlayObjectList().isHitLogic(aPosition))
2706             {
2707                 bHit = true;
2708                 pIAOHandle->SetMoveSingleHandle(true);
2709                 pIAOHandle->SetMoveFirstHandle(true);
2710             }
2711         }
2712 
2713         // test second color handle
2714         pColHdl = pIAOHandle->GetColorHdl2();
2715 
2716         if(!bHit && pColHdl)
2717         {
2718             basegfx::B2DPoint aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2719 
2720             if(pColHdl->getOverlayObjectList().isHitLogic(aPosition))
2721             {
2722                 bHit = true;
2723                 pIAOHandle->SetMoveSingleHandle(true);
2724             }
2725         }
2726 
2727         // test gradient handle itself
2728         if(!bHit)
2729         {
2730             basegfx::B2DPoint aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2731 
2732             if(pIAOHandle->getOverlayObjectList().isHitLogic(aPosition))
2733             {
2734                 bHit = true;
2735             }
2736         }
2737 
2738         // everything up and running :o}
2739         bRetval = bHit;
2740     }
2741     else
2742     {
2743         DBG_ERROR("SdrDragGradient::BeginSdrDrag(): IAOGradient nicht gefunden");
2744     }
2745 
2746     return bRetval;
2747 }
2748 
2749 void SdrDragGradient::MoveSdrDrag(const Point& rPnt)
2750 {
2751     if(pIAOHandle && DragStat().CheckMinMoved(rPnt))
2752     {
2753         DragStat().NextMove(rPnt);
2754 
2755         // Do the Move here!!! DragStat().GetStart()
2756         Point aMoveDiff = rPnt - DragStat().GetStart();
2757 
2758         if(pIAOHandle->IsMoveSingleHandle())
2759         {
2760             if(pIAOHandle->IsMoveFirstHandle())
2761             {
2762                 pIAOHandle->SetPos(DragStat().Ref1() + aMoveDiff);
2763                 if(pIAOHandle->GetColorHdl1())
2764                     pIAOHandle->GetColorHdl1()->SetPos(DragStat().Ref1() + aMoveDiff);
2765             }
2766             else
2767             {
2768                 pIAOHandle->Set2ndPos(DragStat().Ref2() + aMoveDiff);
2769                 if(pIAOHandle->GetColorHdl2())
2770                     pIAOHandle->GetColorHdl2()->SetPos(DragStat().Ref2() + aMoveDiff);
2771             }
2772         }
2773         else
2774         {
2775             pIAOHandle->SetPos(DragStat().Ref1() + aMoveDiff);
2776             pIAOHandle->Set2ndPos(DragStat().Ref2() + aMoveDiff);
2777 
2778             if(pIAOHandle->GetColorHdl1())
2779                 pIAOHandle->GetColorHdl1()->SetPos(DragStat().Ref1() + aMoveDiff);
2780 
2781             if(pIAOHandle->GetColorHdl2())
2782                 pIAOHandle->GetColorHdl2()->SetPos(DragStat().Ref2() + aMoveDiff);
2783         }
2784 
2785         // new state
2786         pIAOHandle->FromIAOToItem(getSdrDragView().GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(), false, false);
2787     }
2788 }
2789 
2790 bool SdrDragGradient::EndSdrDrag(bool /*bCopy*/)
2791 {
2792     // here the result is clear, do something with the values
2793     Ref1() = pIAOHandle->GetPos();
2794     Ref2() = pIAOHandle->Get2ndPos();
2795 
2796     // new state
2797     pIAOHandle->FromIAOToItem(getSdrDragView().GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(), true, true);
2798 
2799     return true;
2800 }
2801 
2802 void SdrDragGradient::CancelSdrDrag()
2803 {
2804     // restore old values
2805     pIAOHandle->SetPos(DragStat().Ref1());
2806     pIAOHandle->Set2ndPos(DragStat().Ref2());
2807 
2808     if(pIAOHandle->GetColorHdl1())
2809         pIAOHandle->GetColorHdl1()->SetPos(DragStat().Ref1());
2810 
2811     if(pIAOHandle->GetColorHdl2())
2812         pIAOHandle->GetColorHdl2()->SetPos(DragStat().Ref2());
2813 
2814     // new state
2815     pIAOHandle->FromIAOToItem(getSdrDragView().GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(), true, false);
2816 }
2817 
2818 Pointer SdrDragGradient::GetSdrDragPointer() const
2819 {
2820     return Pointer(POINTER_REFHAND);
2821 }
2822 
2823 ////////////////////////////////////////////////////////////////////////////////////////////////////
2824 
2825 TYPEINIT1(SdrDragCrook,SdrDragMethod);
2826 
2827 SdrDragCrook::SdrDragCrook(SdrDragView& rNewView)
2828 :   SdrDragMethod(rNewView),
2829     aFact(1,1),
2830     bContortionAllowed(false),
2831     bNoContortionAllowed(false),
2832     bContortion(false),
2833     bResizeAllowed(false),
2834     bResize(false),
2835     bRotateAllowed(false),
2836     bRotate(false),
2837     bVertical(false),
2838     bValid(false),
2839     bLft(false),
2840     bRgt(false),
2841     bUpr(false),
2842     bLwr(false),
2843     bAtCenter(false),
2844     nWink(0),
2845     nMarkSize(0),
2846     eMode(SDRCROOK_ROTATE)
2847 {
2848 }
2849 
2850 void SdrDragCrook::TakeSdrDragComment(XubString& rStr) const
2851 {
2852     ImpTakeDescriptionStr(!bContortion ? STR_DragMethCrook : STR_DragMethCrookContortion, rStr);
2853 
2854     if(bValid)
2855     {
2856         rStr.AppendAscii(" (");
2857 
2858         XubString aStr;
2859         sal_Int32 nVal(nWink);
2860 
2861         if(bAtCenter)
2862             nVal *= 2;
2863 
2864         nVal = Abs(nVal);
2865         getSdrDragView().GetModel()->TakeWinkStr(nVal, aStr);
2866         rStr += aStr;
2867         rStr += sal_Unicode(')');
2868     }
2869 
2870     if(getSdrDragView().IsDragWithCopy())
2871         rStr += ImpGetResStr(STR_EditWithCopy);
2872 }
2873 
2874 // #96920# These defines parametrise the created raster
2875 // for interactions
2876 #define DRAG_CROOK_RASTER_MINIMUM   (4)
2877 #define DRAG_CROOK_RASTER_MAXIMUM   (15)
2878 #define DRAG_CROOK_RASTER_DISTANCE  (30)
2879 
2880 basegfx::B2DPolyPolygon impCreateDragRaster(SdrPageView& rPageView, const Rectangle& rMarkRect)
2881 {
2882     basegfx::B2DPolyPolygon aRetval;
2883 
2884     if(rPageView.PageWindowCount())
2885     {
2886         OutputDevice& rOut = (rPageView.GetPageWindow(0)->GetPaintWindow().GetOutputDevice());
2887         Rectangle aPixelSize = rOut.LogicToPixel(rMarkRect);
2888         sal_uInt32 nHorDiv(aPixelSize.GetWidth() / DRAG_CROOK_RASTER_DISTANCE);
2889         sal_uInt32 nVerDiv(aPixelSize.GetHeight() / DRAG_CROOK_RASTER_DISTANCE);
2890 
2891         if(nHorDiv > DRAG_CROOK_RASTER_MAXIMUM)
2892             nHorDiv = DRAG_CROOK_RASTER_MAXIMUM;
2893         if(nHorDiv < DRAG_CROOK_RASTER_MINIMUM)
2894             nHorDiv = DRAG_CROOK_RASTER_MINIMUM;
2895 
2896         if(nVerDiv > DRAG_CROOK_RASTER_MAXIMUM)
2897             nVerDiv = DRAG_CROOK_RASTER_MAXIMUM;
2898         if(nVerDiv < DRAG_CROOK_RASTER_MINIMUM)
2899             nVerDiv = DRAG_CROOK_RASTER_MINIMUM;
2900 
2901         const double fXLen(rMarkRect.GetWidth() / (double)nHorDiv);
2902         const double fYLen(rMarkRect.GetHeight() / (double)nVerDiv);
2903         double fYPos(rMarkRect.Top());
2904         sal_uInt32 a, b;
2905 
2906         for(a = 0; a <= nVerDiv; a++)
2907         {
2908             // hor lines
2909             for(b = 0; b < nHorDiv; b++)
2910             {
2911                 basegfx::B2DPolygon aHorLineSegment;
2912 
2913                 const double fNewX(rMarkRect.Left() + (b * fXLen));
2914                 aHorLineSegment.append(basegfx::B2DPoint(fNewX, fYPos));
2915                 aHorLineSegment.appendBezierSegment(
2916                     basegfx::B2DPoint(fNewX + (fXLen * (1.0 / 3.0)), fYPos),
2917                     basegfx::B2DPoint(fNewX + (fXLen * (2.0 / 3.0)), fYPos),
2918                     basegfx::B2DPoint(fNewX + fXLen, fYPos));
2919                 aRetval.append(aHorLineSegment);
2920             }
2921 
2922             // increments
2923             fYPos += fYLen;
2924         }
2925 
2926         double fXPos(rMarkRect.Left());
2927 
2928         for(a = 0; a <= nHorDiv; a++)
2929         {
2930             // ver lines
2931             for(b = 0; b < nVerDiv; b++)
2932             {
2933                 basegfx::B2DPolygon aVerLineSegment;
2934 
2935                 const double fNewY(rMarkRect.Top() + (b * fYLen));
2936                 aVerLineSegment.append(basegfx::B2DPoint(fXPos, fNewY));
2937                 aVerLineSegment.appendBezierSegment(
2938                     basegfx::B2DPoint(fXPos, fNewY + (fYLen * (1.0 / 3.0))),
2939                     basegfx::B2DPoint(fXPos, fNewY + (fYLen * (2.0 / 3.0))),
2940                     basegfx::B2DPoint(fXPos, fNewY + fYLen));
2941                 aRetval.append(aVerLineSegment);
2942             }
2943 
2944             // increments
2945             fXPos += fXLen;
2946         }
2947     }
2948 
2949     return aRetval;
2950 }
2951 
2952 void SdrDragCrook::createSdrDragEntries()
2953 {
2954     // Add extended frame raster first, so it will be behind objects
2955     if(getSdrDragView().GetSdrPageView())
2956     {
2957         const basegfx::B2DPolyPolygon aDragRaster(impCreateDragRaster(*getSdrDragView().GetSdrPageView(), GetMarkedRect()));
2958 
2959         if(aDragRaster.count())
2960         {
2961             addSdrDragEntry(new SdrDragEntryPolyPolygon(aDragRaster));
2962         }
2963     }
2964 
2965     // call parent
2966     SdrDragMethod::createSdrDragEntries();
2967 }
2968 
2969 bool SdrDragCrook::BeginSdrDrag()
2970 {
2971     bContortionAllowed=getSdrDragView().IsCrookAllowed(false);
2972     bNoContortionAllowed=getSdrDragView().IsCrookAllowed(true);
2973     bResizeAllowed=getSdrDragView().IsResizeAllowed(false);
2974     bRotateAllowed=getSdrDragView().IsRotateAllowed(false);
2975 
2976     if (bContortionAllowed || bNoContortionAllowed)
2977     {
2978         bVertical=(GetDragHdlKind()==HDL_LOWER || GetDragHdlKind()==HDL_UPPER);
2979         aMarkRect=GetMarkedRect();
2980         aMarkCenter=aMarkRect.Center();
2981         nMarkSize=bVertical ? (aMarkRect.GetHeight()-1) : (aMarkRect.GetWidth()-1);
2982         aCenter=aMarkCenter;
2983         aStart=DragStat().GetStart();
2984         Show();
2985         return true;
2986     }
2987     else
2988     {
2989         return false;
2990     }
2991 }
2992 
2993 void SdrDragCrook::_MovAllPoints(basegfx::B2DPolyPolygon& rTarget)
2994 {
2995     SdrPageView* pPV = getSdrDragView().GetSdrPageView();
2996 
2997     if(pPV)
2998     {
2999         XPolyPolygon aTempPolyPoly(rTarget);
3000 
3001         if (pPV->HasMarkedObjPageView())
3002         {
3003             sal_uInt16 nPolyAnz=aTempPolyPoly.Count();
3004 
3005             if (!bContortion && !getSdrDragView().IsNoDragXorPolys())
3006             {
3007                 sal_uInt16 n1st=0,nLast=0;
3008                 Point aC(aCenter);
3009 
3010                 while (n1st<nPolyAnz)
3011                 {
3012                     nLast=n1st;
3013                     while (nLast<nPolyAnz && aTempPolyPoly[nLast].GetPointCount()!=0) nLast++;
3014                     Rectangle aBound(aTempPolyPoly[n1st].GetBoundRect());
3015                     sal_uInt16 i;
3016 
3017                     for (i=n1st+1; i<nLast; i++)
3018                     {
3019                         aBound.Union(aTempPolyPoly[n1st].GetBoundRect());
3020                     }
3021 
3022                     Point aCtr0(aBound.Center());
3023                     Point aCtr1(aCtr0);
3024 
3025                     if (bResize)
3026                     {
3027                         Fraction aFact1(1,1);
3028 
3029                         if (bVertical)
3030                         {
3031                             ResizePoint(aCtr1,aC,aFact1,aFact);
3032                         }
3033                         else
3034                         {
3035                             ResizePoint(aCtr1,aC,aFact,aFact1);
3036                         }
3037                     }
3038 
3039                     bool bRotOk=false;
3040                     double nSin=0,nCos=0;
3041 
3042                     if (aRad.X()!=0 && aRad.Y()!=0)
3043                     {
3044                         bRotOk=bRotate;
3045 
3046                         switch (eMode)
3047                         {
3048                             case SDRCROOK_ROTATE : CrookRotateXPoint (aCtr1,NULL,NULL,aC,aRad,nSin,nCos,bVertical);           break;
3049                             case SDRCROOK_SLANT  : CrookSlantXPoint  (aCtr1,NULL,NULL,aC,aRad,nSin,nCos,bVertical);           break;
3050                             case SDRCROOK_STRETCH: CrookStretchXPoint(aCtr1,NULL,NULL,aC,aRad,nSin,nCos,bVertical,aMarkRect); break;
3051                         } // switch
3052                     }
3053 
3054                     aCtr1-=aCtr0;
3055 
3056                     for (i=n1st; i<nLast; i++)
3057                     {
3058                         if (bRotOk)
3059                         {
3060                             RotateXPoly(aTempPolyPoly[i],aCtr0,nSin,nCos);
3061                         }
3062 
3063                         aTempPolyPoly[i].Move(aCtr1.X(),aCtr1.Y());
3064                     }
3065 
3066                     n1st=nLast+1;
3067                 }
3068             }
3069             else
3070             {
3071                 sal_uInt16 i,j;
3072 
3073                 for (j=0; j<nPolyAnz; j++)
3074                 {
3075                     XPolygon& aPol=aTempPolyPoly[j];
3076                     sal_uInt16 nPtAnz=aPol.GetPointCount();
3077                     i=0;
3078 
3079                     while (i<nPtAnz)
3080                     {
3081                         Point* pPnt=&aPol[i];
3082                         Point* pC1=NULL;
3083                         Point* pC2=NULL;
3084 
3085                         if (i+1<nPtAnz && aPol.IsControl(i))
3086                         { // Kontrollpunkt links
3087                             pC1=pPnt;
3088                             i++;
3089                             pPnt=&aPol[i];
3090                         }
3091 
3092                         i++;
3093 
3094                         if (i<nPtAnz && aPol.IsControl(i))
3095                         { // Kontrollpunkt rechts
3096                             pC2=&aPol[i];
3097                             i++;
3098                         }
3099 
3100                         _MovCrookPoint(*pPnt,pC1,pC2);
3101                     }
3102                 }
3103             }
3104         }
3105 
3106         rTarget = aTempPolyPoly.getB2DPolyPolygon();
3107     }
3108 }
3109 
3110 void SdrDragCrook::_MovCrookPoint(Point& rPnt, Point* pC1, Point* pC2)
3111 {
3112     bool bVert=bVertical;
3113     bool bC1=pC1!=NULL;
3114     bool bC2=pC2!=NULL;
3115     Point aC(aCenter);
3116 
3117     if (bResize)
3118     {
3119         Fraction aFact1(1,1);
3120 
3121         if (bVert)
3122         {
3123             ResizePoint(rPnt,aC,aFact1,aFact);
3124 
3125             if (bC1)
3126                 ResizePoint(*pC1,aC,aFact1,aFact);
3127 
3128             if (bC2)
3129                 ResizePoint(*pC2,aC,aFact1,aFact);
3130         }
3131         else
3132         {
3133             ResizePoint(rPnt,aC,aFact,aFact1);
3134 
3135             if (bC1)
3136                 ResizePoint(*pC1,aC,aFact,aFact1);
3137 
3138             if (bC2)
3139                 ResizePoint(*pC2,aC,aFact,aFact1);
3140         }
3141     }
3142 
3143     if (aRad.X()!=0 && aRad.Y()!=0)
3144     {
3145         double nSin,nCos;
3146 
3147         switch (eMode)
3148         {
3149             case SDRCROOK_ROTATE : CrookRotateXPoint (rPnt,pC1,pC2,aC,aRad,nSin,nCos,bVert);           break;
3150             case SDRCROOK_SLANT  : CrookSlantXPoint  (rPnt,pC1,pC2,aC,aRad,nSin,nCos,bVert);           break;
3151             case SDRCROOK_STRETCH: CrookStretchXPoint(rPnt,pC1,pC2,aC,aRad,nSin,nCos,bVert,aMarkRect); break;
3152         } // switch
3153     }
3154 }
3155 
3156 void SdrDragCrook::MoveSdrDrag(const Point& rPnt)
3157 {
3158     if (DragStat().CheckMinMoved(rPnt))
3159     {
3160         Point aPnt(rPnt);
3161         bool bNeuMoveOnly=getSdrDragView().IsMoveOnlyDragging();
3162         bAtCenter=false;
3163         SdrCrookMode eNeuMode=getSdrDragView().GetCrookMode();
3164         bool bNeuContortion=!bNeuMoveOnly && ((bContortionAllowed && !getSdrDragView().IsCrookNoContortion()) || !bNoContortionAllowed);
3165         bResize=!getSdrDragView().IsOrtho() && bResizeAllowed && !bNeuMoveOnly;
3166         bool bNeuRotate=bRotateAllowed && !bNeuContortion && !bNeuMoveOnly && eNeuMode==SDRCROOK_ROTATE;
3167         long nSA=0;
3168 
3169         if (nSA==0)
3170             aPnt=GetSnapPos(aPnt);
3171 
3172         Point aNeuCenter(aMarkCenter.X(),aStart.Y());
3173 
3174         if (bVertical)
3175         {
3176             aNeuCenter.X()=aStart.X();
3177             aNeuCenter.Y()=aMarkCenter.Y();
3178         }
3179 
3180         if (!getSdrDragView().IsCrookAtCenter())
3181         {
3182             switch (GetDragHdlKind())
3183             {
3184                 case HDL_UPLFT: aNeuCenter.X()=aMarkRect.Right();  bLft=true; break;
3185                 case HDL_UPPER: aNeuCenter.Y()=aMarkRect.Bottom(); bUpr=true; break;
3186                 case HDL_UPRGT: aNeuCenter.X()=aMarkRect.Left();   bRgt=true; break;
3187                 case HDL_LEFT : aNeuCenter.X()=aMarkRect.Right();  bLft=true; break;
3188                 case HDL_RIGHT: aNeuCenter.X()=aMarkRect.Left();   bRgt=true; break;
3189                 case HDL_LWLFT: aNeuCenter.X()=aMarkRect.Right();  bLft=true; break;
3190                 case HDL_LOWER: aNeuCenter.Y()=aMarkRect.Top();    bLwr=true; break;
3191                 case HDL_LWRGT: aNeuCenter.X()=aMarkRect.Left();   bRgt=true; break;
3192                 default: bAtCenter=true;
3193             }
3194         }
3195         else
3196             bAtCenter=true;
3197 
3198         Fraction aNeuFact(1,1);
3199         long dx1=aPnt.X()-aNeuCenter.X();
3200         long dy1=aPnt.Y()-aNeuCenter.Y();
3201         bValid=bVertical ? dx1!=0 : dy1!=0;
3202 
3203         if (bValid)
3204         {
3205             if (bVertical)
3206                 bValid=Abs(dx1)*100>Abs(dy1);
3207             else
3208                 bValid=Abs(dy1)*100>Abs(dx1);
3209         }
3210 
3211         long nNeuRad=0;
3212         nWink=0;
3213 
3214         if (bValid)
3215         {
3216             double a=0; // Steigung des Radius
3217             long nPntWink=0;
3218 
3219             if (bVertical)
3220             {
3221                 a=((double)dy1)/((double)dx1); // Steigung des Radius
3222                 nNeuRad=((long)(dy1*a)+dx1) /2;
3223                 aNeuCenter.X()+=nNeuRad;
3224                 nPntWink=GetAngle(aPnt-aNeuCenter);
3225             }
3226             else
3227             {
3228                 a=((double)dx1)/((double)dy1); // Steigung des Radius
3229                 nNeuRad=((long)(dx1*a)+dy1) /2;
3230                 aNeuCenter.Y()+=nNeuRad;
3231                 nPntWink=GetAngle(aPnt-aNeuCenter)-9000;
3232             }
3233 
3234             if (!bAtCenter)
3235             {
3236                 if (nNeuRad<0)
3237                 {
3238                     if (bRgt) nPntWink+=18000;
3239                     if (bLft) nPntWink=18000-nPntWink;
3240                     if (bLwr) nPntWink=-nPntWink;
3241                 }
3242                 else
3243                 {
3244                     if (bRgt) nPntWink=-nPntWink;
3245                     if (bUpr) nPntWink=18000-nPntWink;
3246                     if (bLwr) nPntWink+=18000;
3247                 }
3248 
3249                 nPntWink=NormAngle360(nPntWink);
3250             }
3251             else
3252             {
3253                 if (nNeuRad<0) nPntWink+=18000;
3254                 if (bVertical) nPntWink=18000-nPntWink;
3255                 nPntWink=NormAngle180(nPntWink);
3256                 nPntWink=Abs(nPntWink);
3257             }
3258 
3259             double nUmfang=2*Abs(nNeuRad)*nPi;
3260 
3261             if (bResize)
3262             {
3263                 if (nSA!=0)
3264                 { // Winkelfang
3265                     long nWink0=nPntWink;
3266                     nPntWink+=nSA/2;
3267                     nPntWink/=nSA;
3268                     nPntWink*=nSA;
3269                     BigInt a2(nNeuRad);
3270                     a2*=BigInt(nWink);
3271                     a2/=BigInt(nWink0);
3272                     nNeuRad=long(a2);
3273 
3274                     if (bVertical)
3275                         aNeuCenter.X()=aStart.X()+nNeuRad;
3276                     else
3277                         aNeuCenter.Y()=aStart.Y()+nNeuRad;
3278                 }
3279 
3280                 long nMul=(long)(nUmfang*NormAngle360(nPntWink)/36000);
3281 
3282                 if (bAtCenter)
3283                     nMul*=2;
3284 
3285                 aNeuFact=Fraction(nMul,nMarkSize);
3286                 nWink=nPntWink;
3287             }
3288             else
3289             {
3290                 nWink=(long)((nMarkSize*360/nUmfang)*100)/2;
3291 
3292                 if (nWink==0)
3293                     bValid=false;
3294 
3295                 if (bValid && nSA!=0)
3296                 { // Winkelfang
3297                     long nWink0=nWink;
3298                     nWink+=nSA/2;
3299                     nWink/=nSA;
3300                     nWink*=nSA;
3301                     BigInt a2(nNeuRad);
3302                     a2*=BigInt(nWink);
3303                     a2/=BigInt(nWink0);
3304                     nNeuRad=long(a2);
3305 
3306                     if (bVertical)
3307                         aNeuCenter.X()=aStart.X()+nNeuRad;
3308                     else
3309                         aNeuCenter.Y()=aStart.Y()+nNeuRad;
3310                 }
3311             }
3312         }
3313 
3314         if (nWink==0 || nNeuRad==0)
3315             bValid=false;
3316 
3317         if (!bValid)
3318             nNeuRad=0;
3319 
3320         if (!bValid && bResize)
3321         {
3322             long nMul=bVertical ? dy1 : dx1;
3323 
3324             if (bLft || bUpr)
3325                 nMul=-nMul;
3326 
3327             long nDiv=nMarkSize;
3328 
3329             if (bAtCenter)
3330             {
3331                 nMul*=2;
3332                 nMul=Abs(nMul);
3333             }
3334 
3335             aNeuFact=Fraction(nMul,nDiv);
3336         }
3337 
3338         if (aNeuCenter!=aCenter || bNeuContortion!=bContortion || aNeuFact!=aFact ||
3339             bNeuMoveOnly != getMoveOnly() || bNeuRotate!=bRotate || eNeuMode!=eMode)
3340         {
3341             Hide();
3342             setMoveOnly(bNeuMoveOnly);
3343             bRotate=bNeuRotate;
3344             eMode=eNeuMode;
3345             bContortion=bNeuContortion;
3346             aCenter=aNeuCenter;
3347             aFact=aNeuFact;
3348             aRad=Point(nNeuRad,nNeuRad);
3349             bResize=aFact!=Fraction(1,1) && aFact.GetDenominator()!=0 && aFact.IsValid();
3350             DragStat().NextMove(aPnt);
3351             Show();
3352         }
3353     }
3354 }
3355 
3356 void SdrDragCrook::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
3357 {
3358     const bool bDoResize(aFact!=Fraction(1,1));
3359     const bool bDoCrook(aCenter!=aMarkCenter && aRad.X()!=0 && aRad.Y()!=0);
3360 
3361     if (bDoCrook || bDoResize)
3362     {
3363         if (bDoResize)
3364         {
3365             Fraction aFact1(1,1);
3366 
3367             if (bContortion)
3368             {
3369                 if (bVertical)
3370                 {
3371                     rTarget.Resize(aCenter,aFact1,aFact);
3372                 }
3373                 else
3374                 {
3375                     rTarget.Resize(aCenter,aFact,aFact1);
3376                 }
3377             }
3378             else
3379             {
3380                 Point aCtr0(rTarget.GetSnapRect().Center());
3381                 Point aCtr1(aCtr0);
3382 
3383                 if (bVertical)
3384                 {
3385                     ResizePoint(aCtr1,aCenter,aFact1,aFact);
3386                 }
3387                 else
3388                 {
3389                     ResizePoint(aCtr1,aCenter,aFact,aFact1);
3390                 }
3391 
3392                 Size aSiz(aCtr1.X()-aCtr0.X(),aCtr1.Y()-aCtr0.Y());
3393 
3394                 rTarget.Move(aSiz);
3395             }
3396         }
3397 
3398         if (bDoCrook)
3399         {
3400             const Rectangle aLocalMarkRect(getSdrDragView().GetMarkedObjRect());
3401             const bool bLocalRotate(!bContortion && eMode == SDRCROOK_ROTATE && getSdrDragView().IsRotateAllowed(false));
3402 
3403             getSdrDragView().ImpCrookObj(&rTarget,aCenter,aRad,eMode,bVertical,!bContortion,bLocalRotate,aLocalMarkRect);
3404         }
3405     }
3406 }
3407 
3408 void SdrDragCrook::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon& rTarget)
3409 {
3410     // use helper derived from old stuff
3411     _MovAllPoints(rTarget);
3412 }
3413 
3414 bool SdrDragCrook::EndSdrDrag(bool bCopy)
3415 {
3416     Hide();
3417 
3418     if (bResize && aFact==Fraction(1,1))
3419         bResize=false;
3420 
3421     const bool bUndo = getSdrDragView().IsUndoEnabled();
3422 
3423     bool bDoCrook=aCenter!=aMarkCenter && aRad.X()!=0 && aRad.Y()!=0;
3424 
3425     if (bDoCrook || bResize)
3426     {
3427         if (bResize && bUndo)
3428         {
3429             XubString aStr;
3430             ImpTakeDescriptionStr(!bContortion?STR_EditCrook:STR_EditCrookContortion,aStr);
3431 
3432             if (bCopy)
3433                 aStr+=ImpGetResStr(STR_EditWithCopy);
3434 
3435             getSdrDragView().BegUndo(aStr);
3436         }
3437 
3438         if (bResize)
3439         {
3440             Fraction aFact1(1,1);
3441 
3442             if (bContortion)
3443             {
3444                 if (bVertical)
3445                     getSdrDragView().ResizeMarkedObj(aCenter,aFact1,aFact,bCopy);
3446                 else
3447                     getSdrDragView().ResizeMarkedObj(aCenter,aFact,aFact1,bCopy);
3448             }
3449             else
3450             {
3451                 if (bCopy)
3452                     getSdrDragView().CopyMarkedObj();
3453 
3454                 sal_uLong nMarkAnz=getSdrDragView().GetMarkedObjectList().GetMarkCount();
3455 
3456                 for (sal_uLong nm=0; nm<nMarkAnz; nm++)
3457                 {
3458                     SdrMark* pM=getSdrDragView().GetMarkedObjectList().GetMark(nm);
3459                     SdrObject* pO=pM->GetMarkedSdrObj();
3460                     Point aCtr0(pO->GetSnapRect().Center());
3461                     Point aCtr1(aCtr0);
3462 
3463                     if (bVertical)
3464                         ResizePoint(aCtr1,aCenter,aFact1,aFact);
3465                     else
3466                         ResizePoint(aCtr1,aCenter,aFact,aFact1);
3467 
3468                     Size aSiz(aCtr1.X()-aCtr0.X(),aCtr1.Y()-aCtr0.Y());
3469                     if( bUndo )
3470                         AddUndo(getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pO,aSiz));
3471                     pO->Move(aSiz);
3472                 }
3473             }
3474 
3475             bCopy=false;
3476         }
3477 
3478         if (bDoCrook)
3479         {
3480             getSdrDragView().CrookMarkedObj(aCenter,aRad,eMode,bVertical,!bContortion,bCopy);
3481             getSdrDragView().SetLastCrookCenter(aCenter);
3482         }
3483 
3484         if (bResize && bUndo)
3485             getSdrDragView().EndUndo();
3486 
3487         return true;
3488     }
3489 
3490     return false;
3491 }
3492 
3493 Pointer SdrDragCrook::GetSdrDragPointer() const
3494 {
3495     return Pointer(POINTER_CROOK);
3496 }
3497 
3498 ////////////////////////////////////////////////////////////////////////////////////////////////////
3499 
3500 TYPEINIT1(SdrDragDistort,SdrDragMethod);
3501 
3502 SdrDragDistort::SdrDragDistort(SdrDragView& rNewView)
3503 :   SdrDragMethod(rNewView),
3504     nPolyPt(0),
3505     bContortionAllowed(false),
3506     bNoContortionAllowed(false),
3507     bContortion(false)
3508 {
3509 }
3510 
3511 void SdrDragDistort::TakeSdrDragComment(XubString& rStr) const
3512 {
3513     ImpTakeDescriptionStr(STR_DragMethDistort, rStr);
3514 
3515     XubString aStr;
3516 
3517     rStr.AppendAscii(" (x=");
3518     getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDX(), aStr);
3519     rStr += aStr;
3520     rStr.AppendAscii(" y=");
3521     getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDY(), aStr);
3522     rStr += aStr;
3523     rStr += sal_Unicode(')');
3524 
3525     if(getSdrDragView().IsDragWithCopy())
3526         rStr += ImpGetResStr(STR_EditWithCopy);
3527 }
3528 
3529 void SdrDragDistort::createSdrDragEntries()
3530 {
3531     // Add extended frame raster first, so it will be behind objects
3532     if(getSdrDragView().GetSdrPageView())
3533     {
3534         const basegfx::B2DPolyPolygon aDragRaster(impCreateDragRaster(*getSdrDragView().GetSdrPageView(), GetMarkedRect()));
3535 
3536         if(aDragRaster.count())
3537         {
3538             addSdrDragEntry(new SdrDragEntryPolyPolygon(aDragRaster));
3539         }
3540     }
3541 
3542     // call parent
3543     SdrDragMethod::createSdrDragEntries();
3544 }
3545 
3546 bool SdrDragDistort::BeginSdrDrag()
3547 {
3548     bContortionAllowed=getSdrDragView().IsDistortAllowed(false);
3549     bNoContortionAllowed=getSdrDragView().IsDistortAllowed(true);
3550 
3551     if (bContortionAllowed || bNoContortionAllowed)
3552     {
3553         SdrHdlKind eKind=GetDragHdlKind();
3554         nPolyPt=0xFFFF;
3555 
3556         if (eKind==HDL_UPLFT) nPolyPt=0;
3557         if (eKind==HDL_UPRGT) nPolyPt=1;
3558         if (eKind==HDL_LWRGT) nPolyPt=2;
3559         if (eKind==HDL_LWLFT) nPolyPt=3;
3560         if (nPolyPt>3) return false;
3561 
3562         aMarkRect=GetMarkedRect();
3563         aDistortedRect=XPolygon(aMarkRect);
3564         Show();
3565         return true;
3566     }
3567     else
3568     {
3569         return false;
3570     }
3571 }
3572 
3573 void SdrDragDistort::_MovAllPoints(basegfx::B2DPolyPolygon& rTarget)
3574 {
3575     if (bContortion)
3576     {
3577         SdrPageView* pPV = getSdrDragView().GetSdrPageView();
3578 
3579         if(pPV)
3580         {
3581             if (pPV->HasMarkedObjPageView())
3582             {
3583                 basegfx::B2DPolyPolygon aDragPolygon(rTarget);
3584                 const basegfx::B2DRange aOriginalRange(aMarkRect.Left(), aMarkRect.Top(), aMarkRect.Right(), aMarkRect.Bottom());
3585                 const basegfx::B2DPoint aTopLeft(aDistortedRect[0].X(), aDistortedRect[0].Y());
3586                 const basegfx::B2DPoint aTopRight(aDistortedRect[1].X(), aDistortedRect[1].Y());
3587                 const basegfx::B2DPoint aBottomLeft(aDistortedRect[3].X(), aDistortedRect[3].Y());
3588                 const basegfx::B2DPoint aBottomRight(aDistortedRect[2].X(), aDistortedRect[2].Y());
3589 
3590                 aDragPolygon = basegfx::tools::distort(aDragPolygon, aOriginalRange, aTopLeft, aTopRight, aBottomLeft, aBottomRight);
3591                 rTarget = aDragPolygon;
3592             }
3593         }
3594     }
3595 }
3596 
3597 void SdrDragDistort::MoveSdrDrag(const Point& rPnt)
3598 {
3599     if (DragStat().CheckMinMoved(rPnt))
3600     {
3601         Point aPnt(GetSnapPos(rPnt));
3602 
3603         if (getSdrDragView().IsOrtho())
3604             OrthoDistance8(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho());
3605 
3606         bool bNeuContortion=(bContortionAllowed && !getSdrDragView().IsCrookNoContortion()) || !bNoContortionAllowed;
3607 
3608         if (bNeuContortion!=bContortion || aDistortedRect[nPolyPt]!=aPnt)
3609         {
3610             Hide();
3611             aDistortedRect[nPolyPt]=aPnt;
3612             bContortion=bNeuContortion;
3613             DragStat().NextMove(aPnt);
3614             Show();
3615         }
3616     }
3617 }
3618 
3619 bool SdrDragDistort::EndSdrDrag(bool bCopy)
3620 {
3621     Hide();
3622     bool bDoDistort=DragStat().GetDX()!=0 || DragStat().GetDY()!=0;
3623 
3624     if (bDoDistort)
3625     {
3626         getSdrDragView().DistortMarkedObj(aMarkRect,aDistortedRect,!bContortion,bCopy);
3627         return true;
3628     }
3629 
3630     return false;
3631 }
3632 
3633 Pointer SdrDragDistort::GetSdrDragPointer() const
3634 {
3635     return Pointer(POINTER_REFHAND);
3636 }
3637 
3638 void SdrDragDistort::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
3639 {
3640     const bool bDoDistort(DragStat().GetDX()!=0 || DragStat().GetDY()!=0);
3641 
3642     if (bDoDistort)
3643     {
3644         getSdrDragView().ImpDistortObj(&rTarget, aMarkRect, aDistortedRect, !bContortion);
3645     }
3646 }
3647 
3648 void SdrDragDistort::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon& rTarget)
3649 {
3650     // use helper derived from old stuff
3651     _MovAllPoints(rTarget);
3652 }
3653 
3654 ////////////////////////////////////////////////////////////////////////////////////////////////////
3655 
3656 TYPEINIT1(SdrDragCrop,SdrDragResize);
3657 
3658 SdrDragCrop::SdrDragCrop(SdrDragView& rNewView)
3659 :   SdrDragResize(rNewView)
3660 {
3661     // switch off solid dragging for crop; it just makes no sense since showing
3662     // a 50% transparent object above the original will not be visible
3663     setSolidDraggingActive(false);
3664 }
3665 
3666 void SdrDragCrop::TakeSdrDragComment(XubString& rStr) const
3667 {
3668     ImpTakeDescriptionStr(STR_DragMethCrop, rStr);
3669 
3670     XubString aStr;
3671 
3672     rStr.AppendAscii(" (x=");
3673     getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDX(), aStr);
3674     rStr += aStr;
3675     rStr.AppendAscii(" y=");
3676     getSdrDragView().GetModel()->TakeMetricStr(DragStat().GetDY(), aStr);
3677     rStr += aStr;
3678     rStr += sal_Unicode(')');
3679 
3680     if(getSdrDragView().IsDragWithCopy())
3681         rStr += ImpGetResStr(STR_EditWithCopy);
3682 }
3683 
3684 bool SdrDragCrop::EndSdrDrag(bool bCopy)
3685 {
3686     Hide();
3687 
3688     if( DragStat().GetDX()==0 && DragStat().GetDY()==0 )
3689         return false;
3690 
3691     const SdrMarkList& rMarkList = getSdrDragView().GetMarkedObjectList();
3692 
3693     if( rMarkList.GetMarkCount() != 1 )
3694         return false;
3695 
3696     SdrGrafObj* pObj = dynamic_cast<SdrGrafObj*>( rMarkList.GetMark( 0 )->GetMarkedSdrObj() );
3697 
3698     if( !pObj || (pObj->GetGraphicType() == GRAPHIC_NONE) || (pObj->GetGraphicType() == GRAPHIC_DEFAULT) )
3699         return false;
3700 
3701     const GraphicObject& rGraphicObject = pObj->GetGraphicObject();
3702     const MapMode aMapMode100thmm(MAP_100TH_MM);
3703     Size aGraphicSize(rGraphicObject.GetPrefSize());
3704 
3705     if( MAP_PIXEL == rGraphicObject.GetPrefMapMode().GetMapUnit() )
3706         aGraphicSize = Application::GetDefaultDevice()->PixelToLogic( aGraphicSize, aMapMode100thmm );
3707     else
3708         aGraphicSize = Application::GetDefaultDevice()->LogicToLogic( aGraphicSize, rGraphicObject.GetPrefMapMode(), aMapMode100thmm);
3709 
3710     if( aGraphicSize.nA == 0 || aGraphicSize.nB == 0 )
3711         return false;
3712 
3713     const SdrGrafCropItem& rOldCrop = (const SdrGrafCropItem&)pObj->GetMergedItem(SDRATTR_GRAFCROP);
3714 
3715     const bool bUndo = getSdrDragView().IsUndoEnabled();
3716 
3717     if( bUndo )
3718     {
3719         String aUndoStr;
3720         ImpTakeDescriptionStr(STR_DragMethCrop, aUndoStr);
3721 
3722         getSdrDragView().BegUndo( aUndoStr );
3723         getSdrDragView().AddUndo( getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject( *pObj ) );
3724     }
3725 
3726     Rectangle aOldRect( pObj->GetLogicRect() );
3727     getSdrDragView().ResizeMarkedObj(DragStat().Ref1(),aXFact,aYFact,bCopy);
3728     Rectangle aNewRect( pObj->GetLogicRect() );
3729 
3730     double fScaleX = ( aGraphicSize.Width() - rOldCrop.GetLeft() - rOldCrop.GetRight() ) / (double)aOldRect.GetWidth();
3731     double fScaleY = ( aGraphicSize.Height() - rOldCrop.GetTop() - rOldCrop.GetBottom() ) / (double)aOldRect.GetHeight();
3732 
3733     // to correct the never working combination of cropped images and mirroring
3734     // I have to correct the rectangles the calculation is based on here. In the current
3735     // core geometry stuff a vertical mirror is expressed as 180 degree rotation. All
3736     // this can be removed again when aw080 will have cleaned up the old
3737     // (non-)transformation mess in the core.
3738     if(18000 == pObj->GetGeoStat().nDrehWink)
3739     {
3740         // old notation of vertical mirror, need to correct diffs since both rects
3741         // are rotated by 180 degrees
3742         aOldRect = Rectangle(aOldRect.TopLeft() - (aOldRect.BottomRight() - aOldRect.TopLeft()), aOldRect.TopLeft());
3743         aNewRect = Rectangle(aNewRect.TopLeft() - (aNewRect.BottomRight() - aNewRect.TopLeft()), aNewRect.TopLeft());
3744     }
3745 
3746     sal_Int32 nDiffLeft = aNewRect.nLeft - aOldRect.nLeft;
3747     sal_Int32 nDiffTop = aNewRect.nTop - aOldRect.nTop;
3748     sal_Int32 nDiffRight = aNewRect.nRight - aOldRect.nRight;
3749     sal_Int32 nDiffBottom = aNewRect.nBottom - aOldRect.nBottom;
3750 
3751     sal_Int32 nLeftCrop = static_cast<sal_Int32>( rOldCrop.GetLeft() + nDiffLeft * fScaleX );
3752     sal_Int32 nTopCrop = static_cast<sal_Int32>( rOldCrop.GetTop() + nDiffTop * fScaleY );
3753     sal_Int32 nRightCrop = static_cast<sal_Int32>( rOldCrop.GetRight() - nDiffRight * fScaleX );
3754     sal_Int32 nBottomCrop = static_cast<sal_Int32>( rOldCrop.GetBottom() - nDiffBottom * fScaleY );
3755 
3756     SfxItemPool& rPool = getSdrDragView().GetModel()->GetItemPool();
3757     SfxItemSet aSet( rPool, SDRATTR_GRAFCROP, SDRATTR_GRAFCROP );
3758     aSet.Put( SdrGrafCropItem( nLeftCrop, nTopCrop, nRightCrop, nBottomCrop ) );
3759     getSdrDragView().SetAttributes( aSet, false );
3760 
3761     if( bUndo )
3762         getSdrDragView().EndUndo();
3763 
3764     return true;
3765 }
3766 
3767 Pointer SdrDragCrop::GetSdrDragPointer() const
3768 {
3769     return Pointer(POINTER_CROP);
3770 }
3771 
3772 ////////////////////////////////////////////////////////////////////////////////////////////////////
3773 // eof
3774