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