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