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