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