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