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