/src/libreoffice/svx/source/svdraw/svdhdl.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 | | |
21 | | #include <algorithm> |
22 | | #include <cassert> |
23 | | |
24 | | #include <svx/svdhdl.hxx> |
25 | | #include <svx/svdpagv.hxx> |
26 | | #include <svx/svdmrkv.hxx> |
27 | | #include <utility> |
28 | | #include <vcl/settings.hxx> |
29 | | #include <vcl/virdev.hxx> |
30 | | #include <vcl/ptrstyle.hxx> |
31 | | |
32 | | #include <svx/sxekitm.hxx> |
33 | | #include <svx/strings.hrc> |
34 | | #include <svx/svdmodel.hxx> |
35 | | #include "gradtrns.hxx" |
36 | | #include <svx/xflgrit.hxx> |
37 | | #include <svx/svdundo.hxx> |
38 | | #include <svx/dialmgr.hxx> |
39 | | #include <svx/xflftrit.hxx> |
40 | | |
41 | | #include <svx/svdopath.hxx> |
42 | | #include <basegfx/vector/b2dvector.hxx> |
43 | | #include <basegfx/polygon/b2dpolygon.hxx> |
44 | | #include <svx/sdr/overlay/overlaymanager.hxx> |
45 | | #include <svx/sdr/overlay/overlayanimatedbitmapex.hxx> |
46 | | #include <svx/sdr/overlay/overlaybitmapex.hxx> |
47 | | #include <sdr/overlay/overlayline.hxx> |
48 | | #include <sdr/overlay/overlaytriangle.hxx> |
49 | | #include <sdr/overlay/overlayhandle.hxx> |
50 | | #include <sdr/overlay/overlayrectangle.hxx> |
51 | | #include <svx/sdrpagewindow.hxx> |
52 | | #include <svx/sdrpaintwindow.hxx> |
53 | | #include <vcl/svapp.hxx> |
54 | | #include <svx/sdr/overlay/overlaypolypolygon.hxx> |
55 | | #include <tools/lazydelete.hxx> |
56 | | #include <vcl/BitmapTools.hxx> |
57 | | #include <svx/sdr/contact/objectcontact.hxx> |
58 | | #include <svx/sdr/contact/viewcontact.hxx> |
59 | | #include <osl/diagnose.h> |
60 | | |
61 | | #include <basegfx/polygon/b2dpolygontools.hxx> |
62 | | #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx> |
63 | | #include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx> |
64 | | #include <drawinglayer/primitive2d/graphicprimitive2d.hxx> |
65 | | #include <drawinglayer/primitive2d/maskprimitive2d.hxx> |
66 | | #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> |
67 | | #include <svtools/optionsdrawinglayer.hxx> |
68 | | #include <memory> |
69 | | #include <bitmaps.hlst> |
70 | | |
71 | | namespace { |
72 | | |
73 | | // #i15222# |
74 | | // Due to the resource problems in Win95/98 with bitmap resources I |
75 | | // will change this handle bitmap providing class. Old version was splitting |
76 | | // and preparing all small handle bitmaps in device bitmap format, now this will |
77 | | // be done on the fly. Thus, there is only one big bitmap in memory. With |
78 | | // three source bitmaps, this will be 3 system bitmap resources instead of hundreds. |
79 | | // The price for that needs to be evaluated. Maybe we will need another change here |
80 | | // if this is too expensive. |
81 | | class SdrHdlBitmapSet |
82 | | { |
83 | | // the bitmap holding all information |
84 | | Bitmap maMarkersBitmap; |
85 | | |
86 | | // the cropped Bitmaps for reusage |
87 | | ::std::vector< Bitmap > maRealMarkers; |
88 | | |
89 | | // helpers |
90 | | Bitmap& impGetOrCreateTargetBitmap(sal_uInt16 nIndex, const tools::Rectangle& rRectangle); |
91 | | |
92 | | public: |
93 | | explicit SdrHdlBitmapSet(); |
94 | | |
95 | | const Bitmap& GetBitmap(BitmapMarkerKind eKindOfMarker, sal_uInt16 nInd); |
96 | | }; |
97 | | |
98 | | } |
99 | | |
100 | 0 | #define KIND_COUNT (14) |
101 | 0 | #define INDEX_COUNT (6) |
102 | 0 | #define INDIVIDUAL_COUNT (5) |
103 | | |
104 | | SdrHdlBitmapSet::SdrHdlBitmapSet() |
105 | 0 | : maMarkersBitmap(SIP_SA_MARKERS), |
106 | | // 15 kinds (BitmapMarkerKind) use index [0..5] + 5 extra |
107 | 0 | maRealMarkers((KIND_COUNT * INDEX_COUNT) + INDIVIDUAL_COUNT) |
108 | 0 | { |
109 | 0 | } |
110 | | |
111 | | Bitmap& SdrHdlBitmapSet::impGetOrCreateTargetBitmap(sal_uInt16 nIndex, const tools::Rectangle& rRectangle) |
112 | 0 | { |
113 | 0 | Bitmap& rTargetBitmap = maRealMarkers[nIndex]; |
114 | |
|
115 | 0 | if(rTargetBitmap.IsEmpty()) |
116 | 0 | { |
117 | 0 | rTargetBitmap = maMarkersBitmap; |
118 | 0 | rTargetBitmap.Crop(rRectangle); |
119 | 0 | } |
120 | |
|
121 | 0 | return rTargetBitmap; |
122 | 0 | } |
123 | | |
124 | | // change getting of bitmap to use the big resource bitmap |
125 | | const Bitmap& SdrHdlBitmapSet::GetBitmap(BitmapMarkerKind eKindOfMarker, sal_uInt16 nInd) |
126 | 0 | { |
127 | | // fill in size and source position in maMarkersBitmap |
128 | 0 | const sal_uInt16 nYPos(nInd * 11); |
129 | |
|
130 | 0 | switch(eKindOfMarker) |
131 | 0 | { |
132 | 0 | default: |
133 | 0 | { |
134 | 0 | OSL_FAIL( "Unknown kind of marker." ); |
135 | 0 | [[fallthrough]]; // return Rect_9x9 as default |
136 | 0 | } |
137 | 0 | case BitmapMarkerKind::Rect_9x9: |
138 | 0 | { |
139 | 0 | return impGetOrCreateTargetBitmap((1 * INDEX_COUNT) + nInd, tools::Rectangle(Point(7, nYPos), Size(9, 9))); |
140 | 0 | } |
141 | | |
142 | 0 | case BitmapMarkerKind::Rect_7x7: |
143 | 0 | { |
144 | 0 | return impGetOrCreateTargetBitmap((0 * INDEX_COUNT) + nInd, tools::Rectangle(Point(0, nYPos), Size(7, 7))); |
145 | 0 | } |
146 | | |
147 | 0 | case BitmapMarkerKind::Rect_11x11: |
148 | 0 | { |
149 | 0 | return impGetOrCreateTargetBitmap((2 * INDEX_COUNT) + nInd, tools::Rectangle(Point(16, nYPos), Size(11, 11))); |
150 | 0 | } |
151 | | |
152 | 0 | case BitmapMarkerKind::Rect_13x13: |
153 | 0 | { |
154 | 0 | const sal_uInt16 nIndex((3 * INDEX_COUNT) + nInd); |
155 | |
|
156 | 0 | switch(nInd) |
157 | 0 | { |
158 | 0 | case 0: |
159 | 0 | { |
160 | 0 | return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(72, 66), Size(13, 13))); |
161 | 0 | } |
162 | 0 | case 1: |
163 | 0 | { |
164 | 0 | return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(85, 66), Size(13, 13))); |
165 | 0 | } |
166 | 0 | case 2: |
167 | 0 | { |
168 | 0 | return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(72, 79), Size(13, 13))); |
169 | 0 | } |
170 | 0 | case 3: |
171 | 0 | { |
172 | 0 | return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(85, 79), Size(13, 13))); |
173 | 0 | } |
174 | 0 | case 4: |
175 | 0 | { |
176 | 0 | return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(98, 79), Size(13, 13))); |
177 | 0 | } |
178 | 0 | default: // case 5: |
179 | 0 | { |
180 | 0 | return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(98, 66), Size(13, 13))); |
181 | 0 | } |
182 | 0 | } |
183 | 0 | } |
184 | | |
185 | 0 | case BitmapMarkerKind::Circ_7x7: |
186 | 0 | case BitmapMarkerKind::Customshape_7x7: |
187 | 0 | { |
188 | 0 | return impGetOrCreateTargetBitmap((4 * INDEX_COUNT) + nInd, tools::Rectangle(Point(27, nYPos), Size(7, 7))); |
189 | 0 | } |
190 | | |
191 | 0 | case BitmapMarkerKind::Circ_9x9: |
192 | 0 | case BitmapMarkerKind::Customshape_9x9: |
193 | 0 | { |
194 | 0 | return impGetOrCreateTargetBitmap((5 * INDEX_COUNT) + nInd, tools::Rectangle(Point(34, nYPos), Size(9, 9))); |
195 | 0 | } |
196 | | |
197 | 0 | case BitmapMarkerKind::Circ_11x11: |
198 | 0 | case BitmapMarkerKind::Customshape_11x11: |
199 | 0 | { |
200 | 0 | return impGetOrCreateTargetBitmap((6 * INDEX_COUNT) + nInd, tools::Rectangle(Point(43, nYPos), Size(11, 11))); |
201 | 0 | } |
202 | | |
203 | 0 | case BitmapMarkerKind::Elli_7x9: |
204 | 0 | { |
205 | 0 | return impGetOrCreateTargetBitmap((7 * INDEX_COUNT) + nInd, tools::Rectangle(Point(54, nYPos), Size(7, 9))); |
206 | 0 | } |
207 | | |
208 | 0 | case BitmapMarkerKind::Elli_9x11: |
209 | 0 | { |
210 | 0 | return impGetOrCreateTargetBitmap((8 * INDEX_COUNT) + nInd, tools::Rectangle(Point(61, nYPos), Size(9, 11))); |
211 | 0 | } |
212 | | |
213 | 0 | case BitmapMarkerKind::Elli_9x7: |
214 | 0 | { |
215 | 0 | return impGetOrCreateTargetBitmap((9 * INDEX_COUNT) + nInd, tools::Rectangle(Point(70, nYPos), Size(9, 7))); |
216 | 0 | } |
217 | | |
218 | 0 | case BitmapMarkerKind::Elli_11x9: |
219 | 0 | { |
220 | 0 | return impGetOrCreateTargetBitmap((10 * INDEX_COUNT) + nInd, tools::Rectangle(Point(79, nYPos), Size(11, 9))); |
221 | 0 | } |
222 | | |
223 | 0 | case BitmapMarkerKind::RectPlus_7x7: |
224 | 0 | { |
225 | 0 | return impGetOrCreateTargetBitmap((11 * INDEX_COUNT) + nInd, tools::Rectangle(Point(90, nYPos), Size(7, 7))); |
226 | 0 | } |
227 | | |
228 | 0 | case BitmapMarkerKind::RectPlus_9x9: |
229 | 0 | { |
230 | 0 | return impGetOrCreateTargetBitmap((12 * INDEX_COUNT) + nInd, tools::Rectangle(Point(97, nYPos), Size(9, 9))); |
231 | 0 | } |
232 | | |
233 | 0 | case BitmapMarkerKind::RectPlus_11x11: |
234 | 0 | { |
235 | 0 | return impGetOrCreateTargetBitmap((13 * INDEX_COUNT) + nInd, tools::Rectangle(Point(106, nYPos), Size(11, 11))); |
236 | 0 | } |
237 | | |
238 | 0 | case BitmapMarkerKind::Crosshair: |
239 | 0 | { |
240 | 0 | return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 0, tools::Rectangle(Point(0, 68), Size(15, 15))); |
241 | 0 | } |
242 | | |
243 | 0 | case BitmapMarkerKind::Glue: |
244 | 0 | { |
245 | 0 | return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 1, tools::Rectangle(Point(15, 76), Size(9, 9))); |
246 | 0 | } |
247 | | |
248 | 0 | case BitmapMarkerKind::Glue_Deselected: |
249 | 0 | { |
250 | 0 | return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 2, tools::Rectangle(Point(15, 67), Size(9, 9))); |
251 | 0 | } |
252 | | |
253 | 0 | case BitmapMarkerKind::Anchor: // AnchorTR for SW |
254 | 0 | case BitmapMarkerKind::AnchorTR: |
255 | 0 | { |
256 | 0 | return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 3, tools::Rectangle(Point(24, 67), Size(24, 24))); |
257 | 0 | } |
258 | | |
259 | | // add AnchorPressed to be able to animate anchor control |
260 | 0 | case BitmapMarkerKind::AnchorPressed: |
261 | 0 | case BitmapMarkerKind::AnchorPressedTR: |
262 | 0 | { |
263 | 0 | return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 4, tools::Rectangle(Point(48, 67), Size(24, 24))); |
264 | 0 | } |
265 | 0 | } |
266 | 0 | } |
267 | | |
268 | | |
269 | | SdrHdl::SdrHdl(): |
270 | 0 | m_pObj(nullptr), |
271 | 0 | m_pPV(nullptr), |
272 | 0 | m_pHdlList(nullptr), |
273 | 0 | m_eKind(SdrHdlKind::Move), |
274 | 0 | m_nRotationAngle(0), |
275 | 0 | m_nObjHdlNum(0), |
276 | 0 | m_nPolyNum(0), |
277 | 0 | m_nPPntNum(0), |
278 | 0 | m_nSourceHdlNum(0), |
279 | 0 | m_bSelect(false), |
280 | 0 | m_b1PixMore(false), |
281 | 0 | m_bPlusHdl(false), |
282 | 0 | mbMoveOutside(false), |
283 | 0 | mbMouseOver(false) |
284 | 0 | { |
285 | 0 | } |
286 | | |
287 | | SdrHdl::SdrHdl(const Point& rPnt, SdrHdlKind eNewKind): |
288 | 0 | m_pObj(nullptr), |
289 | 0 | m_pPV(nullptr), |
290 | 0 | m_pHdlList(nullptr), |
291 | 0 | m_aPos(rPnt), |
292 | 0 | m_eKind(eNewKind), |
293 | 0 | m_nRotationAngle(0), |
294 | 0 | m_nObjHdlNum(0), |
295 | 0 | m_nPolyNum(0), |
296 | 0 | m_nPPntNum(0), |
297 | 0 | m_nSourceHdlNum(0), |
298 | 0 | m_bSelect(false), |
299 | 0 | m_b1PixMore(false), |
300 | 0 | m_bPlusHdl(false), |
301 | 0 | mbMoveOutside(false), |
302 | 0 | mbMouseOver(false) |
303 | 0 | { |
304 | 0 | } |
305 | | |
306 | | SdrHdl::~SdrHdl() |
307 | 0 | { |
308 | 0 | GetRidOfIAObject(); |
309 | 0 | } |
310 | | |
311 | | void SdrHdl::Set1PixMore(bool bJa) |
312 | 0 | { |
313 | 0 | if(m_b1PixMore != bJa) |
314 | 0 | { |
315 | 0 | m_b1PixMore = bJa; |
316 | | |
317 | | // create new display |
318 | 0 | Touch(); |
319 | 0 | } |
320 | 0 | } |
321 | | |
322 | | void SdrHdl::SetMoveOutside( bool bMoveOutside ) |
323 | 0 | { |
324 | 0 | if(mbMoveOutside != bMoveOutside) |
325 | 0 | { |
326 | 0 | mbMoveOutside = bMoveOutside; |
327 | | |
328 | | // create new display |
329 | 0 | Touch(); |
330 | 0 | } |
331 | 0 | } |
332 | | |
333 | | void SdrHdl::SetRotationAngle(Degree100 n) |
334 | 0 | { |
335 | 0 | if(m_nRotationAngle != n) |
336 | 0 | { |
337 | 0 | m_nRotationAngle = n; |
338 | | |
339 | | // create new display |
340 | 0 | Touch(); |
341 | 0 | } |
342 | 0 | } |
343 | | |
344 | | void SdrHdl::SetPos(const Point& rPnt) |
345 | 0 | { |
346 | 0 | if(m_aPos != rPnt) |
347 | 0 | { |
348 | | // remember new position |
349 | 0 | m_aPos = rPnt; |
350 | | |
351 | | // create new display |
352 | 0 | Touch(); |
353 | 0 | } |
354 | 0 | } |
355 | | |
356 | | void SdrHdl::SetSelected(bool bJa) |
357 | 0 | { |
358 | 0 | if(m_bSelect != bJa) |
359 | 0 | { |
360 | | // remember new value |
361 | 0 | m_bSelect = bJa; |
362 | | |
363 | | // create new display |
364 | 0 | Touch(); |
365 | 0 | } |
366 | 0 | } |
367 | | |
368 | | void SdrHdl::SetHdlList(SdrHdlList* pList) |
369 | 0 | { |
370 | 0 | if(m_pHdlList != pList) |
371 | 0 | { |
372 | | // remember list |
373 | 0 | m_pHdlList = pList; |
374 | | |
375 | | // now it's possible to create graphic representation |
376 | 0 | Touch(); |
377 | 0 | } |
378 | 0 | } |
379 | | |
380 | | void SdrHdl::SetObj(SdrObject* pNewObj) |
381 | 0 | { |
382 | 0 | if(m_pObj != pNewObj) |
383 | 0 | { |
384 | | // remember new object |
385 | 0 | m_pObj = pNewObj; |
386 | | |
387 | | // graphic representation may have changed |
388 | 0 | Touch(); |
389 | 0 | } |
390 | 0 | } |
391 | | |
392 | | void SdrHdl::Touch() |
393 | 0 | { |
394 | | // force update of graphic representation |
395 | 0 | CreateB2dIAObject(); |
396 | 0 | } |
397 | | |
398 | | void SdrHdl::GetRidOfIAObject() |
399 | 0 | { |
400 | | |
401 | | // OVERLAYMANAGER |
402 | 0 | maOverlayGroup.clear(); |
403 | 0 | } |
404 | | |
405 | | void SdrHdl::CreateB2dIAObject() |
406 | 0 | { |
407 | | // first throw away old one |
408 | 0 | GetRidOfIAObject(); |
409 | |
|
410 | 0 | if(!m_pHdlList || !m_pHdlList->GetView() || m_pHdlList->GetView()->areMarkHandlesHidden()) |
411 | 0 | return; |
412 | | |
413 | 0 | BitmapColorIndex eColIndex = BitmapColorIndex::LightGreen; |
414 | 0 | BitmapMarkerKind eKindOfMarker = BitmapMarkerKind::Rect_7x7; |
415 | |
|
416 | 0 | bool bRot = m_pHdlList->IsRotateShear(); |
417 | 0 | if(m_pObj) |
418 | 0 | eColIndex = m_bSelect ? BitmapColorIndex::Cyan : BitmapColorIndex::LightCyan; |
419 | 0 | if(bRot) |
420 | 0 | { |
421 | | // red rotation handles |
422 | 0 | if(m_pObj && m_bSelect) |
423 | 0 | eColIndex = BitmapColorIndex::Red; |
424 | 0 | else |
425 | 0 | eColIndex = BitmapColorIndex::LightRed; |
426 | 0 | } |
427 | |
|
428 | 0 | switch(m_eKind) |
429 | 0 | { |
430 | 0 | case SdrHdlKind::Move: |
431 | 0 | { |
432 | 0 | eKindOfMarker = m_b1PixMore ? BitmapMarkerKind::Rect_9x9 : BitmapMarkerKind::Rect_7x7; |
433 | 0 | break; |
434 | 0 | } |
435 | 0 | case SdrHdlKind::UpperLeft: |
436 | 0 | case SdrHdlKind::UpperRight: |
437 | 0 | case SdrHdlKind::LowerLeft: |
438 | 0 | case SdrHdlKind::LowerRight: |
439 | 0 | { |
440 | | // corner handles |
441 | 0 | if(bRot) |
442 | 0 | { |
443 | 0 | eKindOfMarker = BitmapMarkerKind::Circ_7x7; |
444 | 0 | } |
445 | 0 | else |
446 | 0 | { |
447 | 0 | eKindOfMarker = BitmapMarkerKind::Rect_7x7; |
448 | 0 | } |
449 | 0 | break; |
450 | 0 | } |
451 | 0 | case SdrHdlKind::Upper: |
452 | 0 | case SdrHdlKind::Lower: |
453 | 0 | { |
454 | | // Upper/Lower handles |
455 | 0 | if(bRot) |
456 | 0 | { |
457 | 0 | eKindOfMarker = BitmapMarkerKind::Elli_9x7; |
458 | 0 | } |
459 | 0 | else |
460 | 0 | { |
461 | 0 | eKindOfMarker = BitmapMarkerKind::Rect_7x7; |
462 | 0 | } |
463 | 0 | break; |
464 | 0 | } |
465 | 0 | case SdrHdlKind::Left: |
466 | 0 | case SdrHdlKind::Right: |
467 | 0 | { |
468 | | // Left/Right handles |
469 | 0 | if(bRot) |
470 | 0 | { |
471 | 0 | eKindOfMarker = BitmapMarkerKind::Elli_7x9; |
472 | 0 | } |
473 | 0 | else |
474 | 0 | { |
475 | 0 | eKindOfMarker = BitmapMarkerKind::Rect_7x7; |
476 | 0 | } |
477 | 0 | break; |
478 | 0 | } |
479 | 0 | case SdrHdlKind::Poly: |
480 | 0 | { |
481 | 0 | if(bRot) |
482 | 0 | { |
483 | 0 | eKindOfMarker = m_b1PixMore ? BitmapMarkerKind::Circ_9x9 : BitmapMarkerKind::Circ_7x7; |
484 | 0 | } |
485 | 0 | else |
486 | 0 | { |
487 | 0 | eKindOfMarker = m_b1PixMore ? BitmapMarkerKind::Rect_9x9 : BitmapMarkerKind::Rect_7x7; |
488 | 0 | } |
489 | 0 | break; |
490 | 0 | } |
491 | 0 | case SdrHdlKind::BezierWeight: // weight at poly |
492 | 0 | { |
493 | 0 | eKindOfMarker = BitmapMarkerKind::Circ_7x7; |
494 | 0 | break; |
495 | 0 | } |
496 | 0 | case SdrHdlKind::Circle: |
497 | 0 | { |
498 | 0 | eKindOfMarker = BitmapMarkerKind::Rect_11x11; |
499 | 0 | break; |
500 | 0 | } |
501 | 0 | case SdrHdlKind::Ref1: |
502 | 0 | case SdrHdlKind::Ref2: |
503 | 0 | { |
504 | 0 | eKindOfMarker = BitmapMarkerKind::Crosshair; |
505 | 0 | break; |
506 | 0 | } |
507 | 0 | case SdrHdlKind::Glue: |
508 | 0 | { |
509 | 0 | eKindOfMarker = BitmapMarkerKind::Glue; |
510 | 0 | break; |
511 | 0 | } |
512 | 0 | case SdrHdlKind::Anchor: |
513 | 0 | { |
514 | 0 | eKindOfMarker = BitmapMarkerKind::Anchor; |
515 | 0 | break; |
516 | 0 | } |
517 | 0 | case SdrHdlKind::User: |
518 | 0 | { |
519 | 0 | break; |
520 | 0 | } |
521 | | // top right anchor for SW |
522 | 0 | case SdrHdlKind::Anchor_TR: |
523 | 0 | { |
524 | 0 | eKindOfMarker = BitmapMarkerKind::AnchorTR; |
525 | 0 | break; |
526 | 0 | } |
527 | | |
528 | | // for SJ and the CustomShapeHandles: |
529 | 0 | case SdrHdlKind::CustomShape1: |
530 | 0 | { |
531 | 0 | eKindOfMarker = m_b1PixMore ? BitmapMarkerKind::Customshape_9x9 : BitmapMarkerKind::Customshape_7x7; |
532 | 0 | eColIndex = BitmapColorIndex::Yellow; |
533 | 0 | break; |
534 | 0 | } |
535 | 0 | default: |
536 | 0 | break; |
537 | 0 | } |
538 | | |
539 | 0 | SdrMarkView* pView = m_pHdlList->GetView(); |
540 | 0 | SdrPageView* pPageView = pView->GetSdrPageView(); |
541 | |
|
542 | 0 | if(!pPageView) |
543 | 0 | return; |
544 | | |
545 | 0 | for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++) |
546 | 0 | { |
547 | | // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b]; |
548 | 0 | const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); |
549 | |
|
550 | 0 | if(rPageWindow.GetPaintWindow().OutputToWindow()) |
551 | 0 | { |
552 | 0 | Point aMoveOutsideOffset(0, 0); |
553 | 0 | OutputDevice& rOutDev = rPageWindow.GetPaintWindow().GetOutputDevice(); |
554 | | |
555 | | // add offset if necessary |
556 | 0 | if(m_pHdlList->IsMoveOutside() || mbMoveOutside) |
557 | 0 | { |
558 | 0 | Size aOffset = rOutDev.PixelToLogic(Size(4, 4)); |
559 | |
|
560 | 0 | if(m_eKind == SdrHdlKind::UpperLeft || m_eKind == SdrHdlKind::Upper || m_eKind == SdrHdlKind::UpperRight) |
561 | 0 | aMoveOutsideOffset.AdjustY( -(aOffset.Width()) ); |
562 | 0 | if(m_eKind == SdrHdlKind::LowerLeft || m_eKind == SdrHdlKind::Lower || m_eKind == SdrHdlKind::LowerRight) |
563 | 0 | aMoveOutsideOffset.AdjustY(aOffset.Height() ); |
564 | 0 | if(m_eKind == SdrHdlKind::UpperLeft || m_eKind == SdrHdlKind::Left || m_eKind == SdrHdlKind::LowerLeft) |
565 | 0 | aMoveOutsideOffset.AdjustX( -(aOffset.Width()) ); |
566 | 0 | if(m_eKind == SdrHdlKind::UpperRight || m_eKind == SdrHdlKind::Right || m_eKind == SdrHdlKind::LowerRight) |
567 | 0 | aMoveOutsideOffset.AdjustX(aOffset.Height() ); |
568 | 0 | } |
569 | |
|
570 | 0 | const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager(); |
571 | 0 | if (xManager.is()) |
572 | 0 | { |
573 | 0 | basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y()); |
574 | 0 | std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject; |
575 | 0 | if (getenv ("SVX_DRAW_HANDLES") && (eKindOfMarker == BitmapMarkerKind::Rect_7x7 || eKindOfMarker == BitmapMarkerKind::Rect_9x9 || eKindOfMarker == BitmapMarkerKind::Rect_11x11)) |
576 | 0 | { |
577 | 0 | double fSize = 7.0; |
578 | 0 | switch (eKindOfMarker) |
579 | 0 | { |
580 | 0 | case BitmapMarkerKind::Rect_9x9: |
581 | 0 | fSize = 9.0; |
582 | 0 | break; |
583 | 0 | case BitmapMarkerKind::Rect_11x11: |
584 | 0 | fSize = 11.0; |
585 | 0 | break; |
586 | 0 | default: |
587 | 0 | break; |
588 | 0 | } |
589 | 0 | float fScalingFactor = rOutDev.GetDPIScaleFactor(); |
590 | 0 | basegfx::B2DSize aB2DSize(fSize * fScalingFactor, fSize * fScalingFactor); |
591 | |
|
592 | 0 | Color aHandleFillColor(COL_LIGHTGREEN); |
593 | 0 | switch (eColIndex) |
594 | 0 | { |
595 | 0 | case BitmapColorIndex::Cyan: |
596 | 0 | aHandleFillColor = COL_CYAN; |
597 | 0 | break; |
598 | 0 | case BitmapColorIndex::LightCyan: |
599 | 0 | aHandleFillColor = COL_LIGHTCYAN; |
600 | 0 | break; |
601 | 0 | case BitmapColorIndex::Red: |
602 | 0 | aHandleFillColor = COL_RED; |
603 | 0 | break; |
604 | 0 | case BitmapColorIndex::LightRed: |
605 | 0 | aHandleFillColor = COL_LIGHTRED; |
606 | 0 | break; |
607 | 0 | case BitmapColorIndex::Yellow: |
608 | 0 | aHandleFillColor = COL_YELLOW; |
609 | 0 | break; |
610 | 0 | default: |
611 | 0 | break; |
612 | 0 | } |
613 | 0 | pNewOverlayObject.reset(new sdr::overlay::OverlayHandle(aPosition, aB2DSize, /*HandleStrokeColor*/COL_BLACK, aHandleFillColor)); |
614 | 0 | } |
615 | 0 | else |
616 | 0 | { |
617 | 0 | pNewOverlayObject = CreateOverlayObject( |
618 | 0 | aPosition, eColIndex, eKindOfMarker, |
619 | 0 | aMoveOutsideOffset); |
620 | 0 | } |
621 | | |
622 | | // OVERLAYMANAGER |
623 | 0 | insertNewlyCreatedOverlayObjectForSdrHdl( |
624 | 0 | std::move(pNewOverlayObject), |
625 | 0 | rPageWindow.GetObjectContact(), |
626 | 0 | *xManager); |
627 | 0 | } |
628 | 0 | } |
629 | 0 | } |
630 | 0 | } |
631 | | |
632 | | BitmapMarkerKind SdrHdl::GetNextBigger(BitmapMarkerKind eKnd) |
633 | 0 | { |
634 | 0 | BitmapMarkerKind eRetval(eKnd); |
635 | |
|
636 | 0 | switch(eKnd) |
637 | 0 | { |
638 | 0 | case BitmapMarkerKind::Rect_7x7: eRetval = BitmapMarkerKind::Rect_9x9; break; |
639 | 0 | case BitmapMarkerKind::Rect_9x9: eRetval = BitmapMarkerKind::Rect_11x11; break; |
640 | 0 | case BitmapMarkerKind::Rect_11x11: eRetval = BitmapMarkerKind::Rect_13x13; break; |
641 | | |
642 | 0 | case BitmapMarkerKind::Circ_7x7: eRetval = BitmapMarkerKind::Circ_9x9; break; |
643 | 0 | case BitmapMarkerKind::Circ_9x9: eRetval = BitmapMarkerKind::Circ_11x11; break; |
644 | | |
645 | 0 | case BitmapMarkerKind::Customshape_7x7: eRetval = BitmapMarkerKind::Customshape_9x9; break; |
646 | 0 | case BitmapMarkerKind::Customshape_9x9: eRetval = BitmapMarkerKind::Customshape_11x11; break; |
647 | | //case BitmapMarkerKind::Customshape_11x11: eRetval = ; break; |
648 | | |
649 | 0 | case BitmapMarkerKind::Elli_7x9: eRetval = BitmapMarkerKind::Elli_9x11; break; |
650 | | |
651 | 0 | case BitmapMarkerKind::Elli_9x7: eRetval = BitmapMarkerKind::Elli_11x9; break; |
652 | | |
653 | 0 | case BitmapMarkerKind::RectPlus_7x7: eRetval = BitmapMarkerKind::RectPlus_9x9; break; |
654 | 0 | case BitmapMarkerKind::RectPlus_9x9: eRetval = BitmapMarkerKind::RectPlus_11x11; break; |
655 | | |
656 | | // let anchor blink with its pressed state |
657 | 0 | case BitmapMarkerKind::Anchor: eRetval = BitmapMarkerKind::AnchorPressed; break; |
658 | | |
659 | | // same for AnchorTR |
660 | 0 | case BitmapMarkerKind::AnchorTR: eRetval = BitmapMarkerKind::AnchorPressedTR; break; |
661 | 0 | default: |
662 | 0 | break; |
663 | 0 | } |
664 | | |
665 | 0 | return eRetval; |
666 | 0 | } |
667 | | |
668 | | namespace |
669 | | { |
670 | | |
671 | | OUString appendMarkerName(BitmapMarkerKind eKindOfMarker) |
672 | 0 | { |
673 | 0 | switch(eKindOfMarker) |
674 | 0 | { |
675 | 0 | case BitmapMarkerKind::Rect_7x7: |
676 | 0 | return u"rect7"_ustr; |
677 | 0 | case BitmapMarkerKind::Rect_9x9: |
678 | 0 | return u"rect9"_ustr; |
679 | 0 | case BitmapMarkerKind::Rect_11x11: |
680 | 0 | return u"rect11"_ustr; |
681 | 0 | case BitmapMarkerKind::Rect_13x13: |
682 | 0 | return u"rect13"_ustr; |
683 | 0 | case BitmapMarkerKind::Circ_7x7: |
684 | 0 | case BitmapMarkerKind::Customshape_7x7: |
685 | 0 | return u"circ7"_ustr; |
686 | 0 | case BitmapMarkerKind::Circ_9x9: |
687 | 0 | case BitmapMarkerKind::Customshape_9x9: |
688 | 0 | return u"circ9"_ustr; |
689 | 0 | case BitmapMarkerKind::Circ_11x11: |
690 | 0 | case BitmapMarkerKind::Customshape_11x11: |
691 | 0 | return u"circ11"_ustr; |
692 | 0 | case BitmapMarkerKind::Elli_7x9: |
693 | 0 | return u"elli7x9"_ustr; |
694 | 0 | case BitmapMarkerKind::Elli_9x11: |
695 | 0 | return u"elli9x11"_ustr; |
696 | 0 | case BitmapMarkerKind::Elli_9x7: |
697 | 0 | return u"elli9x7"_ustr; |
698 | 0 | case BitmapMarkerKind::Elli_11x9: |
699 | 0 | return u"elli11x9"_ustr; |
700 | 0 | case BitmapMarkerKind::RectPlus_7x7: |
701 | 0 | return u"rectplus7"_ustr; |
702 | 0 | case BitmapMarkerKind::RectPlus_9x9: |
703 | 0 | return u"rectplus9"_ustr; |
704 | 0 | case BitmapMarkerKind::RectPlus_11x11: |
705 | 0 | return u"rectplus11"_ustr; |
706 | 0 | case BitmapMarkerKind::Crosshair: |
707 | 0 | return u"cross"_ustr; |
708 | 0 | case BitmapMarkerKind::Anchor: |
709 | 0 | case BitmapMarkerKind::AnchorTR: |
710 | 0 | return u"anchor"_ustr; |
711 | 0 | case BitmapMarkerKind::AnchorPressed: |
712 | 0 | case BitmapMarkerKind::AnchorPressedTR: |
713 | 0 | return u"anchor-pressed"_ustr; |
714 | 0 | case BitmapMarkerKind::Glue: |
715 | 0 | return u"glue-selected"_ustr; |
716 | 0 | case BitmapMarkerKind::Glue_Deselected: |
717 | 0 | return u"glue-unselected"_ustr; |
718 | 0 | default: |
719 | 0 | break; |
720 | 0 | } |
721 | 0 | return OUString(); |
722 | 0 | } |
723 | | |
724 | | OUString appendMarkerColor(BitmapColorIndex eIndex) |
725 | 0 | { |
726 | 0 | switch(eIndex) |
727 | 0 | { |
728 | 0 | case BitmapColorIndex::LightGreen: |
729 | 0 | return u"1"_ustr; |
730 | 0 | case BitmapColorIndex::Cyan: |
731 | 0 | return u"2"_ustr; |
732 | 0 | case BitmapColorIndex::LightCyan: |
733 | 0 | return u"3"_ustr; |
734 | 0 | case BitmapColorIndex::Red: |
735 | 0 | return u"4"_ustr; |
736 | 0 | case BitmapColorIndex::LightRed: |
737 | 0 | return u"5"_ustr; |
738 | 0 | case BitmapColorIndex::Yellow: |
739 | 0 | return u"6"_ustr; |
740 | 0 | default: |
741 | 0 | break; |
742 | 0 | } |
743 | 0 | return OUString(); |
744 | 0 | } |
745 | | |
746 | | Bitmap ImpGetBitmap(BitmapMarkerKind eKindOfMarker, BitmapColorIndex eIndex) |
747 | 0 | { |
748 | | // use this code path only when we use HiDPI (for now) |
749 | 0 | if (Application::GetDefaultDevice()->GetDPIScalePercentage() > 100) |
750 | 0 | { |
751 | 0 | OUString sMarkerName = appendMarkerName(eKindOfMarker); |
752 | 0 | if (!sMarkerName.isEmpty()) |
753 | 0 | { |
754 | 0 | OUString sMarkerPrefix(u"svx/res/marker-"_ustr); |
755 | 0 | Bitmap aBitmap; |
756 | |
|
757 | 0 | if (eKindOfMarker == BitmapMarkerKind::Crosshair |
758 | 0 | || eKindOfMarker == BitmapMarkerKind::Anchor |
759 | 0 | || eKindOfMarker == BitmapMarkerKind::AnchorTR |
760 | 0 | || eKindOfMarker == BitmapMarkerKind::AnchorPressed |
761 | 0 | || eKindOfMarker == BitmapMarkerKind::AnchorPressedTR |
762 | 0 | || eKindOfMarker == BitmapMarkerKind::Glue |
763 | 0 | || eKindOfMarker == BitmapMarkerKind::Glue_Deselected) |
764 | 0 | { |
765 | 0 | aBitmap = vcl::bitmap::loadFromName(sMarkerPrefix + sMarkerName + ".png"); |
766 | 0 | } |
767 | 0 | else |
768 | 0 | { |
769 | 0 | aBitmap = vcl::bitmap::loadFromName(sMarkerPrefix + sMarkerName + "-" + appendMarkerColor(eIndex) + ".png"); |
770 | 0 | } |
771 | |
|
772 | 0 | if (!aBitmap.IsEmpty()) |
773 | 0 | return aBitmap; |
774 | 0 | } |
775 | 0 | } |
776 | | |
777 | | // if we can't load the marker... |
778 | | |
779 | 0 | static tools::DeleteOnDeinit< SdrHdlBitmapSet > aModernSet {}; |
780 | 0 | return aModernSet.get()->GetBitmap(eKindOfMarker, sal_uInt16(eIndex)); |
781 | 0 | } |
782 | | |
783 | | } // end anonymous namespace |
784 | | |
785 | | std::unique_ptr<sdr::overlay::OverlayObject> SdrHdl::CreateOverlayObject( |
786 | | const basegfx::B2DPoint& rPos, |
787 | | BitmapColorIndex eColIndex, BitmapMarkerKind eKindOfMarker, Point aMoveOutsideOffset) |
788 | 0 | { |
789 | 0 | std::unique_ptr<sdr::overlay::OverlayObject> pRetval; |
790 | | |
791 | | // support bigger sizes |
792 | 0 | bool bForceBiggerSize(false); |
793 | |
|
794 | 0 | if (m_pHdlList && m_pHdlList->GetHdlSize() > 3) |
795 | 0 | { |
796 | 0 | switch(eKindOfMarker) |
797 | 0 | { |
798 | 0 | case BitmapMarkerKind::Anchor: |
799 | 0 | case BitmapMarkerKind::AnchorPressed: |
800 | 0 | case BitmapMarkerKind::AnchorTR: |
801 | 0 | case BitmapMarkerKind::AnchorPressedTR: |
802 | 0 | { |
803 | | // #i121463# For anchor, do not simply make bigger because of HdlSize, |
804 | | // do it dependent of IsSelected() which Writer can set in drag mode |
805 | 0 | if(IsSelected()) |
806 | 0 | { |
807 | 0 | bForceBiggerSize = true; |
808 | 0 | } |
809 | 0 | break; |
810 | 0 | } |
811 | 0 | default: |
812 | 0 | { |
813 | 0 | bForceBiggerSize = true; |
814 | 0 | break; |
815 | 0 | } |
816 | 0 | } |
817 | 0 | } |
818 | | |
819 | 0 | if(bForceBiggerSize) |
820 | 0 | { |
821 | 0 | eKindOfMarker = GetNextBigger(eKindOfMarker); |
822 | 0 | } |
823 | | |
824 | | // This handle has the focus, visualize it |
825 | 0 | if(IsFocusHdl() && m_pHdlList && m_pHdlList->GetFocusHdl() == this) |
826 | 0 | { |
827 | | // create animated handle |
828 | 0 | BitmapMarkerKind eNextBigger = GetNextBigger(eKindOfMarker); |
829 | |
|
830 | 0 | if(eNextBigger == eKindOfMarker) |
831 | 0 | { |
832 | | // this may happen for the not supported getting-bigger types. |
833 | | // Choose an alternative here |
834 | 0 | switch(eKindOfMarker) |
835 | 0 | { |
836 | 0 | case BitmapMarkerKind::Rect_13x13: eNextBigger = BitmapMarkerKind::Rect_11x11; break; |
837 | 0 | case BitmapMarkerKind::Circ_11x11: eNextBigger = BitmapMarkerKind::Elli_11x9; break; |
838 | 0 | case BitmapMarkerKind::Elli_9x11: eNextBigger = BitmapMarkerKind::Elli_11x9; break; |
839 | 0 | case BitmapMarkerKind::Elli_11x9: eNextBigger = BitmapMarkerKind::Elli_9x11; break; |
840 | 0 | case BitmapMarkerKind::RectPlus_11x11: eNextBigger = BitmapMarkerKind::Rect_13x13; break; |
841 | 0 | case BitmapMarkerKind::Glue: |
842 | 0 | eNextBigger = BitmapMarkerKind::Crosshair; |
843 | 0 | break; |
844 | 0 | case BitmapMarkerKind::Crosshair: |
845 | 0 | case BitmapMarkerKind::Glue_Deselected: |
846 | 0 | eNextBigger = BitmapMarkerKind::Glue; |
847 | 0 | break; |
848 | 0 | default: |
849 | 0 | break; |
850 | 0 | } |
851 | 0 | } |
852 | | |
853 | | // create animated handle |
854 | 0 | Bitmap aBmp1 = ImpGetBitmap(eKindOfMarker, eColIndex); |
855 | 0 | Bitmap aBmp2 = ImpGetBitmap(eNextBigger, eColIndex); |
856 | | |
857 | | // #i53216# Use system cursor blink time. Use the unsigned value. |
858 | 0 | const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); |
859 | 0 | const sal_uInt64 nBlinkTime(rStyleSettings.GetCursorBlinkTime()); |
860 | |
|
861 | 0 | if(eKindOfMarker == BitmapMarkerKind::Anchor || eKindOfMarker == BitmapMarkerKind::AnchorPressed) |
862 | 0 | { |
863 | | // when anchor is used take upper left as reference point inside the handle |
864 | 0 | pRetval.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmp1, aBmp2, nBlinkTime)); |
865 | 0 | } |
866 | 0 | else if(eKindOfMarker == BitmapMarkerKind::AnchorTR || eKindOfMarker == BitmapMarkerKind::AnchorPressedTR) |
867 | 0 | { |
868 | | // AnchorTR for SW, take top right as (0,0) |
869 | 0 | pRetval.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmp1, aBmp2, nBlinkTime, |
870 | 0 | static_cast<sal_uInt16>(aBmp1.GetSizePixel().Width() - 1), 0, |
871 | 0 | static_cast<sal_uInt16>(aBmp2.GetSizePixel().Width() - 1), 0)); |
872 | 0 | } |
873 | 0 | else |
874 | 0 | { |
875 | | // create centered handle as default |
876 | 0 | pRetval.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmp1, aBmp2, nBlinkTime, |
877 | 0 | static_cast<sal_uInt16>(aBmp1.GetSizePixel().Width() - 1) >> 1, |
878 | 0 | static_cast<sal_uInt16>(aBmp1.GetSizePixel().Height() - 1) >> 1, |
879 | 0 | static_cast<sal_uInt16>(aBmp2.GetSizePixel().Width() - 1) >> 1, |
880 | 0 | static_cast<sal_uInt16>(aBmp2.GetSizePixel().Height() - 1) >> 1)); |
881 | 0 | } |
882 | 0 | } |
883 | 0 | else |
884 | 0 | { |
885 | | // create normal handle: use ImpGetBitmapEx(...) now |
886 | 0 | Bitmap aBmp(ImpGetBitmap(eKindOfMarker, eColIndex)); |
887 | | |
888 | | // When the image with handles is not found, the bitmap returned is |
889 | | // empty. This is a problem when we use LibreOffice as a library |
890 | | // (through LOKit - for example on Android) even when we don't show |
891 | | // the handles, because the hit test would always return false. |
892 | | // |
893 | | // This HACK replaces the empty bitmap with a black 13x13 bitmap handle |
894 | | // so that the hit test works for this case. |
895 | 0 | if (aBmp.IsEmpty()) |
896 | 0 | { |
897 | 0 | aBmp = Bitmap(Size(13, 13), vcl::PixelFormat::N24_BPP); |
898 | 0 | aBmp.Erase(COL_BLACK); |
899 | 0 | } |
900 | |
|
901 | 0 | if(eKindOfMarker == BitmapMarkerKind::Anchor || eKindOfMarker == BitmapMarkerKind::AnchorPressed) |
902 | 0 | { |
903 | | // upper left as reference point inside the handle for AnchorPressed, too |
904 | 0 | pRetval.reset(new sdr::overlay::OverlayBitmapEx(rPos, aBmp)); |
905 | 0 | } |
906 | 0 | else if(eKindOfMarker == BitmapMarkerKind::AnchorTR || eKindOfMarker == BitmapMarkerKind::AnchorPressedTR) |
907 | 0 | { |
908 | | // AnchorTR for SW, take top right as (0,0) |
909 | 0 | pRetval.reset(new sdr::overlay::OverlayBitmapEx(rPos, aBmp, |
910 | 0 | static_cast<sal_uInt16>(aBmp.GetSizePixel().Width() - 1), 0)); |
911 | 0 | } |
912 | 0 | else |
913 | 0 | { |
914 | 0 | sal_uInt16 nCenX(static_cast<sal_uInt16>(aBmp.GetSizePixel().Width() - 1) >> 1); |
915 | 0 | sal_uInt16 nCenY(static_cast<sal_uInt16>(aBmp.GetSizePixel().Height() - 1) >> 1); |
916 | |
|
917 | 0 | if(aMoveOutsideOffset.X() > 0) |
918 | 0 | { |
919 | 0 | nCenX = 0; |
920 | 0 | } |
921 | 0 | else if(aMoveOutsideOffset.X() < 0) |
922 | 0 | { |
923 | 0 | nCenX = static_cast<sal_uInt16>(aBmp.GetSizePixel().Width() - 1); |
924 | 0 | } |
925 | |
|
926 | 0 | if(aMoveOutsideOffset.Y() > 0) |
927 | 0 | { |
928 | 0 | nCenY = 0; |
929 | 0 | } |
930 | 0 | else if(aMoveOutsideOffset.Y() < 0) |
931 | 0 | { |
932 | 0 | nCenY = static_cast<sal_uInt16>(aBmp.GetSizePixel().Height() - 1); |
933 | 0 | } |
934 | | |
935 | | // create centered handle as default |
936 | 0 | pRetval.reset(new sdr::overlay::OverlayBitmapEx(rPos, aBmp, nCenX, nCenY)); |
937 | 0 | } |
938 | 0 | } |
939 | | |
940 | 0 | return pRetval; |
941 | 0 | } |
942 | | |
943 | | bool SdrHdl::IsHdlHit(const Point& rPnt) const |
944 | 0 | { |
945 | | // OVERLAYMANAGER |
946 | 0 | basegfx::B2DPoint aPosition(rPnt.X(), rPnt.Y()); |
947 | 0 | return maOverlayGroup.isHitLogic(aPosition); |
948 | 0 | } |
949 | | |
950 | | PointerStyle SdrHdl::GetPointer() const |
951 | 0 | { |
952 | 0 | PointerStyle ePtr=PointerStyle::Move; |
953 | 0 | const bool bSize=m_eKind>=SdrHdlKind::UpperLeft && m_eKind<=SdrHdlKind::LowerRight; |
954 | 0 | const bool bRot=m_pHdlList!=nullptr && m_pHdlList->IsRotateShear(); |
955 | 0 | const bool bDis=m_pHdlList!=nullptr && m_pHdlList->IsDistortShear(); |
956 | 0 | if (bSize && m_pHdlList!=nullptr && (bRot || bDis)) { |
957 | 0 | switch (m_eKind) { |
958 | 0 | case SdrHdlKind::UpperLeft: case SdrHdlKind::UpperRight: |
959 | 0 | case SdrHdlKind::LowerLeft: case SdrHdlKind::LowerRight: ePtr=bRot ? PointerStyle::Rotate : PointerStyle::RefHand; break; |
960 | 0 | case SdrHdlKind::Left : case SdrHdlKind::Right: ePtr=PointerStyle::VShear; break; |
961 | 0 | case SdrHdlKind::Upper: case SdrHdlKind::Lower: ePtr=PointerStyle::HShear; break; |
962 | 0 | default: |
963 | 0 | break; |
964 | 0 | } |
965 | 0 | } else { |
966 | | // When resizing rotated rectangles, rotate the mouse cursor slightly, too |
967 | 0 | if (bSize && m_nRotationAngle!=0_deg100) { |
968 | 0 | Degree100 nHdlAngle(0); |
969 | 0 | switch (m_eKind) { |
970 | 0 | case SdrHdlKind::LowerRight: nHdlAngle=31500_deg100; break; |
971 | 0 | case SdrHdlKind::Lower: nHdlAngle=27000_deg100; break; |
972 | 0 | case SdrHdlKind::LowerLeft: nHdlAngle=22500_deg100; break; |
973 | 0 | case SdrHdlKind::Left : nHdlAngle=18000_deg100; break; |
974 | 0 | case SdrHdlKind::UpperLeft: nHdlAngle=13500_deg100; break; |
975 | 0 | case SdrHdlKind::Upper: nHdlAngle=9000_deg100; break; |
976 | 0 | case SdrHdlKind::UpperRight: nHdlAngle=4500_deg100; break; |
977 | 0 | case SdrHdlKind::Right: nHdlAngle=0_deg100; break; |
978 | 0 | default: |
979 | 0 | break; |
980 | 0 | } |
981 | | // a little bit more (for rounding) |
982 | 0 | nHdlAngle = NormAngle36000(nHdlAngle + m_nRotationAngle + 2249_deg100); |
983 | 0 | nHdlAngle/=4500_deg100; |
984 | 0 | switch (static_cast<sal_uInt8>(nHdlAngle.get())) { |
985 | 0 | case 0: ePtr=PointerStyle::ESize; break; |
986 | 0 | case 1: ePtr=PointerStyle::NESize; break; |
987 | 0 | case 2: ePtr=PointerStyle::NSize; break; |
988 | 0 | case 3: ePtr=PointerStyle::NWSize; break; |
989 | 0 | case 4: ePtr=PointerStyle::WSize; break; |
990 | 0 | case 5: ePtr=PointerStyle::SWSize; break; |
991 | 0 | case 6: ePtr=PointerStyle::SSize; break; |
992 | 0 | case 7: ePtr=PointerStyle::SESize; break; |
993 | 0 | } // switch |
994 | 0 | } else { |
995 | 0 | switch (m_eKind) { |
996 | 0 | case SdrHdlKind::UpperLeft: ePtr=PointerStyle::NWSize; break; |
997 | 0 | case SdrHdlKind::Upper: ePtr=PointerStyle::NSize; break; |
998 | 0 | case SdrHdlKind::UpperRight: ePtr=PointerStyle::NESize; break; |
999 | 0 | case SdrHdlKind::Left : ePtr=PointerStyle::WSize; break; |
1000 | 0 | case SdrHdlKind::Right: ePtr=PointerStyle::ESize; break; |
1001 | 0 | case SdrHdlKind::LowerLeft: ePtr=PointerStyle::SWSize; break; |
1002 | 0 | case SdrHdlKind::Lower: ePtr=PointerStyle::SSize; break; |
1003 | 0 | case SdrHdlKind::LowerRight: ePtr=PointerStyle::SESize; break; |
1004 | 0 | case SdrHdlKind::Poly : ePtr=PointerStyle::MovePoint; break; |
1005 | 0 | case SdrHdlKind::Circle : ePtr=PointerStyle::Hand; break; |
1006 | 0 | case SdrHdlKind::Ref1 : ePtr=PointerStyle::RefHand; break; |
1007 | 0 | case SdrHdlKind::Ref2 : ePtr=PointerStyle::RefHand; break; |
1008 | 0 | case SdrHdlKind::BezierWeight : ePtr=PointerStyle::MoveBezierWeight; break; |
1009 | 0 | case SdrHdlKind::Glue : ePtr=PointerStyle::MovePoint; break; |
1010 | 0 | case SdrHdlKind::CustomShape1 : ePtr=PointerStyle::RefHand; break; |
1011 | 0 | default: |
1012 | 0 | break; |
1013 | 0 | } |
1014 | 0 | } |
1015 | 0 | } |
1016 | 0 | return ePtr; |
1017 | 0 | } |
1018 | | |
1019 | | bool SdrHdl::IsFocusHdl() const |
1020 | 0 | { |
1021 | 0 | switch(m_eKind) |
1022 | 0 | { |
1023 | 0 | case SdrHdlKind::UpperLeft: |
1024 | 0 | case SdrHdlKind::Upper: |
1025 | 0 | case SdrHdlKind::UpperRight: |
1026 | 0 | case SdrHdlKind::Left: |
1027 | 0 | case SdrHdlKind::Right: |
1028 | 0 | case SdrHdlKind::LowerLeft: |
1029 | 0 | case SdrHdlKind::Lower: |
1030 | 0 | case SdrHdlKind::LowerRight: |
1031 | 0 | { |
1032 | | // if it's an activated TextEdit, it's moved to extended points |
1033 | 0 | return !m_pHdlList || !m_pHdlList->IsMoveOutside(); |
1034 | 0 | } |
1035 | | |
1036 | 0 | case SdrHdlKind::Move: // handle to move object |
1037 | 0 | case SdrHdlKind::Poly: // selected point of polygon or curve |
1038 | 0 | case SdrHdlKind::BezierWeight: // weight at a curve |
1039 | 0 | case SdrHdlKind::Circle: // angle of circle segments, corner radius of rectangles |
1040 | 0 | case SdrHdlKind::Ref1: // reference point 1, e. g. center of rotation |
1041 | 0 | case SdrHdlKind::Ref2: // reference point 2, e. g. endpoint of reflection axis |
1042 | 0 | case SdrHdlKind::Glue: // gluepoint |
1043 | | |
1044 | | // for SJ and the CustomShapeHandles: |
1045 | 0 | case SdrHdlKind::CustomShape1: |
1046 | |
|
1047 | 0 | case SdrHdlKind::User: |
1048 | 0 | { |
1049 | 0 | return true; |
1050 | 0 | } |
1051 | | |
1052 | 0 | default: |
1053 | 0 | { |
1054 | 0 | return false; |
1055 | 0 | } |
1056 | 0 | } |
1057 | 0 | } |
1058 | | |
1059 | | void SdrHdl::onMouseEnter(const MouseEvent& /*rMEvt*/) |
1060 | 0 | { |
1061 | 0 | } |
1062 | | |
1063 | | void SdrHdl::onHelpRequest() |
1064 | 0 | { |
1065 | 0 | } |
1066 | | |
1067 | | void SdrHdl::onMouseLeave() |
1068 | 0 | { |
1069 | 0 | } |
1070 | | |
1071 | | Bitmap SdrHdl::createGluePointBitmap() |
1072 | 0 | { |
1073 | 0 | return ImpGetBitmap(BitmapMarkerKind::Glue_Deselected, BitmapColorIndex::LightGreen); |
1074 | 0 | } |
1075 | | |
1076 | | void SdrHdl::insertNewlyCreatedOverlayObjectForSdrHdl( |
1077 | | std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject, |
1078 | | const sdr::contact::ObjectContact& rObjectContact, |
1079 | | sdr::overlay::OverlayManager& rOverlayManager) |
1080 | 0 | { |
1081 | | // check if we have an OverlayObject |
1082 | 0 | if(!pOverlayObject) |
1083 | 0 | { |
1084 | 0 | return; |
1085 | 0 | } |
1086 | | |
1087 | | // Add GridOffset for non-linear ViewToDevice transformation (calc) |
1088 | 0 | if(nullptr != GetObj() && rObjectContact.supportsGridOffsets()) |
1089 | 0 | { |
1090 | 0 | basegfx::B2DVector aOffset(0.0, 0.0); |
1091 | 0 | const sdr::contact::ViewObjectContact& rVOC(GetObj()->GetViewContact().GetViewObjectContact( |
1092 | 0 | const_cast<sdr::contact::ObjectContact&>(rObjectContact))); |
1093 | |
|
1094 | 0 | rObjectContact.calculateGridOffsetForViewObjectContact(aOffset, rVOC); |
1095 | |
|
1096 | 0 | if(!aOffset.equalZero()) |
1097 | 0 | { |
1098 | 0 | pOverlayObject->setOffset(aOffset); |
1099 | 0 | } |
1100 | 0 | } |
1101 | | |
1102 | | // add to OverlayManager |
1103 | 0 | rOverlayManager.add(*pOverlayObject); |
1104 | | |
1105 | | // add to local OverlayObjectList - ownership change (!) |
1106 | 0 | maOverlayGroup.append(std::move(pOverlayObject)); |
1107 | 0 | } |
1108 | | |
1109 | | SdrHdlColor::SdrHdlColor(const Point& rRef, Color aCol, const Size& rSize, bool bLum) |
1110 | 0 | : SdrHdl(rRef, SdrHdlKind::Color), |
1111 | 0 | m_aMarkerSize(rSize), |
1112 | 0 | m_bUseLuminance(bLum) |
1113 | 0 | { |
1114 | 0 | if(IsUseLuminance()) |
1115 | 0 | aCol = GetLuminance(aCol); |
1116 | | |
1117 | | // remember color |
1118 | 0 | m_aMarkerColor = aCol; |
1119 | 0 | } |
1120 | | |
1121 | | SdrHdlColor::~SdrHdlColor() |
1122 | | { |
1123 | | } |
1124 | | |
1125 | | void SdrHdlColor::CreateB2dIAObject() |
1126 | 0 | { |
1127 | | // first throw away old one |
1128 | 0 | GetRidOfIAObject(); |
1129 | |
|
1130 | 0 | if(!m_pHdlList) |
1131 | 0 | return; |
1132 | | |
1133 | 0 | SdrMarkView* pView = m_pHdlList->GetView(); |
1134 | |
|
1135 | 0 | if(!pView || pView->areMarkHandlesHidden()) |
1136 | 0 | return; |
1137 | | |
1138 | 0 | SdrPageView* pPageView = pView->GetSdrPageView(); |
1139 | |
|
1140 | 0 | if(!pPageView) |
1141 | 0 | return; |
1142 | | |
1143 | 0 | for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++) |
1144 | 0 | { |
1145 | 0 | const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); |
1146 | |
|
1147 | 0 | if(rPageWindow.GetPaintWindow().OutputToWindow()) |
1148 | 0 | { |
1149 | 0 | const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager(); |
1150 | 0 | if (xManager.is()) |
1151 | 0 | { |
1152 | 0 | Bitmap aBmpCol(CreateColorDropper(m_aMarkerColor)); |
1153 | 0 | basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y()); |
1154 | 0 | std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new |
1155 | 0 | sdr::overlay::OverlayBitmapEx( |
1156 | 0 | aPosition, |
1157 | 0 | aBmpCol, |
1158 | 0 | static_cast<sal_uInt16>(aBmpCol.GetSizePixel().Width() - 1) >> 1, |
1159 | 0 | static_cast<sal_uInt16>(aBmpCol.GetSizePixel().Height() - 1) >> 1 |
1160 | 0 | )); |
1161 | | |
1162 | | // OVERLAYMANAGER |
1163 | 0 | insertNewlyCreatedOverlayObjectForSdrHdl( |
1164 | 0 | std::move(pNewOverlayObject), |
1165 | 0 | rPageWindow.GetObjectContact(), |
1166 | 0 | *xManager); |
1167 | 0 | } |
1168 | 0 | } |
1169 | 0 | } |
1170 | 0 | } |
1171 | | |
1172 | | Bitmap SdrHdlColor::CreateColorDropper(Color aCol) |
1173 | 0 | { |
1174 | | // get the Bitmap |
1175 | 0 | VclPtr<VirtualDevice> pWrite(VclPtr<VirtualDevice>::Create()); |
1176 | 0 | pWrite->SetOutputSizePixel(m_aMarkerSize); |
1177 | 0 | pWrite->SetBackground(aCol); |
1178 | 0 | pWrite->Erase(); |
1179 | | |
1180 | | // draw outer border |
1181 | 0 | sal_Int32 nWidth = m_aMarkerSize.Width(); |
1182 | 0 | sal_Int32 nHeight = m_aMarkerSize.Height(); |
1183 | |
|
1184 | 0 | pWrite->SetLineColor(COL_LIGHTGRAY); |
1185 | 0 | pWrite->DrawLine(Point(0, 0), Point(0, nHeight - 1)); |
1186 | 0 | pWrite->DrawLine(Point(1, 0), Point(nWidth - 1, 0)); |
1187 | 0 | pWrite->SetLineColor(COL_GRAY); |
1188 | 0 | pWrite->DrawLine(Point(1, nHeight - 1), Point(nWidth - 1, nHeight - 1)); |
1189 | 0 | pWrite->DrawLine(Point(nWidth - 1, 1), Point(nWidth - 1, nHeight - 2)); |
1190 | | |
1191 | | // draw lighter UpperLeft |
1192 | 0 | const Color aLightColor( |
1193 | 0 | static_cast<sal_uInt8>(::std::min(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetRed()) + sal_Int16(0x0040)), sal_Int16(0x00ff))), |
1194 | 0 | static_cast<sal_uInt8>(::std::min(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetGreen()) + sal_Int16(0x0040)), sal_Int16(0x00ff))), |
1195 | 0 | static_cast<sal_uInt8>(::std::min(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetBlue()) + sal_Int16(0x0040)), sal_Int16(0x00ff)))); |
1196 | 0 | pWrite->SetLineColor(aLightColor); |
1197 | 0 | pWrite->DrawLine(Point(1, 1), Point(1, nHeight - 2)); |
1198 | 0 | pWrite->DrawLine(Point(2, 1), Point(nWidth - 2, 1)); |
1199 | | |
1200 | | // draw darker LowerRight |
1201 | 0 | const Color aDarkColor( |
1202 | 0 | static_cast<sal_uInt8>(::std::max(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetRed()) - sal_Int16(0x0040)), sal_Int16(0x0000))), |
1203 | 0 | static_cast<sal_uInt8>(::std::max(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetGreen()) - sal_Int16(0x0040)), sal_Int16(0x0000))), |
1204 | 0 | static_cast<sal_uInt8>(::std::max(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetBlue()) - sal_Int16(0x0040)), sal_Int16(0x0000)))); |
1205 | 0 | pWrite->SetLineColor(aDarkColor); |
1206 | 0 | pWrite->DrawLine(Point(2, nHeight - 2), Point(nWidth - 2, nHeight - 2)); |
1207 | 0 | pWrite->DrawLine(Point(nWidth - 2, 2), Point(nWidth - 2, nHeight - 3)); |
1208 | |
|
1209 | 0 | return pWrite->GetBitmap(Point(0,0), m_aMarkerSize); |
1210 | 0 | } |
1211 | | |
1212 | | Color SdrHdlColor::GetLuminance(const Color& rCol) |
1213 | 0 | { |
1214 | 0 | sal_uInt8 aLum = rCol.GetLuminance(); |
1215 | 0 | Color aRetval(aLum, aLum, aLum); |
1216 | 0 | return aRetval; |
1217 | 0 | } |
1218 | | |
1219 | | void SdrHdlColor::SetColor(Color aNew, bool bCallLink) |
1220 | 0 | { |
1221 | 0 | if(IsUseLuminance()) |
1222 | 0 | aNew = GetLuminance(aNew); |
1223 | |
|
1224 | 0 | if(m_aMarkerColor != aNew) |
1225 | 0 | { |
1226 | | // remember new color |
1227 | 0 | m_aMarkerColor = aNew; |
1228 | | |
1229 | | // create new display |
1230 | 0 | Touch(); |
1231 | | |
1232 | | // tell about change |
1233 | 0 | if(bCallLink) |
1234 | 0 | m_aColorChangeHdl.Call(this); |
1235 | 0 | } |
1236 | 0 | } |
1237 | | |
1238 | | void SdrHdlColor::SetSize(const Size& rNew) |
1239 | 0 | { |
1240 | 0 | if(rNew != m_aMarkerSize) |
1241 | 0 | { |
1242 | | // remember new size |
1243 | 0 | m_aMarkerSize = rNew; |
1244 | | |
1245 | | // create new display |
1246 | 0 | Touch(); |
1247 | 0 | } |
1248 | 0 | } |
1249 | | |
1250 | | SdrHdlGradient::SdrHdlGradient(const Point& rRef1, const Point& rRef2, bool bGrad) |
1251 | 0 | : SdrHdl(rRef1, bGrad ? SdrHdlKind::Gradient : SdrHdlKind::Transparence) |
1252 | 0 | , m_pColHdl1(nullptr) |
1253 | 0 | , m_pColHdl2(nullptr) |
1254 | 0 | , m_a2ndPos(rRef2) |
1255 | 0 | , m_bGradient(bGrad) |
1256 | 0 | , m_bMoveSingleHandle(false) |
1257 | 0 | , m_bMoveFirstHandle(false) |
1258 | 0 | { |
1259 | 0 | } |
1260 | | |
1261 | | SdrHdlGradient::~SdrHdlGradient() |
1262 | | { |
1263 | | } |
1264 | | |
1265 | | void SdrHdlGradient::Set2ndPos(const Point& rPnt) |
1266 | 0 | { |
1267 | 0 | if(m_a2ndPos != rPnt) |
1268 | 0 | { |
1269 | | // remember new position |
1270 | 0 | m_a2ndPos = rPnt; |
1271 | | |
1272 | | // create new display |
1273 | 0 | Touch(); |
1274 | 0 | } |
1275 | 0 | } |
1276 | | |
1277 | | void SdrHdlGradient::CreateB2dIAObject() |
1278 | 0 | { |
1279 | | // first throw away old one |
1280 | 0 | GetRidOfIAObject(); |
1281 | |
|
1282 | 0 | if(!m_pHdlList) |
1283 | 0 | return; |
1284 | | |
1285 | 0 | SdrMarkView* pView = m_pHdlList->GetView(); |
1286 | |
|
1287 | 0 | if(!pView || pView->areMarkHandlesHidden()) |
1288 | 0 | return; |
1289 | | |
1290 | 0 | SdrPageView* pPageView = pView->GetSdrPageView(); |
1291 | |
|
1292 | 0 | if(!pPageView) |
1293 | 0 | return; |
1294 | | |
1295 | 0 | for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++) |
1296 | 0 | { |
1297 | 0 | const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); |
1298 | |
|
1299 | 0 | if(rPageWindow.GetPaintWindow().OutputToWindow()) |
1300 | 0 | { |
1301 | 0 | const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager(); |
1302 | 0 | if (xManager.is()) |
1303 | 0 | { |
1304 | | // striped line in between |
1305 | 0 | basegfx::B2DVector aVec(m_a2ndPos.X() - m_aPos.X(), m_a2ndPos.Y() - m_aPos.Y()); |
1306 | 0 | double fVecLen = aVec.getLength(); |
1307 | 0 | double fLongPercentArrow = (1.0 - 0.05) * fVecLen; |
1308 | 0 | double fHalfArrowWidth = (0.05 * 0.5) * fVecLen; |
1309 | 0 | aVec.normalize(); |
1310 | 0 | basegfx::B2DVector aPerpend(-aVec.getY(), aVec.getX()); |
1311 | 0 | sal_Int32 nMidX = static_cast<sal_Int32>(m_aPos.X() + aVec.getX() * fLongPercentArrow); |
1312 | 0 | sal_Int32 nMidY = static_cast<sal_Int32>(m_aPos.Y() + aVec.getY() * fLongPercentArrow); |
1313 | 0 | Point aMidPoint(nMidX, nMidY); |
1314 | |
|
1315 | 0 | basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y()); |
1316 | 0 | basegfx::B2DPoint aMidPos(aMidPoint.X(), aMidPoint.Y()); |
1317 | |
|
1318 | 0 | std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new |
1319 | 0 | sdr::overlay::OverlayLineStriped( |
1320 | 0 | aPosition, aMidPos |
1321 | 0 | )); |
1322 | |
|
1323 | 0 | pNewOverlayObject->setBaseColor(IsGradient() ? COL_BLACK : COL_BLUE); |
1324 | | |
1325 | | // OVERLAYMANAGER |
1326 | 0 | insertNewlyCreatedOverlayObjectForSdrHdl( |
1327 | 0 | std::move(pNewOverlayObject), |
1328 | 0 | rPageWindow.GetObjectContact(), |
1329 | 0 | *xManager); |
1330 | | |
1331 | | // arrowhead |
1332 | 0 | Point aLeft(aMidPoint.X() + static_cast<sal_Int32>(aPerpend.getX() * fHalfArrowWidth), |
1333 | 0 | aMidPoint.Y() + static_cast<sal_Int32>(aPerpend.getY() * fHalfArrowWidth)); |
1334 | 0 | Point aRight(aMidPoint.X() - static_cast<sal_Int32>(aPerpend.getX() * fHalfArrowWidth), |
1335 | 0 | aMidPoint.Y() - static_cast<sal_Int32>(aPerpend.getY() * fHalfArrowWidth)); |
1336 | |
|
1337 | 0 | basegfx::B2DPoint aPositionLeft(aLeft.X(), aLeft.Y()); |
1338 | 0 | basegfx::B2DPoint aPositionRight(aRight.X(), aRight.Y()); |
1339 | 0 | basegfx::B2DPoint aPosition2(m_a2ndPos.X(), m_a2ndPos.Y()); |
1340 | |
|
1341 | 0 | pNewOverlayObject.reset(new |
1342 | 0 | sdr::overlay::OverlayTriangle( |
1343 | 0 | aPositionLeft, |
1344 | 0 | aPosition2, |
1345 | 0 | aPositionRight, |
1346 | 0 | IsGradient() ? COL_BLACK : COL_BLUE |
1347 | 0 | )); |
1348 | | |
1349 | | // OVERLAYMANAGER |
1350 | 0 | insertNewlyCreatedOverlayObjectForSdrHdl( |
1351 | 0 | std::move(pNewOverlayObject), |
1352 | 0 | rPageWindow.GetObjectContact(), |
1353 | 0 | *xManager); |
1354 | 0 | } |
1355 | 0 | } |
1356 | 0 | } |
1357 | 0 | } |
1358 | | |
1359 | | IMPL_LINK_NOARG(SdrHdlGradient, ColorChangeHdl, SdrHdlColor*, void) |
1360 | 0 | { |
1361 | 0 | if(GetObj()) |
1362 | 0 | FromIAOToItem(GetObj(), true, true); |
1363 | 0 | } |
1364 | | |
1365 | | void SdrHdlGradient::FromIAOToItem(SdrObject* _pObj, bool bSetItemOnObject, bool bUndo) |
1366 | 0 | { |
1367 | | // from IAO positions and colors to gradient |
1368 | 0 | const SfxItemSet& rSet = _pObj->GetMergedItemSet(); |
1369 | |
|
1370 | 0 | GradTransGradient aOldGradTransGradient; |
1371 | 0 | GradTransGradient aGradTransGradient; |
1372 | 0 | GradTransVector aGradTransVector; |
1373 | |
|
1374 | 0 | aGradTransVector.maPositionA = basegfx::B2DPoint(GetPos().X(), GetPos().Y()); |
1375 | 0 | aGradTransVector.maPositionB = basegfx::B2DPoint(Get2ndPos().X(), Get2ndPos().Y()); |
1376 | 0 | if(m_pColHdl1) |
1377 | 0 | aGradTransVector.aCol1 = m_pColHdl1->GetColor(); |
1378 | 0 | if(m_pColHdl2) |
1379 | 0 | aGradTransVector.aCol2 = m_pColHdl2->GetColor(); |
1380 | |
|
1381 | 0 | if(IsGradient()) |
1382 | 0 | aOldGradTransGradient.aGradient = rSet.Get(XATTR_FILLGRADIENT).GetGradientValue(); |
1383 | 0 | else |
1384 | 0 | aOldGradTransGradient.aGradient = rSet.Get(XATTR_FILLFLOATTRANSPARENCE).GetGradientValue(); |
1385 | | |
1386 | | // transform vector data to gradient |
1387 | 0 | GradTransformer::VecToGrad(aGradTransVector, aGradTransGradient, aOldGradTransGradient, _pObj, m_bMoveSingleHandle, m_bMoveFirstHandle); |
1388 | |
|
1389 | 0 | if(bSetItemOnObject) |
1390 | 0 | { |
1391 | 0 | SdrModel& rModel(_pObj->getSdrModelFromSdrObject()); |
1392 | 0 | SfxItemSet aNewSet(rModel.GetItemPool()); |
1393 | 0 | const OUString aString; |
1394 | |
|
1395 | 0 | if(IsGradient()) |
1396 | 0 | { |
1397 | 0 | XFillGradientItem aNewGradItem(aString, aGradTransGradient.aGradient); |
1398 | 0 | aNewSet.Put(aNewGradItem); |
1399 | 0 | } |
1400 | 0 | else |
1401 | 0 | { |
1402 | 0 | XFillFloatTransparenceItem aNewTransItem(aString, aGradTransGradient.aGradient); |
1403 | 0 | aNewSet.Put(aNewTransItem); |
1404 | 0 | } |
1405 | |
|
1406 | 0 | if(bUndo && rModel.IsUndoEnabled()) |
1407 | 0 | { |
1408 | 0 | rModel.BegUndo(SvxResId(IsGradient() ? SIP_XA_FILLGRADIENT : SIP_XA_FILLTRANSPARENCE)); |
1409 | 0 | rModel.AddUndo(rModel.GetSdrUndoFactory().CreateUndoAttrObject(*_pObj)); |
1410 | 0 | rModel.EndUndo(); |
1411 | 0 | } |
1412 | |
|
1413 | 0 | m_pObj->SetMergedItemSetAndBroadcast(aNewSet); |
1414 | 0 | } |
1415 | | |
1416 | | // back transformation, set values on pIAOHandle |
1417 | 0 | GradTransformer::GradToVec(aGradTransGradient, aGradTransVector, _pObj); |
1418 | |
|
1419 | 0 | SetPos({ basegfx::fround<tools::Long>(aGradTransVector.maPositionA.getX()), |
1420 | 0 | basegfx::fround<tools::Long>(aGradTransVector.maPositionA.getY()) }); |
1421 | 0 | Set2ndPos({ basegfx::fround<tools::Long>(aGradTransVector.maPositionB.getX()), |
1422 | 0 | basegfx::fround<tools::Long>(aGradTransVector.maPositionB.getY()) }); |
1423 | 0 | if(m_pColHdl1) |
1424 | 0 | { |
1425 | 0 | m_pColHdl1->SetPos({ basegfx::fround<tools::Long>(aGradTransVector.maPositionA.getX()), |
1426 | 0 | basegfx::fround<tools::Long>(aGradTransVector.maPositionA.getY()) }); |
1427 | 0 | m_pColHdl1->SetColor(aGradTransVector.aCol1); |
1428 | 0 | } |
1429 | 0 | if(m_pColHdl2) |
1430 | 0 | { |
1431 | 0 | m_pColHdl2->SetPos({ basegfx::fround<tools::Long>(aGradTransVector.maPositionB.getX()), |
1432 | 0 | basegfx::fround<tools::Long>(aGradTransVector.maPositionB.getY()) }); |
1433 | 0 | m_pColHdl2->SetColor(aGradTransVector.aCol2); |
1434 | 0 | } |
1435 | 0 | } |
1436 | | |
1437 | | |
1438 | | SdrHdlLine::~SdrHdlLine() {} |
1439 | | |
1440 | | void SdrHdlLine::CreateB2dIAObject() |
1441 | 0 | { |
1442 | | // first throw away old one |
1443 | 0 | GetRidOfIAObject(); |
1444 | |
|
1445 | 0 | if(!m_pHdlList) |
1446 | 0 | return; |
1447 | | |
1448 | 0 | SdrMarkView* pView = m_pHdlList->GetView(); |
1449 | |
|
1450 | 0 | if(!(pView && !pView->areMarkHandlesHidden() && m_pHdl1 && m_pHdl2)) |
1451 | 0 | return; |
1452 | | |
1453 | 0 | SdrPageView* pPageView = pView->GetSdrPageView(); |
1454 | |
|
1455 | 0 | if(!pPageView) |
1456 | 0 | return; |
1457 | | |
1458 | 0 | for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++) |
1459 | 0 | { |
1460 | 0 | const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); |
1461 | |
|
1462 | 0 | if(rPageWindow.GetPaintWindow().OutputToWindow()) |
1463 | 0 | { |
1464 | 0 | const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager(); |
1465 | 0 | if (xManager.is()) |
1466 | 0 | { |
1467 | 0 | basegfx::B2DPoint aPosition1(m_pHdl1->GetPos().X(), m_pHdl1->GetPos().Y()); |
1468 | 0 | basegfx::B2DPoint aPosition2(m_pHdl2->GetPos().X(), m_pHdl2->GetPos().Y()); |
1469 | |
|
1470 | 0 | std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new |
1471 | 0 | sdr::overlay::OverlayLineStriped( |
1472 | 0 | aPosition1, |
1473 | 0 | aPosition2 |
1474 | 0 | )); |
1475 | | |
1476 | | // color(?) |
1477 | 0 | pNewOverlayObject->setBaseColor(COL_LIGHTRED); |
1478 | | |
1479 | | // OVERLAYMANAGER |
1480 | 0 | insertNewlyCreatedOverlayObjectForSdrHdl( |
1481 | 0 | std::move(pNewOverlayObject), |
1482 | 0 | rPageWindow.GetObjectContact(), |
1483 | 0 | *xManager); |
1484 | 0 | } |
1485 | 0 | } |
1486 | 0 | } |
1487 | 0 | } |
1488 | | |
1489 | | PointerStyle SdrHdlLine::GetPointer() const |
1490 | 0 | { |
1491 | 0 | return PointerStyle::RefHand; |
1492 | 0 | } |
1493 | | |
1494 | | |
1495 | | SdrHdlBezWgt::~SdrHdlBezWgt() {} |
1496 | | |
1497 | | void SdrHdlBezWgt::CreateB2dIAObject() |
1498 | 0 | { |
1499 | | // call parent |
1500 | 0 | SdrHdl::CreateB2dIAObject(); |
1501 | | |
1502 | | // create lines |
1503 | 0 | if(!m_pHdlList) |
1504 | 0 | return; |
1505 | | |
1506 | 0 | SdrMarkView* pView = m_pHdlList->GetView(); |
1507 | |
|
1508 | 0 | if(!pView || pView->areMarkHandlesHidden()) |
1509 | 0 | return; |
1510 | | |
1511 | 0 | SdrPageView* pPageView = pView->GetSdrPageView(); |
1512 | |
|
1513 | 0 | if(!pPageView) |
1514 | 0 | return; |
1515 | | |
1516 | 0 | for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++) |
1517 | 0 | { |
1518 | 0 | const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); |
1519 | |
|
1520 | 0 | if(rPageWindow.GetPaintWindow().OutputToWindow()) |
1521 | 0 | { |
1522 | 0 | const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager(); |
1523 | 0 | if (xManager.is()) |
1524 | 0 | { |
1525 | 0 | basegfx::B2DPoint aPosition1(m_pHdl1->GetPos().X(), m_pHdl1->GetPos().Y()); |
1526 | 0 | basegfx::B2DPoint aPosition2(m_aPos.X(), m_aPos.Y()); |
1527 | |
|
1528 | 0 | if(!aPosition1.equal(aPosition2)) |
1529 | 0 | { |
1530 | 0 | std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new |
1531 | 0 | sdr::overlay::OverlayLineStriped( |
1532 | 0 | aPosition1, |
1533 | 0 | aPosition2 |
1534 | 0 | )); |
1535 | | |
1536 | | // line part is not hittable |
1537 | 0 | pNewOverlayObject->setHittable(false); |
1538 | | |
1539 | | // color(?) |
1540 | 0 | pNewOverlayObject->setBaseColor(COL_LIGHTBLUE); |
1541 | | |
1542 | | // OVERLAYMANAGER |
1543 | 0 | insertNewlyCreatedOverlayObjectForSdrHdl( |
1544 | 0 | std::move(pNewOverlayObject), |
1545 | 0 | rPageWindow.GetObjectContact(), |
1546 | 0 | *xManager); |
1547 | 0 | } |
1548 | 0 | } |
1549 | 0 | } |
1550 | 0 | } |
1551 | 0 | } |
1552 | | |
1553 | | |
1554 | | E3dVolumeMarker::E3dVolumeMarker(const basegfx::B2DPolyPolygon& rWireframePoly) |
1555 | 0 | { |
1556 | 0 | m_aWireframePoly = rWireframePoly; |
1557 | 0 | } |
1558 | | |
1559 | | void E3dVolumeMarker::CreateB2dIAObject() |
1560 | 0 | { |
1561 | | // create lines |
1562 | 0 | if(!m_pHdlList) |
1563 | 0 | return; |
1564 | | |
1565 | 0 | SdrMarkView* pView = m_pHdlList->GetView(); |
1566 | |
|
1567 | 0 | if(!pView || pView->areMarkHandlesHidden()) |
1568 | 0 | return; |
1569 | | |
1570 | 0 | SdrPageView* pPageView = pView->GetSdrPageView(); |
1571 | |
|
1572 | 0 | if(!pPageView) |
1573 | 0 | return; |
1574 | | |
1575 | 0 | for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++) |
1576 | 0 | { |
1577 | 0 | const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); |
1578 | |
|
1579 | 0 | if(rPageWindow.GetPaintWindow().OutputToWindow()) |
1580 | 0 | { |
1581 | 0 | const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager(); |
1582 | 0 | if (xManager.is() && m_aWireframePoly.count()) |
1583 | 0 | { |
1584 | 0 | std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new |
1585 | 0 | sdr::overlay::OverlayPolyPolygonStripedAndFilled( |
1586 | 0 | m_aWireframePoly)); |
1587 | |
|
1588 | 0 | pNewOverlayObject->setBaseColor(COL_BLACK); |
1589 | | |
1590 | | // OVERLAYMANAGER |
1591 | 0 | insertNewlyCreatedOverlayObjectForSdrHdl( |
1592 | 0 | std::move(pNewOverlayObject), |
1593 | 0 | rPageWindow.GetObjectContact(), |
1594 | 0 | *xManager); |
1595 | 0 | } |
1596 | 0 | } |
1597 | 0 | } |
1598 | 0 | } |
1599 | | |
1600 | | |
1601 | | ImpEdgeHdl::~ImpEdgeHdl() |
1602 | | { |
1603 | | } |
1604 | | |
1605 | | void ImpEdgeHdl::CreateB2dIAObject() |
1606 | 0 | { |
1607 | 0 | if(m_nObjHdlNum > 1 || !m_pObj) |
1608 | 0 | { |
1609 | | // call parent |
1610 | 0 | SdrHdl::CreateB2dIAObject(); |
1611 | 0 | return; |
1612 | 0 | } |
1613 | | |
1614 | | // first throw away old one |
1615 | 0 | GetRidOfIAObject(); |
1616 | |
|
1617 | 0 | BitmapColorIndex eColIndex = BitmapColorIndex::LightCyan; |
1618 | 0 | BitmapMarkerKind eKindOfMarker = BitmapMarkerKind::Rect_7x7; |
1619 | |
|
1620 | 0 | if(!m_pHdlList) |
1621 | 0 | return; |
1622 | | |
1623 | 0 | SdrMarkView* pView = m_pHdlList->GetView(); |
1624 | |
|
1625 | 0 | if(!pView || pView->areMarkHandlesHidden()) |
1626 | 0 | return; |
1627 | | |
1628 | | // tdf#159666 Crash when table and line object are selected at the same time |
1629 | 0 | auto pEdge = dynamic_cast<SdrEdgeObj*>(m_pObj); |
1630 | 0 | if (!pEdge) |
1631 | 0 | return; |
1632 | | |
1633 | 0 | if(pEdge->GetConnectedNode(m_nObjHdlNum == 0) != nullptr) |
1634 | 0 | eColIndex = BitmapColorIndex::LightRed; |
1635 | |
|
1636 | 0 | if(m_nPPntNum < 2) |
1637 | 0 | { |
1638 | | // Handle with plus sign inside |
1639 | 0 | eKindOfMarker = BitmapMarkerKind::Circ_7x7; |
1640 | 0 | } |
1641 | |
|
1642 | 0 | SdrPageView* pPageView = pView->GetSdrPageView(); |
1643 | 0 | if(!pPageView) |
1644 | 0 | return; |
1645 | | |
1646 | 0 | for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++) |
1647 | 0 | { |
1648 | 0 | const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); |
1649 | |
|
1650 | 0 | if(rPageWindow.GetPaintWindow().OutputToWindow()) |
1651 | 0 | { |
1652 | 0 | const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager(); |
1653 | 0 | if (xManager.is()) |
1654 | 0 | { |
1655 | 0 | basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y()); |
1656 | 0 | std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(CreateOverlayObject( |
1657 | 0 | aPosition, |
1658 | 0 | eColIndex, |
1659 | 0 | eKindOfMarker)); |
1660 | | |
1661 | | // OVERLAYMANAGER |
1662 | 0 | insertNewlyCreatedOverlayObjectForSdrHdl( |
1663 | 0 | std::move(pNewOverlayObject), |
1664 | 0 | rPageWindow.GetObjectContact(), |
1665 | 0 | *xManager); |
1666 | 0 | } |
1667 | 0 | } |
1668 | 0 | } |
1669 | 0 | } |
1670 | | |
1671 | | void ImpEdgeHdl::SetLineCode(SdrEdgeLineCode eCode) |
1672 | 0 | { |
1673 | 0 | if(m_eLineCode != eCode) |
1674 | 0 | { |
1675 | | // remember new value |
1676 | 0 | m_eLineCode = eCode; |
1677 | | |
1678 | | // create new display |
1679 | 0 | Touch(); |
1680 | 0 | } |
1681 | 0 | } |
1682 | | |
1683 | | PointerStyle ImpEdgeHdl::GetPointer() const |
1684 | 0 | { |
1685 | 0 | SdrEdgeObj* pEdge=dynamic_cast<SdrEdgeObj*>( m_pObj ); |
1686 | 0 | if (pEdge==nullptr) |
1687 | 0 | return SdrHdl::GetPointer(); |
1688 | 0 | if (m_nObjHdlNum<=1) |
1689 | 0 | return PointerStyle::MovePoint; |
1690 | 0 | if (IsHorzDrag()) |
1691 | 0 | return PointerStyle::ESize; |
1692 | 0 | else |
1693 | 0 | return PointerStyle::SSize; |
1694 | 0 | } |
1695 | | |
1696 | | bool ImpEdgeHdl::IsHorzDrag() const |
1697 | 0 | { |
1698 | 0 | SdrEdgeObj* pEdge=dynamic_cast<SdrEdgeObj*>( m_pObj ); |
1699 | 0 | if (pEdge==nullptr) |
1700 | 0 | return false; |
1701 | 0 | if (m_nObjHdlNum<=1) |
1702 | 0 | return false; |
1703 | | |
1704 | 0 | SdrEdgeKind eEdgeKind = pEdge->GetObjectItem(SDRATTR_EDGEKIND).GetValue(); |
1705 | |
|
1706 | 0 | const SdrEdgeInfoRec& rInfo=pEdge->m_aEdgeInfo; |
1707 | 0 | if (eEdgeKind==SdrEdgeKind::OrthoLines || eEdgeKind==SdrEdgeKind::Bezier) |
1708 | 0 | { |
1709 | 0 | return !rInfo.ImpIsHorzLine(m_eLineCode,*pEdge->m_pEdgeTrack); |
1710 | 0 | } |
1711 | 0 | else if (eEdgeKind==SdrEdgeKind::ThreeLines) |
1712 | 0 | { |
1713 | 0 | tools::Long nAngle=m_nObjHdlNum==2 ? rInfo.m_nAngle1 : rInfo.m_nAngle2; |
1714 | 0 | return nAngle==0 || nAngle==18000; |
1715 | 0 | } |
1716 | 0 | return false; |
1717 | 0 | } |
1718 | | |
1719 | | |
1720 | | ImpMeasureHdl::~ImpMeasureHdl() |
1721 | | { |
1722 | | } |
1723 | | |
1724 | | void ImpMeasureHdl::CreateB2dIAObject() |
1725 | 0 | { |
1726 | | // first throw away old one |
1727 | 0 | GetRidOfIAObject(); |
1728 | |
|
1729 | 0 | if(!m_pHdlList) |
1730 | 0 | return; |
1731 | | |
1732 | 0 | SdrMarkView* pView = m_pHdlList->GetView(); |
1733 | |
|
1734 | 0 | if(!pView || pView->areMarkHandlesHidden()) |
1735 | 0 | return; |
1736 | | |
1737 | 0 | BitmapColorIndex eColIndex = BitmapColorIndex::LightCyan; |
1738 | 0 | BitmapMarkerKind eKindOfMarker = BitmapMarkerKind::Rect_9x9; |
1739 | |
|
1740 | 0 | if(m_nObjHdlNum > 1) |
1741 | 0 | { |
1742 | 0 | eKindOfMarker = BitmapMarkerKind::Rect_7x7; |
1743 | 0 | } |
1744 | |
|
1745 | 0 | if(m_bSelect) |
1746 | 0 | { |
1747 | 0 | eColIndex = BitmapColorIndex::Cyan; |
1748 | 0 | } |
1749 | |
|
1750 | 0 | SdrPageView* pPageView = pView->GetSdrPageView(); |
1751 | |
|
1752 | 0 | if(!pPageView) |
1753 | 0 | return; |
1754 | | |
1755 | 0 | for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++) |
1756 | 0 | { |
1757 | 0 | const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); |
1758 | |
|
1759 | 0 | if(rPageWindow.GetPaintWindow().OutputToWindow()) |
1760 | 0 | { |
1761 | 0 | const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager(); |
1762 | 0 | if (xManager.is()) |
1763 | 0 | { |
1764 | 0 | basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y()); |
1765 | 0 | std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(CreateOverlayObject( |
1766 | 0 | aPosition, |
1767 | 0 | eColIndex, |
1768 | 0 | eKindOfMarker)); |
1769 | | |
1770 | | // OVERLAYMANAGER |
1771 | 0 | insertNewlyCreatedOverlayObjectForSdrHdl( |
1772 | 0 | std::move(pNewOverlayObject), |
1773 | 0 | rPageWindow.GetObjectContact(), |
1774 | 0 | *xManager); |
1775 | 0 | } |
1776 | 0 | } |
1777 | 0 | } |
1778 | 0 | } |
1779 | | |
1780 | | PointerStyle ImpMeasureHdl::GetPointer() const |
1781 | 0 | { |
1782 | 0 | switch (m_nObjHdlNum) |
1783 | 0 | { |
1784 | 0 | case 0: case 1: return PointerStyle::Hand; |
1785 | 0 | case 2: case 3: return PointerStyle::MovePoint; |
1786 | 0 | case 4: case 5: return SdrHdl::GetPointer(); // will then be rotated appropriately |
1787 | 0 | } // switch |
1788 | 0 | return PointerStyle::NotAllowed; |
1789 | 0 | } |
1790 | | |
1791 | | |
1792 | | ImpTextframeHdl::ImpTextframeHdl(const tools::Rectangle& rRect) : |
1793 | 0 | SdrHdl(rRect.TopLeft(),SdrHdlKind::Move), |
1794 | 0 | maRect(rRect) |
1795 | 0 | { |
1796 | 0 | } |
1797 | | |
1798 | | void ImpTextframeHdl::CreateB2dIAObject() |
1799 | 0 | { |
1800 | | // first throw away old one |
1801 | 0 | GetRidOfIAObject(); |
1802 | |
|
1803 | 0 | if(!m_pHdlList) |
1804 | 0 | return; |
1805 | | |
1806 | 0 | SdrMarkView* pView = m_pHdlList->GetView(); |
1807 | |
|
1808 | 0 | if(!pView || pView->areMarkHandlesHidden()) |
1809 | 0 | return; |
1810 | | |
1811 | 0 | SdrPageView* pPageView = pView->GetSdrPageView(); |
1812 | |
|
1813 | 0 | if(!pPageView) |
1814 | 0 | return; |
1815 | | |
1816 | 0 | for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++) |
1817 | 0 | { |
1818 | 0 | const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); |
1819 | |
|
1820 | 0 | if(rPageWindow.GetPaintWindow().OutputToWindow()) |
1821 | 0 | { |
1822 | 0 | const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager(); |
1823 | 0 | if (xManager.is()) |
1824 | 0 | { |
1825 | 0 | const basegfx::B2DPoint aTopLeft(maRect.Left(), maRect.Top()); |
1826 | 0 | const basegfx::B2DPoint aBottomRight(maRect.Right(), maRect.Bottom()); |
1827 | 0 | const Color aHilightColor(SvtOptionsDrawinglayer::getHilightColor()); |
1828 | 0 | const double fTransparence(SvtOptionsDrawinglayer::GetTransparentSelectionPercent() * 0.01); |
1829 | |
|
1830 | 0 | std::unique_ptr<sdr::overlay::OverlayRectangle> pNewOverlayObject(new sdr::overlay::OverlayRectangle( |
1831 | 0 | aTopLeft, |
1832 | 0 | aBottomRight, |
1833 | 0 | aHilightColor, |
1834 | 0 | fTransparence, |
1835 | 0 | 3.0, |
1836 | 0 | 3.0, |
1837 | 0 | -toRadians(m_nRotationAngle), |
1838 | 0 | true)); // allow animation; the Handle is not shown at text edit time |
1839 | |
|
1840 | 0 | pNewOverlayObject->setHittable(false); |
1841 | | |
1842 | | // OVERLAYMANAGER |
1843 | 0 | insertNewlyCreatedOverlayObjectForSdrHdl( |
1844 | 0 | std::move(pNewOverlayObject), |
1845 | 0 | rPageWindow.GetObjectContact(), |
1846 | 0 | *xManager); |
1847 | 0 | } |
1848 | 0 | } |
1849 | 0 | } |
1850 | 0 | } |
1851 | | |
1852 | | |
1853 | | static bool ImpSdrHdlListSorter(std::unique_ptr<SdrHdl> const& lhs, std::unique_ptr<SdrHdl> const& rhs) |
1854 | 0 | { |
1855 | 0 | SdrHdlKind eKind1=lhs->GetKind(); |
1856 | 0 | SdrHdlKind eKind2=rhs->GetKind(); |
1857 | | // Level 1: first normal handles, then Glue, then User, then Plus handles, then reference point handles |
1858 | 0 | unsigned n1=1; |
1859 | 0 | unsigned n2=1; |
1860 | 0 | if (eKind1!=eKind2) |
1861 | 0 | { |
1862 | 0 | if (eKind1==SdrHdlKind::Ref1 || eKind1==SdrHdlKind::Ref2 || eKind1==SdrHdlKind::MirrorAxis) n1=5; |
1863 | 0 | else if (eKind1==SdrHdlKind::Glue) n1=2; |
1864 | 0 | else if (eKind1==SdrHdlKind::User) n1=3; |
1865 | 0 | else if (eKind1==SdrHdlKind::SmartTag) n1=0; |
1866 | 0 | if (eKind2==SdrHdlKind::Ref1 || eKind2==SdrHdlKind::Ref2 || eKind2==SdrHdlKind::MirrorAxis) n2=5; |
1867 | 0 | else if (eKind2==SdrHdlKind::Glue) n2=2; |
1868 | 0 | else if (eKind2==SdrHdlKind::User) n2=3; |
1869 | 0 | else if (eKind2==SdrHdlKind::SmartTag) n2=0; |
1870 | 0 | } |
1871 | 0 | if (lhs->IsPlusHdl()) n1=4; |
1872 | 0 | if (rhs->IsPlusHdl()) n2=4; |
1873 | 0 | if (n1==n2) |
1874 | 0 | { |
1875 | | // Level 2: PageView (Pointer) |
1876 | 0 | SdrPageView* pPV1=lhs->GetPageView(); |
1877 | 0 | SdrPageView* pPV2=rhs->GetPageView(); |
1878 | 0 | if (pPV1==pPV2) |
1879 | 0 | { |
1880 | | // Level 3: Position (x+y) |
1881 | 0 | SdrObject* pObj1=lhs->GetObj(); |
1882 | 0 | SdrObject* pObj2=rhs->GetObj(); |
1883 | 0 | if (pObj1==pObj2) |
1884 | 0 | { |
1885 | 0 | sal_uInt32 nNum1=lhs->GetObjHdlNum(); |
1886 | 0 | sal_uInt32 nNum2=rhs->GetObjHdlNum(); |
1887 | 0 | if (nNum1==nNum2) |
1888 | 0 | { |
1889 | 0 | if (eKind1==eKind2) |
1890 | 0 | return lhs<rhs; // Hack, to always get to the same sorting |
1891 | 0 | return static_cast<sal_uInt16>(eKind1)<static_cast<sal_uInt16>(eKind2); |
1892 | 0 | } |
1893 | 0 | else |
1894 | 0 | return nNum1<nNum2; |
1895 | 0 | } |
1896 | 0 | else |
1897 | 0 | { |
1898 | 0 | return pObj1<pObj2; |
1899 | 0 | } |
1900 | 0 | } |
1901 | 0 | else |
1902 | 0 | { |
1903 | 0 | return pPV1<pPV2; |
1904 | 0 | } |
1905 | 0 | } |
1906 | 0 | else |
1907 | 0 | { |
1908 | 0 | return n1<n2; |
1909 | 0 | } |
1910 | 0 | } |
1911 | | |
1912 | | namespace { |
1913 | | |
1914 | | // Helper struct for re-sorting handles |
1915 | | struct ImplHdlAndIndex |
1916 | | { |
1917 | | SdrHdl* mpHdl; |
1918 | | sal_uInt32 mnIndex; |
1919 | | }; |
1920 | | |
1921 | | } |
1922 | | |
1923 | | extern "C" { |
1924 | | |
1925 | | // Helper method for sorting handles taking care of OrdNums, keeping order in |
1926 | | // single objects and re-sorting polygon handles intuitively |
1927 | | static int ImplSortHdlFunc( const void* pVoid1, const void* pVoid2 ) |
1928 | 0 | { |
1929 | 0 | const ImplHdlAndIndex* p1 = static_cast<ImplHdlAndIndex const *>(pVoid1); |
1930 | 0 | const ImplHdlAndIndex* p2 = static_cast<ImplHdlAndIndex const *>(pVoid2); |
1931 | |
|
1932 | 0 | if(p1->mpHdl->GetObj() == p2->mpHdl->GetObj()) |
1933 | 0 | { |
1934 | 0 | if(p1->mpHdl->GetObj() && dynamic_cast<const SdrPathObj*>(p1->mpHdl->GetObj()) != nullptr) |
1935 | 0 | { |
1936 | | // same object and a path object |
1937 | 0 | if((p1->mpHdl->GetKind() == SdrHdlKind::Poly || p1->mpHdl->GetKind() == SdrHdlKind::BezierWeight) |
1938 | 0 | && (p2->mpHdl->GetKind() == SdrHdlKind::Poly || p2->mpHdl->GetKind() == SdrHdlKind::BezierWeight)) |
1939 | 0 | { |
1940 | | // both handles are point or control handles |
1941 | 0 | if(p1->mpHdl->GetPolyNum() == p2->mpHdl->GetPolyNum()) |
1942 | 0 | { |
1943 | 0 | if(p1->mpHdl->GetPointNum() < p2->mpHdl->GetPointNum()) |
1944 | 0 | { |
1945 | 0 | return -1; |
1946 | 0 | } |
1947 | 0 | else |
1948 | 0 | { |
1949 | 0 | return 1; |
1950 | 0 | } |
1951 | 0 | } |
1952 | 0 | else if(p1->mpHdl->GetPolyNum() < p2->mpHdl->GetPolyNum()) |
1953 | 0 | { |
1954 | 0 | return -1; |
1955 | 0 | } |
1956 | 0 | else |
1957 | 0 | { |
1958 | 0 | return 1; |
1959 | 0 | } |
1960 | 0 | } |
1961 | 0 | } |
1962 | 0 | } |
1963 | 0 | else |
1964 | 0 | { |
1965 | 0 | if(!p1->mpHdl->GetObj()) |
1966 | 0 | { |
1967 | 0 | return -1; |
1968 | 0 | } |
1969 | 0 | else if(!p2->mpHdl->GetObj()) |
1970 | 0 | { |
1971 | 0 | return 1; |
1972 | 0 | } |
1973 | 0 | else |
1974 | 0 | { |
1975 | | // different objects, use OrdNum for sort |
1976 | 0 | const sal_uInt32 nOrdNum1 = p1->mpHdl->GetObj()->GetOrdNum(); |
1977 | 0 | const sal_uInt32 nOrdNum2 = p2->mpHdl->GetObj()->GetOrdNum(); |
1978 | |
|
1979 | 0 | if(nOrdNum1 < nOrdNum2) |
1980 | 0 | { |
1981 | 0 | return -1; |
1982 | 0 | } |
1983 | 0 | else |
1984 | 0 | { |
1985 | 0 | return 1; |
1986 | 0 | } |
1987 | 0 | } |
1988 | 0 | } |
1989 | | |
1990 | | // fallback to indices |
1991 | 0 | if(p1->mnIndex < p2->mnIndex) |
1992 | 0 | { |
1993 | 0 | return -1; |
1994 | 0 | } |
1995 | 0 | else |
1996 | 0 | { |
1997 | 0 | return 1; |
1998 | 0 | } |
1999 | 0 | } |
2000 | | |
2001 | | } |
2002 | | |
2003 | | void SdrHdlList::TravelFocusHdl(bool bForward) |
2004 | 0 | { |
2005 | | // security correction |
2006 | 0 | if (mnFocusIndex >= GetHdlCount()) |
2007 | 0 | mnFocusIndex = SAL_MAX_SIZE; |
2008 | |
|
2009 | 0 | if(maList.empty()) |
2010 | 0 | return; |
2011 | | |
2012 | | // take care of old handle |
2013 | 0 | const size_t nOldHdlNum(mnFocusIndex); |
2014 | 0 | SdrHdl* pOld = nullptr; |
2015 | 0 | if (nOldHdlNum < GetHdlCount()) |
2016 | 0 | pOld = GetHdl(nOldHdlNum); |
2017 | |
|
2018 | 0 | if(pOld) |
2019 | 0 | { |
2020 | | // switch off old handle |
2021 | 0 | mnFocusIndex = SAL_MAX_SIZE; |
2022 | 0 | pOld->Touch(); |
2023 | 0 | } |
2024 | | |
2025 | | // allocate pointer array for sorted handle list |
2026 | 0 | std::unique_ptr<ImplHdlAndIndex[]> pHdlAndIndex(new ImplHdlAndIndex[maList.size()]); |
2027 | | |
2028 | | // build sorted handle list |
2029 | 0 | for( size_t a = 0; a < maList.size(); ++a) |
2030 | 0 | { |
2031 | 0 | pHdlAndIndex[a].mpHdl = maList[a].get(); |
2032 | 0 | pHdlAndIndex[a].mnIndex = a; |
2033 | 0 | } |
2034 | |
|
2035 | 0 | qsort(pHdlAndIndex.get(), maList.size(), sizeof(ImplHdlAndIndex), ImplSortHdlFunc); |
2036 | | |
2037 | | // look for old num in sorted array |
2038 | 0 | size_t nOldHdl(nOldHdlNum); |
2039 | |
|
2040 | 0 | if(nOldHdlNum != SAL_MAX_SIZE) |
2041 | 0 | { |
2042 | 0 | for(size_t a = 0; a < maList.size(); ++a) |
2043 | 0 | { |
2044 | 0 | if(pHdlAndIndex[a].mpHdl == pOld) |
2045 | 0 | { |
2046 | 0 | nOldHdl = a; |
2047 | 0 | break; |
2048 | 0 | } |
2049 | 0 | } |
2050 | 0 | } |
2051 | | |
2052 | | // build new HdlNum |
2053 | 0 | size_t nNewHdl(nOldHdl); |
2054 | | |
2055 | | // do the focus travel |
2056 | 0 | if(bForward) |
2057 | 0 | { |
2058 | 0 | if(nOldHdl != SAL_MAX_SIZE) |
2059 | 0 | { |
2060 | 0 | if(nOldHdl == maList.size() - 1) |
2061 | 0 | { |
2062 | | // end forward run |
2063 | 0 | nNewHdl = SAL_MAX_SIZE; |
2064 | 0 | } |
2065 | 0 | else |
2066 | 0 | { |
2067 | | // simply the next handle |
2068 | 0 | nNewHdl++; |
2069 | 0 | } |
2070 | 0 | } |
2071 | 0 | else |
2072 | 0 | { |
2073 | | // start forward run at first entry |
2074 | 0 | nNewHdl = 0; |
2075 | 0 | } |
2076 | 0 | } |
2077 | 0 | else |
2078 | 0 | { |
2079 | 0 | if(nOldHdl == SAL_MAX_SIZE) |
2080 | 0 | { |
2081 | | // start backward run at last entry |
2082 | 0 | nNewHdl = maList.size() - 1; |
2083 | |
|
2084 | 0 | } |
2085 | 0 | else |
2086 | 0 | { |
2087 | 0 | if(nOldHdl == 0) |
2088 | 0 | { |
2089 | | // end backward run |
2090 | 0 | nNewHdl = SAL_MAX_SIZE; |
2091 | 0 | } |
2092 | 0 | else |
2093 | 0 | { |
2094 | | // simply the previous handle |
2095 | 0 | nNewHdl--; |
2096 | 0 | } |
2097 | 0 | } |
2098 | 0 | } |
2099 | | |
2100 | | // build new HdlNum |
2101 | 0 | sal_uIntPtr nNewHdlNum(nNewHdl); |
2102 | | |
2103 | | // look for old num in sorted array |
2104 | 0 | if(nNewHdl != SAL_MAX_SIZE) |
2105 | 0 | { |
2106 | 0 | SdrHdl* pNew = pHdlAndIndex[nNewHdl].mpHdl; |
2107 | |
|
2108 | 0 | for(size_t a = 0; a < maList.size(); ++a) |
2109 | 0 | { |
2110 | 0 | if(maList[a].get() == pNew) |
2111 | 0 | { |
2112 | 0 | nNewHdlNum = a; |
2113 | 0 | break; |
2114 | 0 | } |
2115 | 0 | } |
2116 | 0 | } |
2117 | | |
2118 | | // take care of next handle |
2119 | 0 | if(nOldHdlNum != nNewHdlNum) |
2120 | 0 | { |
2121 | 0 | mnFocusIndex = nNewHdlNum; |
2122 | 0 | if (mnFocusIndex < GetHdlCount()) |
2123 | 0 | { |
2124 | 0 | SdrHdl* pNew = GetHdl(mnFocusIndex); |
2125 | 0 | pNew->Touch(); |
2126 | 0 | } |
2127 | 0 | } |
2128 | 0 | } |
2129 | | |
2130 | | SdrHdl* SdrHdlList::GetFocusHdl() const |
2131 | 1.09M | { |
2132 | 1.09M | if(mnFocusIndex < GetHdlCount()) |
2133 | 0 | return GetHdl(mnFocusIndex); |
2134 | 1.09M | else |
2135 | 1.09M | return nullptr; |
2136 | 1.09M | } |
2137 | | |
2138 | | void SdrHdlList::SetFocusHdl(SdrHdl* pNew) |
2139 | 0 | { |
2140 | 0 | if(!pNew) |
2141 | 0 | return; |
2142 | | |
2143 | 0 | SdrHdl* pActual = GetFocusHdl(); |
2144 | |
|
2145 | 0 | if(pActual && pActual == pNew) |
2146 | 0 | return; |
2147 | | |
2148 | 0 | const size_t nNewHdlNum = GetHdlNum(pNew); |
2149 | |
|
2150 | 0 | if(nNewHdlNum != SAL_MAX_SIZE) |
2151 | 0 | { |
2152 | 0 | mnFocusIndex = nNewHdlNum; |
2153 | |
|
2154 | 0 | if(pActual) |
2155 | 0 | { |
2156 | 0 | pActual->Touch(); |
2157 | 0 | } |
2158 | |
|
2159 | 0 | pNew->Touch(); |
2160 | 0 | } |
2161 | 0 | } |
2162 | | |
2163 | | void SdrHdlList::ResetFocusHdl() |
2164 | 0 | { |
2165 | 0 | SdrHdl* pHdl = GetFocusHdl(); |
2166 | |
|
2167 | 0 | mnFocusIndex = SAL_MAX_SIZE; |
2168 | |
|
2169 | 0 | if(pHdl) |
2170 | 0 | { |
2171 | 0 | pHdl->Touch(); |
2172 | 0 | } |
2173 | 0 | } |
2174 | | |
2175 | | |
2176 | | SdrHdlList::SdrHdlList(SdrMarkView* pV) |
2177 | | : mnFocusIndex(SAL_MAX_SIZE), |
2178 | 436k | m_pView(pV) |
2179 | 436k | { |
2180 | 436k | m_nHdlSize = 3; |
2181 | 436k | m_bRotateShear = false; |
2182 | 436k | m_bMoveOutside = false; |
2183 | 436k | m_bDistortShear = false; |
2184 | 436k | } |
2185 | | |
2186 | | SdrHdlList::~SdrHdlList() |
2187 | 436k | { |
2188 | 436k | Clear(); |
2189 | 436k | } |
2190 | | |
2191 | | void SdrHdlList::SetHdlSize(sal_uInt16 nSiz) |
2192 | 87.9k | { |
2193 | 87.9k | if(m_nHdlSize != nSiz) |
2194 | 87.9k | { |
2195 | | // remember new value |
2196 | 87.9k | m_nHdlSize = nSiz; |
2197 | | |
2198 | | // propagate change to IAOs |
2199 | 87.9k | for(size_t i=0; i<GetHdlCount(); ++i) |
2200 | 0 | { |
2201 | 0 | SdrHdl* pHdl = GetHdl(i); |
2202 | 0 | pHdl->Touch(); |
2203 | 0 | } |
2204 | 87.9k | } |
2205 | 87.9k | } |
2206 | | |
2207 | | void SdrHdlList::SetMoveOutside(bool bOn) |
2208 | 0 | { |
2209 | 0 | if(m_bMoveOutside != bOn) |
2210 | 0 | { |
2211 | | // remember new value |
2212 | 0 | m_bMoveOutside = bOn; |
2213 | | |
2214 | | // propagate change to IAOs |
2215 | 0 | for(size_t i=0; i<GetHdlCount(); ++i) |
2216 | 0 | { |
2217 | 0 | SdrHdl* pHdl = GetHdl(i); |
2218 | 0 | pHdl->Touch(); |
2219 | 0 | } |
2220 | 0 | } |
2221 | 0 | } |
2222 | | |
2223 | | void SdrHdlList::SetRotateShear(bool bOn) |
2224 | 367k | { |
2225 | 367k | m_bRotateShear = bOn; |
2226 | 367k | } |
2227 | | |
2228 | | void SdrHdlList::SetDistortShear(bool bOn) |
2229 | 367k | { |
2230 | 367k | m_bDistortShear = bOn; |
2231 | 367k | } |
2232 | | |
2233 | | std::unique_ptr<SdrHdl> SdrHdlList::RemoveHdl(size_t nNum) |
2234 | 0 | { |
2235 | 0 | std::unique_ptr<SdrHdl> pRetval = std::move(maList[nNum]); |
2236 | 0 | maList.erase(maList.begin() + nNum); |
2237 | |
|
2238 | 0 | return pRetval; |
2239 | 0 | } |
2240 | | |
2241 | | void SdrHdlList::RemoveAllByKind(SdrHdlKind eKind) |
2242 | 0 | { |
2243 | 0 | std::erase_if(maList, [&eKind](std::unique_ptr<SdrHdl>& rItem) { return rItem->GetKind() == eKind; }); |
2244 | 0 | } |
2245 | | |
2246 | | void SdrHdlList::Clear() |
2247 | 803k | { |
2248 | 803k | maList.clear(); |
2249 | | |
2250 | 803k | m_bRotateShear=false; |
2251 | 803k | m_bDistortShear=false; |
2252 | 803k | } |
2253 | | |
2254 | | void SdrHdlList::Sort() |
2255 | 366k | { |
2256 | | // remember currently focused handle |
2257 | 366k | SdrHdl* pPrev = GetFocusHdl(); |
2258 | | |
2259 | 366k | std::sort( maList.begin(), maList.end(), ImpSdrHdlListSorter ); |
2260 | | |
2261 | | // get now and compare |
2262 | 366k | SdrHdl* pNow = GetFocusHdl(); |
2263 | | |
2264 | 366k | if(pPrev == pNow) |
2265 | 366k | return; |
2266 | | |
2267 | 0 | if(pPrev) |
2268 | 0 | { |
2269 | 0 | pPrev->Touch(); |
2270 | 0 | } |
2271 | |
|
2272 | 0 | if(pNow) |
2273 | 0 | { |
2274 | 0 | pNow->Touch(); |
2275 | 0 | } |
2276 | 0 | } |
2277 | | |
2278 | | size_t SdrHdlList::GetHdlNum(const SdrHdl* pHdl) const |
2279 | 0 | { |
2280 | 0 | if (pHdl==nullptr) |
2281 | 0 | return SAL_MAX_SIZE; |
2282 | 0 | auto it = std::find_if( maList.begin(), maList.end(), |
2283 | 0 | [&](const std::unique_ptr<SdrHdl> & p) { return p.get() == pHdl; }); |
2284 | 0 | assert(it != maList.end()); |
2285 | 0 | if( it == maList.end() ) |
2286 | 0 | return SAL_MAX_SIZE; |
2287 | 0 | return it - maList.begin(); |
2288 | 0 | } |
2289 | | |
2290 | | void SdrHdlList::AddHdl(std::unique_ptr<SdrHdl> pHdl) |
2291 | 0 | { |
2292 | 0 | assert(pHdl); |
2293 | 0 | pHdl->SetHdlList(this); |
2294 | 0 | maList.push_back(std::move(pHdl)); |
2295 | 0 | } |
2296 | | |
2297 | | SdrHdl* SdrHdlList::IsHdlListHit(const Point& rPnt) const |
2298 | 0 | { |
2299 | 0 | SdrHdl* pRet=nullptr; |
2300 | 0 | const size_t nCount=GetHdlCount(); |
2301 | 0 | size_t nNum=nCount; |
2302 | 0 | while (nNum>0 && pRet==nullptr) |
2303 | 0 | { |
2304 | 0 | nNum--; |
2305 | 0 | SdrHdl* pHdl=GetHdl(nNum); |
2306 | 0 | if (pHdl->IsHdlHit(rPnt)) |
2307 | 0 | pRet=pHdl; |
2308 | 0 | } |
2309 | 0 | return pRet; |
2310 | 0 | } |
2311 | | |
2312 | | SdrHdl* SdrHdlList::GetHdl(SdrHdlKind eKind1) const |
2313 | 0 | { |
2314 | 0 | SdrHdl* pRet=nullptr; |
2315 | 0 | for (size_t i=0; i<GetHdlCount() && pRet==nullptr; ++i) |
2316 | 0 | { |
2317 | 0 | SdrHdl* pHdl=GetHdl(i); |
2318 | 0 | if (pHdl->GetKind()==eKind1) |
2319 | 0 | pRet=pHdl; |
2320 | 0 | } |
2321 | 0 | return pRet; |
2322 | 0 | } |
2323 | | |
2324 | | void SdrHdlList::MoveTo(SdrHdlList& rOther) |
2325 | 0 | { |
2326 | 0 | for (auto & pHdl : maList) |
2327 | 0 | pHdl->SetHdlList(&rOther); |
2328 | 0 | rOther.maList.insert(rOther.maList.end(), |
2329 | 0 | std::make_move_iterator(maList.begin()), std::make_move_iterator(maList.end())); |
2330 | 0 | maList.clear(); |
2331 | 0 | } |
2332 | | |
2333 | | SdrCropHdl::SdrCropHdl( |
2334 | | const Point& rPnt, |
2335 | | SdrHdlKind eNewKind, |
2336 | | double fShearX, |
2337 | | double fRotation) |
2338 | 0 | : SdrHdl(rPnt, eNewKind), |
2339 | 0 | mfShearX(fShearX), |
2340 | 0 | mfRotation(fRotation) |
2341 | 0 | { |
2342 | 0 | } |
2343 | | |
2344 | | |
2345 | | Bitmap SdrCropHdl::GetBitmapForHandle( const Bitmap& rBitmap, int nSize ) |
2346 | 0 | { |
2347 | 0 | int nPixelSize = 0, nX = 0, nY = 0, nOffset = 0; |
2348 | |
|
2349 | 0 | if( nSize <= 3 ) |
2350 | 0 | { |
2351 | 0 | nPixelSize = 13; |
2352 | 0 | nOffset = 0; |
2353 | 0 | } |
2354 | 0 | else if( nSize <=4 ) |
2355 | 0 | { |
2356 | 0 | nPixelSize = 17; |
2357 | 0 | nOffset = 39; |
2358 | 0 | } |
2359 | 0 | else |
2360 | 0 | { |
2361 | 0 | nPixelSize = 21; |
2362 | 0 | nOffset = 90; |
2363 | 0 | } |
2364 | |
|
2365 | 0 | switch( m_eKind ) |
2366 | 0 | { |
2367 | 0 | case SdrHdlKind::UpperLeft: nX = 0; nY = 0; break; |
2368 | 0 | case SdrHdlKind::Upper: nX = 1; nY = 0; break; |
2369 | 0 | case SdrHdlKind::UpperRight: nX = 2; nY = 0; break; |
2370 | 0 | case SdrHdlKind::Left: nX = 0; nY = 1; break; |
2371 | 0 | case SdrHdlKind::Right: nX = 2; nY = 1; break; |
2372 | 0 | case SdrHdlKind::LowerLeft: nX = 0; nY = 2; break; |
2373 | 0 | case SdrHdlKind::Lower: nX = 1; nY = 2; break; |
2374 | 0 | case SdrHdlKind::LowerRight: nX = 2; nY = 2; break; |
2375 | 0 | default: break; |
2376 | 0 | } |
2377 | | |
2378 | 0 | tools::Rectangle aSourceRect( Point( nX * nPixelSize + nOffset, nY * nPixelSize), Size(nPixelSize, nPixelSize) ); |
2379 | |
|
2380 | 0 | Bitmap aRetval(rBitmap); |
2381 | 0 | aRetval.Crop(aSourceRect); |
2382 | 0 | return aRetval; |
2383 | 0 | } |
2384 | | |
2385 | | |
2386 | | void SdrCropHdl::CreateB2dIAObject() |
2387 | 0 | { |
2388 | | // first throw away old one |
2389 | 0 | GetRidOfIAObject(); |
2390 | |
|
2391 | 0 | SdrMarkView* pView = m_pHdlList ? m_pHdlList->GetView() : nullptr; |
2392 | 0 | SdrPageView* pPageView = pView ? pView->GetSdrPageView() : nullptr; |
2393 | |
|
2394 | 0 | if( !pPageView || pView->areMarkHandlesHidden() ) |
2395 | 0 | return; |
2396 | | |
2397 | 0 | const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); |
2398 | 0 | int nHdlSize = m_pHdlList->GetHdlSize(); |
2399 | |
|
2400 | 0 | const Bitmap aHandlesBitmap(SIP_SA_CROP_MARKERS); |
2401 | 0 | Bitmap aBmp1( GetBitmapForHandle( aHandlesBitmap, nHdlSize ) ); |
2402 | |
|
2403 | 0 | for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++) |
2404 | 0 | { |
2405 | 0 | const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); |
2406 | |
|
2407 | 0 | if(rPageWindow.GetPaintWindow().OutputToWindow()) |
2408 | 0 | { |
2409 | 0 | const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager(); |
2410 | 0 | if (xManager.is()) |
2411 | 0 | { |
2412 | 0 | basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y()); |
2413 | |
|
2414 | 0 | std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject; |
2415 | | |
2416 | | // animate focused handles |
2417 | 0 | if(IsFocusHdl() && (m_pHdlList->GetFocusHdl() == this)) |
2418 | 0 | { |
2419 | 0 | if( nHdlSize >= 2 ) |
2420 | 0 | nHdlSize = 1; |
2421 | |
|
2422 | 0 | Bitmap aBmp2( GetBitmapForHandle( aHandlesBitmap, nHdlSize + 1 ) ); |
2423 | |
|
2424 | 0 | const sal_uInt64 nBlinkTime = rStyleSettings.GetCursorBlinkTime(); |
2425 | |
|
2426 | 0 | pOverlayObject.reset(new sdr::overlay::OverlayAnimatedBitmapEx( |
2427 | 0 | aPosition, |
2428 | 0 | aBmp1, |
2429 | 0 | aBmp2, |
2430 | 0 | nBlinkTime, |
2431 | 0 | static_cast<sal_uInt16>(aBmp1.GetSizePixel().Width() - 1) >> 1, |
2432 | 0 | static_cast<sal_uInt16>(aBmp1.GetSizePixel().Height() - 1) >> 1, |
2433 | 0 | static_cast<sal_uInt16>(aBmp2.GetSizePixel().Width() - 1) >> 1, |
2434 | 0 | static_cast<sal_uInt16>(aBmp2.GetSizePixel().Height() - 1) >> 1, |
2435 | 0 | mfShearX, |
2436 | 0 | mfRotation)); |
2437 | 0 | } |
2438 | 0 | else |
2439 | 0 | { |
2440 | | // create centered handle as default |
2441 | 0 | pOverlayObject.reset(new sdr::overlay::OverlayBitmapEx( |
2442 | 0 | aPosition, |
2443 | 0 | aBmp1, |
2444 | 0 | static_cast<sal_uInt16>(aBmp1.GetSizePixel().Width() - 1) >> 1, |
2445 | 0 | static_cast<sal_uInt16>(aBmp1.GetSizePixel().Height() - 1) >> 1, |
2446 | 0 | 0.0, |
2447 | 0 | mfShearX, |
2448 | 0 | mfRotation)); |
2449 | 0 | } |
2450 | | |
2451 | | // OVERLAYMANAGER |
2452 | 0 | insertNewlyCreatedOverlayObjectForSdrHdl( |
2453 | 0 | std::move(pOverlayObject), |
2454 | 0 | rPageWindow.GetObjectContact(), |
2455 | 0 | *xManager); |
2456 | 0 | } |
2457 | 0 | } |
2458 | 0 | } |
2459 | 0 | } |
2460 | | |
2461 | | |
2462 | | // with the correction of crop handling I could get rid of the extra mirroring flag, adapted stuff |
2463 | | // accordingly |
2464 | | |
2465 | | SdrCropViewHdl::SdrCropViewHdl( |
2466 | | basegfx::B2DHomMatrix aObjectTransform, |
2467 | | Graphic aGraphic, |
2468 | | double fCropLeft, |
2469 | | double fCropTop, |
2470 | | double fCropRight, |
2471 | | double fCropBottom) |
2472 | 0 | : SdrHdl(Point(), SdrHdlKind::User), |
2473 | 0 | maObjectTransform(std::move(aObjectTransform)), |
2474 | 0 | maGraphic(std::move(aGraphic)), |
2475 | 0 | mfCropLeft(fCropLeft), |
2476 | 0 | mfCropTop(fCropTop), |
2477 | 0 | mfCropRight(fCropRight), |
2478 | 0 | mfCropBottom(fCropBottom) |
2479 | 0 | { |
2480 | 0 | } |
2481 | | |
2482 | | namespace { |
2483 | | |
2484 | 0 | void translateRotationToMirroring(basegfx::B2DVector & scale, double * rotate) { |
2485 | 0 | assert(rotate != nullptr); |
2486 | | |
2487 | | // detect 180 degree rotation, this is the same as mirrored in X and Y, |
2488 | | // thus change to mirroring. Prefer mirroring here. Use the equal call |
2489 | | // with getSmallValue here, the original which uses rtl::math::approxEqual |
2490 | | // is too correct here. Maybe this changes with enhanced precision in aw080 |
2491 | | // to the better so that this can be reduced to the more precise call again |
2492 | 0 | if(basegfx::fTools::equal(fabs(*rotate), M_PI, 0.000000001)) |
2493 | 0 | { |
2494 | 0 | scale.setX(scale.getX() * -1.0); |
2495 | 0 | scale.setY(scale.getY() * -1.0); |
2496 | 0 | *rotate = 0.0; |
2497 | 0 | } |
2498 | 0 | } |
2499 | | |
2500 | | } |
2501 | | |
2502 | | void SdrCropViewHdl::CreateB2dIAObject() |
2503 | 0 | { |
2504 | 0 | GetRidOfIAObject(); |
2505 | 0 | SdrMarkView* pView = m_pHdlList ? m_pHdlList->GetView() : nullptr; |
2506 | 0 | SdrPageView* pPageView = pView ? pView->GetSdrPageView() : nullptr; |
2507 | |
|
2508 | 0 | if(!pPageView || pView->areMarkHandlesHidden()) |
2509 | 0 | { |
2510 | 0 | return; |
2511 | 0 | } |
2512 | | |
2513 | | // decompose to have current translate and scale |
2514 | 0 | basegfx::B2DVector aScale, aTranslate; |
2515 | 0 | double fRotate, fShearX; |
2516 | |
|
2517 | 0 | maObjectTransform.decompose(aScale, aTranslate, fRotate, fShearX); |
2518 | |
|
2519 | 0 | if(aScale.equalZero()) |
2520 | 0 | { |
2521 | 0 | return; |
2522 | 0 | } |
2523 | | |
2524 | 0 | translateRotationToMirroring(aScale, &fRotate); |
2525 | | |
2526 | | // remember mirroring, reset at Scale and adapt crop values for usage; |
2527 | | // mirroring can stay in the object transformation, so do not have to |
2528 | | // cope with it here (except later for the CroppedImage transformation, |
2529 | | // see below) |
2530 | 0 | const bool bMirroredX(aScale.getX() < 0.0); |
2531 | 0 | const bool bMirroredY(aScale.getY() < 0.0); |
2532 | 0 | double fCropLeft(mfCropLeft); |
2533 | 0 | double fCropTop(mfCropTop); |
2534 | 0 | double fCropRight(mfCropRight); |
2535 | 0 | double fCropBottom(mfCropBottom); |
2536 | |
|
2537 | 0 | if(bMirroredX) |
2538 | 0 | { |
2539 | 0 | aScale.setX(-aScale.getX()); |
2540 | 0 | } |
2541 | |
|
2542 | 0 | if(bMirroredY) |
2543 | 0 | { |
2544 | 0 | aScale.setY(-aScale.getY()); |
2545 | 0 | } |
2546 | | |
2547 | | // create target translate and scale |
2548 | 0 | const basegfx::B2DVector aTargetScale( |
2549 | 0 | aScale.getX() + fCropRight + fCropLeft, |
2550 | 0 | aScale.getY() + fCropBottom + fCropTop); |
2551 | 0 | const basegfx::B2DVector aTargetTranslate( |
2552 | 0 | aTranslate.getX() - fCropLeft, |
2553 | 0 | aTranslate.getY() - fCropTop); |
2554 | | |
2555 | | // create ranges to make comparisons |
2556 | 0 | const basegfx::B2DRange aCurrentForCompare( |
2557 | 0 | aTranslate.getX(), aTranslate.getY(), |
2558 | 0 | aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY()); |
2559 | 0 | basegfx::B2DRange aCropped( |
2560 | 0 | aTargetTranslate.getX(), aTargetTranslate.getY(), |
2561 | 0 | aTargetTranslate.getX() + aTargetScale.getX(), aTargetTranslate.getY() + aTargetScale.getY()); |
2562 | |
|
2563 | 0 | if(aCropped.isEmpty()) |
2564 | 0 | { |
2565 | | // nothing to return since cropped content is completely empty |
2566 | 0 | return; |
2567 | 0 | } |
2568 | | |
2569 | 0 | if(aCurrentForCompare.equal(aCropped)) |
2570 | 0 | { |
2571 | | // no crop at all |
2572 | 0 | return; |
2573 | 0 | } |
2574 | | |
2575 | | // back-transform to have values in unit coordinates |
2576 | 0 | basegfx::B2DHomMatrix aBackToUnit; |
2577 | 0 | aBackToUnit.translate(-aTranslate.getX(), -aTranslate.getY()); |
2578 | 0 | aBackToUnit.scale( |
2579 | 0 | basegfx::fTools::equalZero(aScale.getX()) ? 1.0 : 1.0 / aScale.getX(), |
2580 | 0 | basegfx::fTools::equalZero(aScale.getY()) ? 1.0 : 1.0 / aScale.getY()); |
2581 | | |
2582 | | // transform cropped back to unit coordinates |
2583 | 0 | aCropped.transform(aBackToUnit); |
2584 | | |
2585 | | // prepare crop PolyPolygon |
2586 | 0 | basegfx::B2DPolygon aGraphicOutlinePolygon( |
2587 | 0 | basegfx::utils::createPolygonFromRect( |
2588 | 0 | aCropped)); |
2589 | 0 | basegfx::B2DPolyPolygon aCropPolyPolygon(aGraphicOutlinePolygon); |
2590 | | |
2591 | | // current range is unit range |
2592 | 0 | basegfx::B2DRange aOverlap(0.0, 0.0, 1.0, 1.0); |
2593 | |
|
2594 | 0 | aOverlap.intersect(aCropped); |
2595 | |
|
2596 | 0 | if(!aOverlap.isEmpty()) |
2597 | 0 | { |
2598 | 0 | aCropPolyPolygon.append( |
2599 | 0 | basegfx::utils::createPolygonFromRect( |
2600 | 0 | aOverlap)); |
2601 | 0 | } |
2602 | | |
2603 | | // transform to object coordinates to prepare for clip |
2604 | 0 | aCropPolyPolygon.transform(maObjectTransform); |
2605 | 0 | aGraphicOutlinePolygon.transform(maObjectTransform); |
2606 | | |
2607 | | // create cropped transformation |
2608 | 0 | basegfx::B2DHomMatrix aCroppedTransform; |
2609 | |
|
2610 | 0 | aCroppedTransform.scale( |
2611 | 0 | aCropped.getWidth(), |
2612 | 0 | aCropped.getHeight()); |
2613 | 0 | aCroppedTransform.translate( |
2614 | 0 | aCropped.getMinX(), |
2615 | 0 | aCropped.getMinY()); |
2616 | 0 | aCroppedTransform = maObjectTransform * aCroppedTransform; |
2617 | | |
2618 | | // prepare graphic primitive (transformed) |
2619 | 0 | const drawinglayer::primitive2d::Primitive2DReference aGraphic( |
2620 | 0 | new drawinglayer::primitive2d::GraphicPrimitive2D( |
2621 | 0 | aCroppedTransform, |
2622 | 0 | maGraphic)); |
2623 | | |
2624 | | // prepare outline polygon for whole graphic |
2625 | 0 | const basegfx::BColor aHilightColor(SvtOptionsDrawinglayer::getHilightColor().getBColor()); |
2626 | 0 | const drawinglayer::primitive2d::Primitive2DReference aGraphicOutline( |
2627 | 0 | new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( |
2628 | 0 | std::move(aGraphicOutlinePolygon), |
2629 | 0 | aHilightColor)); |
2630 | | |
2631 | | // combine these |
2632 | 0 | drawinglayer::primitive2d::Primitive2DContainer aCombination { aGraphic, aGraphicOutline }; |
2633 | | |
2634 | | // embed to MaskPrimitive2D |
2635 | 0 | const drawinglayer::primitive2d::Primitive2DReference aMaskedGraphic( |
2636 | 0 | new drawinglayer::primitive2d::MaskPrimitive2D( |
2637 | 0 | std::move(aCropPolyPolygon), |
2638 | 0 | std::move(aCombination))); |
2639 | | |
2640 | | // embed to UnifiedTransparencePrimitive2D |
2641 | 0 | const drawinglayer::primitive2d::Primitive2DReference aTransparenceMaskedGraphic( |
2642 | 0 | new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( |
2643 | 0 | drawinglayer::primitive2d::Primitive2DContainer { aMaskedGraphic }, |
2644 | 0 | 0.8)); |
2645 | |
|
2646 | 0 | const drawinglayer::primitive2d::Primitive2DContainer aSequence { aTransparenceMaskedGraphic }; |
2647 | |
|
2648 | 0 | for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++) |
2649 | 0 | { |
2650 | | // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b]; |
2651 | 0 | const SdrPageWindow& rPageWindow = *(pPageView->GetPageWindow(b)); |
2652 | |
|
2653 | 0 | if(rPageWindow.GetPaintWindow().OutputToWindow()) |
2654 | 0 | { |
2655 | 0 | const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager(); |
2656 | 0 | if(xManager.is()) |
2657 | 0 | { |
2658 | 0 | std::unique_ptr<sdr::overlay::OverlayObject> pNew(new sdr::overlay::OverlayPrimitive2DSequenceObject(drawinglayer::primitive2d::Primitive2DContainer(aSequence))); |
2659 | | |
2660 | | // only informative object, no hit |
2661 | 0 | pNew->setHittable(false); |
2662 | | |
2663 | | // OVERLAYMANAGER |
2664 | 0 | insertNewlyCreatedOverlayObjectForSdrHdl( |
2665 | 0 | std::move(pNew), |
2666 | 0 | rPageWindow.GetObjectContact(), |
2667 | 0 | *xManager); |
2668 | 0 | } |
2669 | 0 | } |
2670 | 0 | } |
2671 | 0 | } |
2672 | | |
2673 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |