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