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