xref: /aoo4110/main/svx/source/svdraw/svddrgmt.cxx (revision b1cdbd2c)
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_7x7(aBackPen, aRGBFrontColor)));
313 
314 		    aRetval = drawinglayer::primitive2d::Primitive2DSequence(&aMarkerArrayPrimitive2D, 1);
315         }
316     }
317 
318     return aRetval;
319 }
320 
321 ////////////////////////////////////////////////////////////////////////////////////////////////////
322 
323 TYPEINIT0(SdrDragMethod);
324 
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