1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
24 #include <svx/svdhdl.hxx>
25 #include <svx/svdpagv.hxx>
26 #include <svx/svdmrkv.hxx>
27 #include <vcl/settings.hxx>
28 #include <vcl/virdev.hxx>
29 #include <vcl/ptrstyle.hxx>
31 #include <svx/sxekitm.hxx>
32 #include <svx/strings.hrc>
33 #include <svx/svdmodel.hxx>
34 #include "gradtrns.hxx"
35 #include <svx/xflgrit.hxx>
36 #include <svx/svdundo.hxx>
37 #include <svx/dialmgr.hxx>
38 #include <svx/xflftrit.hxx>
40 #include <svx/svdopath.hxx>
41 #include <basegfx/vector/b2dvector.hxx>
42 #include <basegfx/polygon/b2dpolygon.hxx>
43 #include <svx/sdr/overlay/overlaymanager.hxx>
44 #include <svx/sdr/overlay/overlayanimatedbitmapex.hxx>
45 #include <svx/sdr/overlay/overlaybitmapex.hxx>
46 #include <sdr/overlay/overlayline.hxx>
47 #include <sdr/overlay/overlaytriangle.hxx>
48 #include <sdr/overlay/overlayhandle.hxx>
49 #include <sdr/overlay/overlayrectangle.hxx>
50 #include <svx/sdrpagewindow.hxx>
51 #include <svx/sdrpaintwindow.hxx>
52 #include <vcl/svapp.hxx>
53 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
54 #include <vcl/lazydelete.hxx>
55 #include <vcl/BitmapTools.hxx>
56 #include <svx/sdr/contact/objectcontact.hxx>
57 #include <svx/sdr/contact/viewcontact.hxx>
59 #include <basegfx/polygon/b2dpolygontools.hxx>
60 #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
61 #include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
62 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
63 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
64 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
66 #include <bitmaps.hlst>
71 // Due to the resource problems in Win95/98 with bitmap resources I
72 // will change this handle bitmap providing class. Old version was splitting
73 // and preparing all small handle bitmaps in device bitmap format, now this will
74 // be done on the fly. Thus, there is only one big bitmap in memory. With
75 // three source bitmaps, this will be 3 system bitmap resources instead of hundreds.
76 // The price for that needs to be evaluated. Maybe we will need another change here
77 // if this is too expensive.
80 // the bitmap holding all information
81 BitmapEx maMarkersBitmap
;
83 // the cropped Bitmaps for reusage
84 ::std::vector
< BitmapEx
> maRealMarkers
;
87 BitmapEx
& impGetOrCreateTargetBitmap(sal_uInt16 nIndex
, const tools::Rectangle
& rRectangle
);
90 explicit SdrHdlBitmapSet();
92 const BitmapEx
& GetBitmapEx(BitmapMarkerKind eKindOfMarker
, sal_uInt16 nInd
);
97 #define KIND_COUNT (14)
98 #define INDEX_COUNT (6)
99 #define INDIVIDUAL_COUNT (5)
101 SdrHdlBitmapSet::SdrHdlBitmapSet()
102 : maMarkersBitmap(SIP_SA_MARKERS
),
103 // 15 kinds (BitmapMarkerKind) use index [0..5] + 5 extra
104 maRealMarkers((KIND_COUNT
* INDEX_COUNT
) + INDIVIDUAL_COUNT
)
108 BitmapEx
& SdrHdlBitmapSet::impGetOrCreateTargetBitmap(sal_uInt16 nIndex
, const tools::Rectangle
& rRectangle
)
110 BitmapEx
& rTargetBitmap
= maRealMarkers
[nIndex
];
112 if(rTargetBitmap
.IsEmpty())
114 rTargetBitmap
= maMarkersBitmap
;
115 rTargetBitmap
.Crop(rRectangle
);
118 return rTargetBitmap
;
121 // change getting of bitmap to use the big resource bitmap
122 const BitmapEx
& SdrHdlBitmapSet::GetBitmapEx(BitmapMarkerKind eKindOfMarker
, sal_uInt16 nInd
)
124 // fill in size and source position in maMarkersBitmap
125 const sal_uInt16
nYPos(nInd
* 11);
127 switch(eKindOfMarker
)
131 OSL_FAIL( "Unknown kind of marker." );
132 [[fallthrough
]]; // return Rect_9x9 as default
134 case BitmapMarkerKind::Rect_9x9
:
136 return impGetOrCreateTargetBitmap((1 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(7, nYPos
), Size(9, 9)));
139 case BitmapMarkerKind::Rect_7x7
:
141 return impGetOrCreateTargetBitmap((0 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(0, nYPos
), Size(7, 7)));
144 case BitmapMarkerKind::Rect_11x11
:
146 return impGetOrCreateTargetBitmap((2 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(16, nYPos
), Size(11, 11)));
149 case BitmapMarkerKind::Rect_13x13
:
151 const sal_uInt16
nIndex((3 * INDEX_COUNT
) + nInd
);
157 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(72, 66), Size(13, 13)));
161 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(85, 66), Size(13, 13)));
165 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(72, 79), Size(13, 13)));
169 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(85, 79), Size(13, 13)));
173 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(98, 79), Size(13, 13)));
177 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(98, 66), Size(13, 13)));
182 case BitmapMarkerKind::Circ_7x7
:
183 case BitmapMarkerKind::Customshape_7x7
:
185 return impGetOrCreateTargetBitmap((4 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(27, nYPos
), Size(7, 7)));
188 case BitmapMarkerKind::Circ_9x9
:
189 case BitmapMarkerKind::Customshape_9x9
:
191 return impGetOrCreateTargetBitmap((5 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(34, nYPos
), Size(9, 9)));
194 case BitmapMarkerKind::Circ_11x11
:
195 case BitmapMarkerKind::Customshape_11x11
:
197 return impGetOrCreateTargetBitmap((6 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(43, nYPos
), Size(11, 11)));
200 case BitmapMarkerKind::Elli_7x9
:
202 return impGetOrCreateTargetBitmap((7 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(54, nYPos
), Size(7, 9)));
205 case BitmapMarkerKind::Elli_9x11
:
207 return impGetOrCreateTargetBitmap((8 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(61, nYPos
), Size(9, 11)));
210 case BitmapMarkerKind::Elli_9x7
:
212 return impGetOrCreateTargetBitmap((9 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(70, nYPos
), Size(9, 7)));
215 case BitmapMarkerKind::Elli_11x9
:
217 return impGetOrCreateTargetBitmap((10 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(79, nYPos
), Size(11, 9)));
220 case BitmapMarkerKind::RectPlus_7x7
:
222 return impGetOrCreateTargetBitmap((11 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(90, nYPos
), Size(7, 7)));
225 case BitmapMarkerKind::RectPlus_9x9
:
227 return impGetOrCreateTargetBitmap((12 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(97, nYPos
), Size(9, 9)));
230 case BitmapMarkerKind::RectPlus_11x11
:
232 return impGetOrCreateTargetBitmap((13 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(106, nYPos
), Size(11, 11)));
235 case BitmapMarkerKind::Crosshair
:
237 return impGetOrCreateTargetBitmap((KIND_COUNT
* INDEX_COUNT
) + 0, tools::Rectangle(Point(0, 68), Size(15, 15)));
240 case BitmapMarkerKind::Glue
:
242 return impGetOrCreateTargetBitmap((KIND_COUNT
* INDEX_COUNT
) + 1, tools::Rectangle(Point(15, 76), Size(9, 9)));
245 case BitmapMarkerKind::Glue_Deselected
:
247 return impGetOrCreateTargetBitmap((KIND_COUNT
* INDEX_COUNT
) + 2, tools::Rectangle(Point(15, 67), Size(9, 9)));
250 case BitmapMarkerKind::Anchor
: // AnchorTR for SW
251 case BitmapMarkerKind::AnchorTR
:
253 return impGetOrCreateTargetBitmap((KIND_COUNT
* INDEX_COUNT
) + 3, tools::Rectangle(Point(24, 67), Size(24, 24)));
256 // add AnchorPressed to be able to animate anchor control
257 case BitmapMarkerKind::AnchorPressed
:
258 case BitmapMarkerKind::AnchorPressedTR
:
260 return impGetOrCreateTargetBitmap((KIND_COUNT
* INDEX_COUNT
) + 4, tools::Rectangle(Point(48, 67), Size(24, 24)));
270 eKind(SdrHdlKind::Move
),
279 mbMoveOutside(false),
284 SdrHdl::SdrHdl(const Point
& rPnt
, SdrHdlKind eNewKind
):
298 mbMoveOutside(false),
308 void SdrHdl::Set1PixMore(bool bJa
)
314 // create new display
319 void SdrHdl::SetMoveOutside( bool bMoveOutside
)
321 if(mbMoveOutside
!= bMoveOutside
)
323 mbMoveOutside
= bMoveOutside
;
325 // create new display
330 void SdrHdl::SetRotationAngle(tools::Long n
)
332 if(nRotationAngle
!= n
)
336 // create new display
341 void SdrHdl::SetPos(const Point
& rPnt
)
345 // remember new position
348 // create new display
353 void SdrHdl::SetSelected(bool bJa
)
357 // remember new value
360 // create new display
365 void SdrHdl::SetHdlList(SdrHdlList
* pList
)
367 if(pHdlList
!= pList
)
372 // now it's possible to create graphic representation
377 void SdrHdl::SetObj(SdrObject
* pNewObj
)
381 // remember new object
384 // graphic representation may have changed
391 // force update of graphic representation
395 void SdrHdl::GetRidOfIAObject()
399 maOverlayGroup
.clear();
402 void SdrHdl::CreateB2dIAObject()
404 // first throw away old one
407 if(!pHdlList
|| !pHdlList
->GetView() || pHdlList
->GetView()->areMarkHandlesHidden())
410 BitmapColorIndex eColIndex
= BitmapColorIndex::LightGreen
;
411 BitmapMarkerKind eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
413 bool bRot
= pHdlList
->IsRotateShear();
415 eColIndex
= bSelect
? BitmapColorIndex::Cyan
: BitmapColorIndex::LightCyan
;
418 // red rotation handles
420 eColIndex
= BitmapColorIndex::Red
;
422 eColIndex
= BitmapColorIndex::LightRed
;
427 case SdrHdlKind::Move
:
429 eKindOfMarker
= b1PixMore
? BitmapMarkerKind::Rect_9x9
: BitmapMarkerKind::Rect_7x7
;
432 case SdrHdlKind::UpperLeft
:
433 case SdrHdlKind::UpperRight
:
434 case SdrHdlKind::LowerLeft
:
435 case SdrHdlKind::LowerRight
:
440 eKindOfMarker
= BitmapMarkerKind::Circ_7x7
;
444 eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
448 case SdrHdlKind::Upper
:
449 case SdrHdlKind::Lower
:
451 // Upper/Lower handles
454 eKindOfMarker
= BitmapMarkerKind::Elli_9x7
;
458 eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
462 case SdrHdlKind::Left
:
463 case SdrHdlKind::Right
:
465 // Left/Right handles
468 eKindOfMarker
= BitmapMarkerKind::Elli_7x9
;
472 eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
476 case SdrHdlKind::Poly
:
480 eKindOfMarker
= b1PixMore
? BitmapMarkerKind::Circ_9x9
: BitmapMarkerKind::Circ_7x7
;
484 eKindOfMarker
= b1PixMore
? BitmapMarkerKind::Rect_9x9
: BitmapMarkerKind::Rect_7x7
;
488 case SdrHdlKind::BezierWeight
: // weight at poly
490 eKindOfMarker
= BitmapMarkerKind::Circ_7x7
;
493 case SdrHdlKind::Circle
:
495 eKindOfMarker
= BitmapMarkerKind::Rect_11x11
;
498 case SdrHdlKind::Ref1
:
499 case SdrHdlKind::Ref2
:
501 eKindOfMarker
= BitmapMarkerKind::Crosshair
;
504 case SdrHdlKind::Glue
:
506 eKindOfMarker
= BitmapMarkerKind::Glue
;
509 case SdrHdlKind::Anchor
:
511 eKindOfMarker
= BitmapMarkerKind::Anchor
;
514 case SdrHdlKind::User
:
518 // top right anchor for SW
519 case SdrHdlKind::Anchor_TR
:
521 eKindOfMarker
= BitmapMarkerKind::AnchorTR
;
525 // for SJ and the CustomShapeHandles:
526 case SdrHdlKind::CustomShape1
:
528 eKindOfMarker
= b1PixMore
? BitmapMarkerKind::Customshape_9x9
: BitmapMarkerKind::Customshape_7x7
;
529 eColIndex
= BitmapColorIndex::Yellow
;
536 SdrMarkView
* pView
= pHdlList
->GetView();
537 SdrPageView
* pPageView
= pView
->GetSdrPageView();
542 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
544 // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
545 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
547 if(rPageWindow
.GetPaintWindow().OutputToWindow())
549 Point
aMoveOutsideOffset(0, 0);
550 OutputDevice
& rOutDev
= rPageWindow
.GetPaintWindow().GetOutputDevice();
552 // add offset if necessary
553 if(pHdlList
->IsMoveOutside() || mbMoveOutside
)
555 Size aOffset
= rOutDev
.PixelToLogic(Size(4, 4));
557 if(eKind
== SdrHdlKind::UpperLeft
|| eKind
== SdrHdlKind::Upper
|| eKind
== SdrHdlKind::UpperRight
)
558 aMoveOutsideOffset
.AdjustY( -(aOffset
.Width()) );
559 if(eKind
== SdrHdlKind::LowerLeft
|| eKind
== SdrHdlKind::Lower
|| eKind
== SdrHdlKind::LowerRight
)
560 aMoveOutsideOffset
.AdjustY(aOffset
.Height() );
561 if(eKind
== SdrHdlKind::UpperLeft
|| eKind
== SdrHdlKind::Left
|| eKind
== SdrHdlKind::LowerLeft
)
562 aMoveOutsideOffset
.AdjustX( -(aOffset
.Width()) );
563 if(eKind
== SdrHdlKind::UpperRight
|| eKind
== SdrHdlKind::Right
|| eKind
== SdrHdlKind::LowerRight
)
564 aMoveOutsideOffset
.AdjustX(aOffset
.Height() );
567 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
570 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
571 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject
;
572 if (getenv ("SVX_DRAW_HANDLES") && (eKindOfMarker
== BitmapMarkerKind::Rect_7x7
|| eKindOfMarker
== BitmapMarkerKind::Rect_9x9
|| eKindOfMarker
== BitmapMarkerKind::Rect_11x11
))
575 switch (eKindOfMarker
)
577 case BitmapMarkerKind::Rect_9x9
:
580 case BitmapMarkerKind::Rect_11x11
:
586 float fScalingFactor
= rOutDev
.GetDPIScaleFactor();
587 basegfx::B2DSize
aB2DSize(fSize
* fScalingFactor
, fSize
* fScalingFactor
);
589 Color
aHandleFillColor(COL_LIGHTGREEN
);
592 case BitmapColorIndex::Cyan
:
593 aHandleFillColor
= COL_CYAN
;
595 case BitmapColorIndex::LightCyan
:
596 aHandleFillColor
= COL_LIGHTCYAN
;
598 case BitmapColorIndex::Red
:
599 aHandleFillColor
= COL_RED
;
601 case BitmapColorIndex::LightRed
:
602 aHandleFillColor
= COL_LIGHTRED
;
604 case BitmapColorIndex::Yellow
:
605 aHandleFillColor
= COL_YELLOW
;
610 pNewOverlayObject
.reset(new sdr::overlay::OverlayHandle(aPosition
, aB2DSize
, /*HandleStrokeColor*/COL_BLACK
, aHandleFillColor
));
614 pNewOverlayObject
= CreateOverlayObject(
615 aPosition
, eColIndex
, eKindOfMarker
,
620 insertNewlyCreatedOverlayObjectForSdrHdl(
621 std::move(pNewOverlayObject
),
622 rPageWindow
.GetObjectContact(),
629 BitmapMarkerKind
SdrHdl::GetNextBigger(BitmapMarkerKind eKnd
)
631 BitmapMarkerKind
eRetval(eKnd
);
635 case BitmapMarkerKind::Rect_7x7
: eRetval
= BitmapMarkerKind::Rect_9x9
; break;
636 case BitmapMarkerKind::Rect_9x9
: eRetval
= BitmapMarkerKind::Rect_11x11
; break;
637 case BitmapMarkerKind::Rect_11x11
: eRetval
= BitmapMarkerKind::Rect_13x13
; break;
639 case BitmapMarkerKind::Circ_7x7
: eRetval
= BitmapMarkerKind::Circ_9x9
; break;
640 case BitmapMarkerKind::Circ_9x9
: eRetval
= BitmapMarkerKind::Circ_11x11
; break;
642 case BitmapMarkerKind::Customshape_7x7
: eRetval
= BitmapMarkerKind::Customshape_9x9
; break;
643 case BitmapMarkerKind::Customshape_9x9
: eRetval
= BitmapMarkerKind::Customshape_11x11
; break;
644 //case BitmapMarkerKind::Customshape_11x11: eRetval = ; break;
646 case BitmapMarkerKind::Elli_7x9
: eRetval
= BitmapMarkerKind::Elli_9x11
; break;
648 case BitmapMarkerKind::Elli_9x7
: eRetval
= BitmapMarkerKind::Elli_11x9
; break;
650 case BitmapMarkerKind::RectPlus_7x7
: eRetval
= BitmapMarkerKind::RectPlus_9x9
; break;
651 case BitmapMarkerKind::RectPlus_9x9
: eRetval
= BitmapMarkerKind::RectPlus_11x11
; break;
653 // let anchor blink with its pressed state
654 case BitmapMarkerKind::Anchor
: eRetval
= BitmapMarkerKind::AnchorPressed
; break;
657 case BitmapMarkerKind::AnchorTR
: eRetval
= BitmapMarkerKind::AnchorPressedTR
; break;
668 OUString
appendMarkerName(BitmapMarkerKind eKindOfMarker
)
670 switch(eKindOfMarker
)
672 case BitmapMarkerKind::Rect_7x7
:
674 case BitmapMarkerKind::Rect_9x9
:
676 case BitmapMarkerKind::Rect_11x11
:
678 case BitmapMarkerKind::Rect_13x13
:
680 case BitmapMarkerKind::Circ_7x7
:
681 case BitmapMarkerKind::Customshape_7x7
:
683 case BitmapMarkerKind::Circ_9x9
:
684 case BitmapMarkerKind::Customshape_9x9
:
686 case BitmapMarkerKind::Circ_11x11
:
687 case BitmapMarkerKind::Customshape_11x11
:
689 case BitmapMarkerKind::Elli_7x9
:
691 case BitmapMarkerKind::Elli_9x11
:
693 case BitmapMarkerKind::Elli_9x7
:
695 case BitmapMarkerKind::Elli_11x9
:
697 case BitmapMarkerKind::RectPlus_7x7
:
699 case BitmapMarkerKind::RectPlus_9x9
:
701 case BitmapMarkerKind::RectPlus_11x11
:
703 case BitmapMarkerKind::Crosshair
:
705 case BitmapMarkerKind::Anchor
:
706 case BitmapMarkerKind::AnchorTR
:
708 case BitmapMarkerKind::AnchorPressed
:
709 case BitmapMarkerKind::AnchorPressedTR
:
710 return "anchor-pressed";
711 case BitmapMarkerKind::Glue
:
712 return "glue-selected";
713 case BitmapMarkerKind::Glue_Deselected
:
714 return "glue-unselected";
721 OUString
appendMarkerColor(BitmapColorIndex eIndex
)
725 case BitmapColorIndex::LightGreen
:
727 case BitmapColorIndex::Cyan
:
729 case BitmapColorIndex::LightCyan
:
731 case BitmapColorIndex::Red
:
733 case BitmapColorIndex::LightRed
:
735 case BitmapColorIndex::Yellow
:
743 BitmapEx
ImpGetBitmapEx(BitmapMarkerKind eKindOfMarker
, BitmapColorIndex eIndex
)
745 // use this code path only when we use HiDPI (for now)
746 if (Application::GetDefaultDevice()->GetDPIScalePercentage() > 100)
748 OUString sMarkerName
= appendMarkerName(eKindOfMarker
);
749 if (!sMarkerName
.isEmpty())
751 OUString
sMarkerPrefix("svx/res/marker-");
754 if (eKindOfMarker
== BitmapMarkerKind::Crosshair
755 || eKindOfMarker
== BitmapMarkerKind::Anchor
756 || eKindOfMarker
== BitmapMarkerKind::AnchorTR
757 || eKindOfMarker
== BitmapMarkerKind::AnchorPressed
758 || eKindOfMarker
== BitmapMarkerKind::AnchorPressedTR
759 || eKindOfMarker
== BitmapMarkerKind::Glue
760 || eKindOfMarker
== BitmapMarkerKind::Glue_Deselected
)
762 aBitmapEx
= vcl::bitmap::loadFromName(sMarkerPrefix
+ sMarkerName
+ ".png");
766 aBitmapEx
= vcl::bitmap::loadFromName(sMarkerPrefix
+ sMarkerName
+ "-" + appendMarkerColor(eIndex
) + ".png");
769 if (!aBitmapEx
.IsEmpty())
774 // if we can't load the marker...
776 static vcl::DeleteOnDeinit
< SdrHdlBitmapSet
> aModernSet(new SdrHdlBitmapSet
);
777 return aModernSet
.get()->GetBitmapEx(eKindOfMarker
, sal_uInt16(eIndex
));
780 } // end anonymous namespace
782 std::unique_ptr
<sdr::overlay::OverlayObject
> SdrHdl::CreateOverlayObject(
783 const basegfx::B2DPoint
& rPos
,
784 BitmapColorIndex eColIndex
, BitmapMarkerKind eKindOfMarker
, Point aMoveOutsideOffset
)
786 std::unique_ptr
<sdr::overlay::OverlayObject
> pRetval
;
788 // support bigger sizes
789 bool bForceBiggerSize(false);
791 if(pHdlList
->GetHdlSize() > 3)
793 switch(eKindOfMarker
)
795 case BitmapMarkerKind::Anchor
:
796 case BitmapMarkerKind::AnchorPressed
:
797 case BitmapMarkerKind::AnchorTR
:
798 case BitmapMarkerKind::AnchorPressedTR
:
800 // #i121463# For anchor, do not simply make bigger because of HdlSize,
801 // do it dependent of IsSelected() which Writer can set in drag mode
804 bForceBiggerSize
= true;
810 bForceBiggerSize
= true;
818 eKindOfMarker
= GetNextBigger(eKindOfMarker
);
821 // This handle has the focus, visualize it
822 if(IsFocusHdl() && pHdlList
&& pHdlList
->GetFocusHdl() == this)
824 // create animated handle
825 BitmapMarkerKind eNextBigger
= GetNextBigger(eKindOfMarker
);
827 if(eNextBigger
== eKindOfMarker
)
829 // this may happen for the not supported getting-bigger types.
830 // Choose an alternative here
831 switch(eKindOfMarker
)
833 case BitmapMarkerKind::Rect_13x13
: eNextBigger
= BitmapMarkerKind::Rect_11x11
; break;
834 case BitmapMarkerKind::Circ_11x11
: eNextBigger
= BitmapMarkerKind::Elli_11x9
; break;
835 case BitmapMarkerKind::Elli_9x11
: eNextBigger
= BitmapMarkerKind::Elli_11x9
; break;
836 case BitmapMarkerKind::Elli_11x9
: eNextBigger
= BitmapMarkerKind::Elli_9x11
; break;
837 case BitmapMarkerKind::RectPlus_11x11
: eNextBigger
= BitmapMarkerKind::Rect_13x13
; break;
839 case BitmapMarkerKind::Crosshair
:
840 eNextBigger
= BitmapMarkerKind::Glue
;
843 case BitmapMarkerKind::Glue
:
844 eNextBigger
= BitmapMarkerKind::Crosshair
;
846 case BitmapMarkerKind::Glue_Deselected
:
847 eNextBigger
= BitmapMarkerKind::Glue
;
854 // create animated handle
855 BitmapEx aBmpEx1
= ImpGetBitmapEx(eKindOfMarker
, eColIndex
);
856 BitmapEx aBmpEx2
= ImpGetBitmapEx(eNextBigger
, eColIndex
);
858 // #i53216# Use system cursor blink time. Use the unsigned value.
859 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
860 const sal_uInt64
nBlinkTime(rStyleSettings
.GetCursorBlinkTime());
862 if(eKindOfMarker
== BitmapMarkerKind::Anchor
|| eKindOfMarker
== BitmapMarkerKind::AnchorPressed
)
864 // when anchor is used take upper left as reference point inside the handle
865 pRetval
.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos
, aBmpEx1
, aBmpEx2
, nBlinkTime
));
867 else if(eKindOfMarker
== BitmapMarkerKind::AnchorTR
|| eKindOfMarker
== BitmapMarkerKind::AnchorPressedTR
)
869 // AnchorTR for SW, take top right as (0,0)
870 pRetval
.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos
, aBmpEx1
, aBmpEx2
, nBlinkTime
,
871 static_cast<sal_uInt16
>(aBmpEx1
.GetSizePixel().Width() - 1), 0,
872 static_cast<sal_uInt16
>(aBmpEx2
.GetSizePixel().Width() - 1), 0));
876 // create centered handle as default
877 pRetval
.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos
, aBmpEx1
, aBmpEx2
, nBlinkTime
,
878 static_cast<sal_uInt16
>(aBmpEx1
.GetSizePixel().Width() - 1) >> 1,
879 static_cast<sal_uInt16
>(aBmpEx1
.GetSizePixel().Height() - 1) >> 1,
880 static_cast<sal_uInt16
>(aBmpEx2
.GetSizePixel().Width() - 1) >> 1,
881 static_cast<sal_uInt16
>(aBmpEx2
.GetSizePixel().Height() - 1) >> 1));
886 // create normal handle: use ImpGetBitmapEx(...) now
887 BitmapEx aBmpEx
= ImpGetBitmapEx(eKindOfMarker
, eColIndex
);
889 // When the image with handles is not found, the bitmap returned is
890 // empty. This is a problem when we use LibreOffice as a library
891 // (through LOKit - for example on Android) even when we don't show
892 // the handles, because the hit test would always return false.
894 // This HACK replaces the empty bitmap with a black 13x13 bitmap handle
895 // so that the hit test works for this case.
896 if (aBmpEx
.IsEmpty())
898 aBmpEx
= BitmapEx(Size(13, 13), 24);
899 aBmpEx
.Erase(COL_BLACK
);
902 if(eKindOfMarker
== BitmapMarkerKind::Anchor
|| eKindOfMarker
== BitmapMarkerKind::AnchorPressed
)
904 // upper left as reference point inside the handle for AnchorPressed, too
905 pRetval
.reset(new sdr::overlay::OverlayBitmapEx(rPos
, aBmpEx
));
907 else if(eKindOfMarker
== BitmapMarkerKind::AnchorTR
|| eKindOfMarker
== BitmapMarkerKind::AnchorPressedTR
)
909 // AnchorTR for SW, take top right as (0,0)
910 pRetval
.reset(new sdr::overlay::OverlayBitmapEx(rPos
, aBmpEx
,
911 static_cast<sal_uInt16
>(aBmpEx
.GetSizePixel().Width() - 1), 0));
915 sal_uInt16
nCenX(static_cast<sal_uInt16
>(aBmpEx
.GetSizePixel().Width() - 1) >> 1);
916 sal_uInt16
nCenY(static_cast<sal_uInt16
>(aBmpEx
.GetSizePixel().Height() - 1) >> 1);
918 if(aMoveOutsideOffset
.X() > 0)
922 else if(aMoveOutsideOffset
.X() < 0)
924 nCenX
= static_cast<sal_uInt16
>(aBmpEx
.GetSizePixel().Width() - 1);
927 if(aMoveOutsideOffset
.Y() > 0)
931 else if(aMoveOutsideOffset
.Y() < 0)
933 nCenY
= static_cast<sal_uInt16
>(aBmpEx
.GetSizePixel().Height() - 1);
936 // create centered handle as default
937 pRetval
.reset(new sdr::overlay::OverlayBitmapEx(rPos
, aBmpEx
, nCenX
, nCenY
));
944 bool SdrHdl::IsHdlHit(const Point
& rPnt
) const
947 basegfx::B2DPoint
aPosition(rPnt
.X(), rPnt
.Y());
948 return maOverlayGroup
.isHitLogic(aPosition
);
951 PointerStyle
SdrHdl::GetPointer() const
953 PointerStyle ePtr
=PointerStyle::Move
;
954 const bool bSize
=eKind
>=SdrHdlKind::UpperLeft
&& eKind
<=SdrHdlKind::LowerRight
;
955 const bool bRot
=pHdlList
!=nullptr && pHdlList
->IsRotateShear();
956 const bool bDis
=pHdlList
!=nullptr && pHdlList
->IsDistortShear();
957 if (bSize
&& pHdlList
!=nullptr && (bRot
|| bDis
)) {
959 case SdrHdlKind::UpperLeft
: case SdrHdlKind::UpperRight
:
960 case SdrHdlKind::LowerLeft
: case SdrHdlKind::LowerRight
: ePtr
=bRot
? PointerStyle::Rotate
: PointerStyle::RefHand
; break;
961 case SdrHdlKind::Left
: case SdrHdlKind::Right
: ePtr
=PointerStyle::VShear
; break;
962 case SdrHdlKind::Upper
: case SdrHdlKind::Lower
: ePtr
=PointerStyle::HShear
; break;
967 // When resizing rotated rectangles, rotate the mouse cursor slightly, too
968 if (bSize
&& nRotationAngle
!=0) {
969 tools::Long nHdlAngle
=0;
971 case SdrHdlKind::LowerRight
: nHdlAngle
=31500; break;
972 case SdrHdlKind::Lower
: nHdlAngle
=27000; break;
973 case SdrHdlKind::LowerLeft
: nHdlAngle
=22500; break;
974 case SdrHdlKind::Left
: nHdlAngle
=18000; break;
975 case SdrHdlKind::UpperLeft
: nHdlAngle
=13500; break;
976 case SdrHdlKind::Upper
: nHdlAngle
=9000; break;
977 case SdrHdlKind::UpperRight
: nHdlAngle
=4500; break;
978 case SdrHdlKind::Right
: nHdlAngle
=0; break;
982 // a little bit more (for rounding)
983 nHdlAngle
= NormAngle36000(nHdlAngle
+ nRotationAngle
+ 2249);
985 switch (static_cast<sal_uInt8
>(nHdlAngle
)) {
986 case 0: ePtr
=PointerStyle::ESize
; break;
987 case 1: ePtr
=PointerStyle::NESize
; break;
988 case 2: ePtr
=PointerStyle::NSize
; break;
989 case 3: ePtr
=PointerStyle::NWSize
; break;
990 case 4: ePtr
=PointerStyle::WSize
; break;
991 case 5: ePtr
=PointerStyle::SWSize
; break;
992 case 6: ePtr
=PointerStyle::SSize
; break;
993 case 7: ePtr
=PointerStyle::SESize
; break;
997 case SdrHdlKind::UpperLeft
: ePtr
=PointerStyle::NWSize
; break;
998 case SdrHdlKind::Upper
: ePtr
=PointerStyle::NSize
; break;
999 case SdrHdlKind::UpperRight
: ePtr
=PointerStyle::NESize
; break;
1000 case SdrHdlKind::Left
: ePtr
=PointerStyle::WSize
; break;
1001 case SdrHdlKind::Right
: ePtr
=PointerStyle::ESize
; break;
1002 case SdrHdlKind::LowerLeft
: ePtr
=PointerStyle::SWSize
; break;
1003 case SdrHdlKind::Lower
: ePtr
=PointerStyle::SSize
; break;
1004 case SdrHdlKind::LowerRight
: ePtr
=PointerStyle::SESize
; break;
1005 case SdrHdlKind::Poly
: ePtr
=PointerStyle::MovePoint
; break;
1006 case SdrHdlKind::Circle
: ePtr
=PointerStyle::Hand
; break;
1007 case SdrHdlKind::Ref1
: ePtr
=PointerStyle::RefHand
; break;
1008 case SdrHdlKind::Ref2
: ePtr
=PointerStyle::RefHand
; break;
1009 case SdrHdlKind::BezierWeight
: ePtr
=PointerStyle::MoveBezierWeight
; break;
1010 case SdrHdlKind::Glue
: ePtr
=PointerStyle::MovePoint
; break;
1011 case SdrHdlKind::CustomShape1
: ePtr
=PointerStyle::Hand
; break;
1020 bool SdrHdl::IsFocusHdl() const
1024 case SdrHdlKind::UpperLeft
:
1025 case SdrHdlKind::Upper
:
1026 case SdrHdlKind::UpperRight
:
1027 case SdrHdlKind::Left
:
1028 case SdrHdlKind::Right
:
1029 case SdrHdlKind::LowerLeft
:
1030 case SdrHdlKind::Lower
:
1031 case SdrHdlKind::LowerRight
:
1033 // if it's an activated TextEdit, it's moved to extended points
1034 return !pHdlList
|| !pHdlList
->IsMoveOutside();
1037 case SdrHdlKind::Move
: // handle to move object
1038 case SdrHdlKind::Poly
: // selected point of polygon or curve
1039 case SdrHdlKind::BezierWeight
: // weight at a curve
1040 case SdrHdlKind::Circle
: // angle of circle segments, corner radius of rectangles
1041 case SdrHdlKind::Ref1
: // reference point 1, e. g. center of rotation
1042 case SdrHdlKind::Ref2
: // reference point 2, e. g. endpoint of reflection axis
1043 case SdrHdlKind::Glue
: // glue point
1045 // for SJ and the CustomShapeHandles:
1046 case SdrHdlKind::CustomShape1
:
1048 case SdrHdlKind::User
:
1060 void SdrHdl::onMouseEnter(const MouseEvent
& /*rMEvt*/)
1064 void SdrHdl::onHelpRequest()
1068 void SdrHdl::onMouseLeave()
1072 BitmapEx
SdrHdl::createGluePointBitmap()
1074 return ImpGetBitmapEx(BitmapMarkerKind::Glue_Deselected
, BitmapColorIndex::LightGreen
);
1077 void SdrHdl::insertNewlyCreatedOverlayObjectForSdrHdl(
1078 std::unique_ptr
<sdr::overlay::OverlayObject
> pOverlayObject
,
1079 const sdr::contact::ObjectContact
& rObjectContact
,
1080 sdr::overlay::OverlayManager
& rOverlayManager
)
1082 // check if we have an OverlayObject
1088 // Add GridOffset for non-linear ViewToDevice transformation (calc)
1089 if(nullptr != GetObj() && rObjectContact
.supportsGridOffsets())
1091 basegfx::B2DVector
aOffset(0.0, 0.0);
1092 const sdr::contact::ViewObjectContact
& rVOC(GetObj()->GetViewContact().GetViewObjectContact(
1093 const_cast<sdr::contact::ObjectContact
&>(rObjectContact
)));
1095 rObjectContact
.calculateGridOffsetForViewOjectContact(aOffset
, rVOC
);
1097 if(!aOffset
.equalZero())
1099 pOverlayObject
->setOffset(aOffset
);
1103 // add to OverlayManager
1104 rOverlayManager
.add(*pOverlayObject
);
1106 // add to local OverlayObjectList - ownership change (!)
1107 maOverlayGroup
.append(std::move(pOverlayObject
));
1110 SdrHdlColor::SdrHdlColor(const Point
& rRef
, Color aCol
, const Size
& rSize
, bool bLum
)
1111 : SdrHdl(rRef
, SdrHdlKind::Color
),
1115 if(IsUseLuminance())
1116 aCol
= GetLuminance(aCol
);
1119 aMarkerColor
= aCol
;
1122 SdrHdlColor::~SdrHdlColor()
1126 void SdrHdlColor::CreateB2dIAObject()
1128 // first throw away old one
1134 SdrMarkView
* pView
= pHdlList
->GetView();
1136 if(!pView
|| pView
->areMarkHandlesHidden())
1139 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1144 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1146 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1148 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1150 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
1153 BitmapEx
aBmpCol(CreateColorDropper(aMarkerColor
));
1154 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
1155 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(new
1156 sdr::overlay::OverlayBitmapEx(
1159 static_cast<sal_uInt16
>(aBmpCol
.GetSizePixel().Width() - 1) >> 1,
1160 static_cast<sal_uInt16
>(aBmpCol
.GetSizePixel().Height() - 1) >> 1
1164 insertNewlyCreatedOverlayObjectForSdrHdl(
1165 std::move(pNewOverlayObject
),
1166 rPageWindow
.GetObjectContact(),
1173 BitmapEx
SdrHdlColor::CreateColorDropper(Color aCol
)
1176 VclPtr
<VirtualDevice
> pWrite(VclPtr
<VirtualDevice
>::Create());
1177 pWrite
->SetOutputSizePixel(aMarkerSize
);
1178 pWrite
->SetBackground(aCol
);
1181 // draw outer border
1182 sal_Int32 nWidth
= aMarkerSize
.Width();
1183 sal_Int32 nHeight
= aMarkerSize
.Height();
1185 pWrite
->SetLineColor(COL_LIGHTGRAY
);
1186 pWrite
->DrawLine(Point(0, 0), Point(0, nHeight
- 1));
1187 pWrite
->DrawLine(Point(1, 0), Point(nWidth
- 1, 0));
1188 pWrite
->SetLineColor(COL_GRAY
);
1189 pWrite
->DrawLine(Point(1, nHeight
- 1), Point(nWidth
- 1, nHeight
- 1));
1190 pWrite
->DrawLine(Point(nWidth
- 1, 1), Point(nWidth
- 1, nHeight
- 2));
1192 // draw lighter UpperLeft
1193 const Color
aLightColor(
1194 static_cast<sal_uInt8
>(::std::min(static_cast<sal_Int16
>(static_cast<sal_Int16
>(aCol
.GetRed()) + sal_Int16(0x0040)), sal_Int16(0x00ff))),
1195 static_cast<sal_uInt8
>(::std::min(static_cast<sal_Int16
>(static_cast<sal_Int16
>(aCol
.GetGreen()) + sal_Int16(0x0040)), sal_Int16(0x00ff))),
1196 static_cast<sal_uInt8
>(::std::min(static_cast<sal_Int16
>(static_cast<sal_Int16
>(aCol
.GetBlue()) + sal_Int16(0x0040)), sal_Int16(0x00ff))));
1197 pWrite
->SetLineColor(aLightColor
);
1198 pWrite
->DrawLine(Point(1, 1), Point(1, nHeight
- 2));
1199 pWrite
->DrawLine(Point(2, 1), Point(nWidth
- 2, 1));
1201 // draw darker LowerRight
1202 const Color
aDarkColor(
1203 static_cast<sal_uInt8
>(::std::max(static_cast<sal_Int16
>(static_cast<sal_Int16
>(aCol
.GetRed()) - sal_Int16(0x0040)), sal_Int16(0x0000))),
1204 static_cast<sal_uInt8
>(::std::max(static_cast<sal_Int16
>(static_cast<sal_Int16
>(aCol
.GetGreen()) - sal_Int16(0x0040)), sal_Int16(0x0000))),
1205 static_cast<sal_uInt8
>(::std::max(static_cast<sal_Int16
>(static_cast<sal_Int16
>(aCol
.GetBlue()) - sal_Int16(0x0040)), sal_Int16(0x0000))));
1206 pWrite
->SetLineColor(aDarkColor
);
1207 pWrite
->DrawLine(Point(2, nHeight
- 2), Point(nWidth
- 2, nHeight
- 2));
1208 pWrite
->DrawLine(Point(nWidth
- 2, 2), Point(nWidth
- 2, nHeight
- 3));
1210 return pWrite
->GetBitmapEx(Point(0,0), aMarkerSize
);
1213 Color
SdrHdlColor::GetLuminance(const Color
& rCol
)
1215 sal_uInt8 aLum
= rCol
.GetLuminance();
1216 Color
aRetval(aLum
, aLum
, aLum
);
1220 void SdrHdlColor::SetColor(Color aNew
, bool bCallLink
)
1222 if(IsUseLuminance())
1223 aNew
= GetLuminance(aNew
);
1225 if(aMarkerColor
!= aNew
)
1227 // remember new color
1228 aMarkerColor
= aNew
;
1230 // create new display
1233 // tell about change
1235 aColorChangeHdl
.Call(this);
1239 void SdrHdlColor::SetSize(const Size
& rNew
)
1241 if(rNew
!= aMarkerSize
)
1243 // remember new size
1246 // create new display
1251 SdrHdlGradient::SdrHdlGradient(const Point
& rRef1
, const Point
& rRef2
, bool bGrad
)
1252 : SdrHdl(rRef1
, bGrad
? SdrHdlKind::Gradient
: SdrHdlKind::Transparence
)
1257 , bMoveSingleHandle(false)
1258 , bMoveFirstHandle(false)
1262 SdrHdlGradient::~SdrHdlGradient()
1266 void SdrHdlGradient::Set2ndPos(const Point
& rPnt
)
1270 // remember new position
1273 // create new display
1278 void SdrHdlGradient::CreateB2dIAObject()
1280 // first throw away old one
1286 SdrMarkView
* pView
= pHdlList
->GetView();
1288 if(!pView
|| pView
->areMarkHandlesHidden())
1291 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1296 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1298 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1300 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1302 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
1305 // striped line in between
1306 basegfx::B2DVector
aVec(a2ndPos
.X() - aPos
.X(), a2ndPos
.Y() - aPos
.Y());
1307 double fVecLen
= aVec
.getLength();
1308 double fLongPercentArrow
= (1.0 - 0.05) * fVecLen
;
1309 double fHalfArrowWidth
= (0.05 * 0.5) * fVecLen
;
1311 basegfx::B2DVector
aPerpend(-aVec
.getY(), aVec
.getX());
1312 sal_Int32 nMidX
= static_cast<sal_Int32
>(aPos
.X() + aVec
.getX() * fLongPercentArrow
);
1313 sal_Int32 nMidY
= static_cast<sal_Int32
>(aPos
.Y() + aVec
.getY() * fLongPercentArrow
);
1314 Point
aMidPoint(nMidX
, nMidY
);
1316 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
1317 basegfx::B2DPoint
aMidPos(aMidPoint
.X(), aMidPoint
.Y());
1319 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(new
1320 sdr::overlay::OverlayLineStriped(
1324 pNewOverlayObject
->setBaseColor(IsGradient() ? COL_BLACK
: COL_BLUE
);
1327 insertNewlyCreatedOverlayObjectForSdrHdl(
1328 std::move(pNewOverlayObject
),
1329 rPageWindow
.GetObjectContact(),
1333 Point
aLeft(aMidPoint
.X() + static_cast<sal_Int32
>(aPerpend
.getX() * fHalfArrowWidth
),
1334 aMidPoint
.Y() + static_cast<sal_Int32
>(aPerpend
.getY() * fHalfArrowWidth
));
1335 Point
aRight(aMidPoint
.X() - static_cast<sal_Int32
>(aPerpend
.getX() * fHalfArrowWidth
),
1336 aMidPoint
.Y() - static_cast<sal_Int32
>(aPerpend
.getY() * fHalfArrowWidth
));
1338 basegfx::B2DPoint
aPositionLeft(aLeft
.X(), aLeft
.Y());
1339 basegfx::B2DPoint
aPositionRight(aRight
.X(), aRight
.Y());
1340 basegfx::B2DPoint
aPosition2(a2ndPos
.X(), a2ndPos
.Y());
1342 pNewOverlayObject
.reset(new
1343 sdr::overlay::OverlayTriangle(
1347 IsGradient() ? COL_BLACK
: COL_BLUE
1351 insertNewlyCreatedOverlayObjectForSdrHdl(
1352 std::move(pNewOverlayObject
),
1353 rPageWindow
.GetObjectContact(),
1360 IMPL_LINK_NOARG(SdrHdlGradient
, ColorChangeHdl
, SdrHdlColor
*, void)
1363 FromIAOToItem(GetObj(), true, true);
1366 void SdrHdlGradient::FromIAOToItem(SdrObject
* _pObj
, bool bSetItemOnObject
, bool bUndo
)
1368 // from IAO positions and colors to gradient
1369 const SfxItemSet
& rSet
= _pObj
->GetMergedItemSet();
1371 GradTransGradient aOldGradTransGradient
;
1372 GradTransGradient aGradTransGradient
;
1373 GradTransVector aGradTransVector
;
1375 aGradTransVector
.maPositionA
= basegfx::B2DPoint(GetPos().X(), GetPos().Y());
1376 aGradTransVector
.maPositionB
= basegfx::B2DPoint(Get2ndPos().X(), Get2ndPos().Y());
1378 aGradTransVector
.aCol1
= pColHdl1
->GetColor();
1380 aGradTransVector
.aCol2
= pColHdl2
->GetColor();
1383 aOldGradTransGradient
.aGradient
= rSet
.Get(XATTR_FILLGRADIENT
).GetGradientValue();
1385 aOldGradTransGradient
.aGradient
= rSet
.Get(XATTR_FILLFLOATTRANSPARENCE
).GetGradientValue();
1387 // transform vector data to gradient
1388 GradTransformer::VecToGrad(aGradTransVector
, aGradTransGradient
, aOldGradTransGradient
, _pObj
, bMoveSingleHandle
, bMoveFirstHandle
);
1390 if(bSetItemOnObject
)
1392 SdrModel
& rModel(_pObj
->getSdrModelFromSdrObject());
1393 SfxItemSet
aNewSet(rModel
.GetItemPool());
1394 const OUString aString
;
1398 XFillGradientItem
aNewGradItem(aString
, aGradTransGradient
.aGradient
);
1399 aNewSet
.Put(aNewGradItem
);
1403 XFillFloatTransparenceItem
aNewTransItem(aString
, aGradTransGradient
.aGradient
);
1404 aNewSet
.Put(aNewTransItem
);
1407 if(bUndo
&& rModel
.IsUndoEnabled())
1409 rModel
.BegUndo(SvxResId(IsGradient() ? SIP_XA_FILLGRADIENT
: SIP_XA_FILLTRANSPARENCE
));
1410 rModel
.AddUndo(rModel
.GetSdrUndoFactory().CreateUndoAttrObject(*_pObj
));
1414 pObj
->SetMergedItemSetAndBroadcast(aNewSet
);
1417 // back transformation, set values on pIAOHandle
1418 GradTransformer::GradToVec(aGradTransGradient
, aGradTransVector
, _pObj
);
1420 SetPos(Point(FRound(aGradTransVector
.maPositionA
.getX()), FRound(aGradTransVector
.maPositionA
.getY())));
1421 Set2ndPos(Point(FRound(aGradTransVector
.maPositionB
.getX()), FRound(aGradTransVector
.maPositionB
.getY())));
1424 pColHdl1
->SetPos(Point(FRound(aGradTransVector
.maPositionA
.getX()), FRound(aGradTransVector
.maPositionA
.getY())));
1425 pColHdl1
->SetColor(aGradTransVector
.aCol1
);
1429 pColHdl2
->SetPos(Point(FRound(aGradTransVector
.maPositionB
.getX()), FRound(aGradTransVector
.maPositionB
.getY())));
1430 pColHdl2
->SetColor(aGradTransVector
.aCol2
);
1435 SdrHdlLine::~SdrHdlLine() {}
1437 void SdrHdlLine::CreateB2dIAObject()
1439 // first throw away old one
1445 SdrMarkView
* pView
= pHdlList
->GetView();
1447 if(!(pView
&& !pView
->areMarkHandlesHidden() && pHdl1
&& pHdl2
))
1450 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1455 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1457 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1459 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1461 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
1464 basegfx::B2DPoint
aPosition1(pHdl1
->GetPos().X(), pHdl1
->GetPos().Y());
1465 basegfx::B2DPoint
aPosition2(pHdl2
->GetPos().X(), pHdl2
->GetPos().Y());
1467 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(new
1468 sdr::overlay::OverlayLineStriped(
1474 pNewOverlayObject
->setBaseColor(COL_LIGHTRED
);
1477 insertNewlyCreatedOverlayObjectForSdrHdl(
1478 std::move(pNewOverlayObject
),
1479 rPageWindow
.GetObjectContact(),
1486 PointerStyle
SdrHdlLine::GetPointer() const
1488 return PointerStyle::RefHand
;
1492 SdrHdlBezWgt::~SdrHdlBezWgt() {}
1494 void SdrHdlBezWgt::CreateB2dIAObject()
1497 SdrHdl::CreateB2dIAObject();
1503 SdrMarkView
* pView
= pHdlList
->GetView();
1505 if(!pView
|| pView
->areMarkHandlesHidden())
1508 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1513 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1515 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1517 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1519 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
1522 basegfx::B2DPoint
aPosition1(pHdl1
->GetPos().X(), pHdl1
->GetPos().Y());
1523 basegfx::B2DPoint
aPosition2(aPos
.X(), aPos
.Y());
1525 if(!aPosition1
.equal(aPosition2
))
1527 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(new
1528 sdr::overlay::OverlayLineStriped(
1533 // line part is not hittable
1534 pNewOverlayObject
->setHittable(false);
1537 pNewOverlayObject
->setBaseColor(COL_LIGHTBLUE
);
1540 insertNewlyCreatedOverlayObjectForSdrHdl(
1541 std::move(pNewOverlayObject
),
1542 rPageWindow
.GetObjectContact(),
1551 E3dVolumeMarker::E3dVolumeMarker(const basegfx::B2DPolyPolygon
& rWireframePoly
)
1553 aWireframePoly
= rWireframePoly
;
1556 void E3dVolumeMarker::CreateB2dIAObject()
1562 SdrMarkView
* pView
= pHdlList
->GetView();
1564 if(!pView
|| pView
->areMarkHandlesHidden())
1567 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1572 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1574 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1576 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1578 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
1579 if (xManager
.is() && aWireframePoly
.count())
1581 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(new
1582 sdr::overlay::OverlayPolyPolygonStripedAndFilled(
1585 pNewOverlayObject
->setBaseColor(COL_BLACK
);
1588 insertNewlyCreatedOverlayObjectForSdrHdl(
1589 std::move(pNewOverlayObject
),
1590 rPageWindow
.GetObjectContact(),
1598 ImpEdgeHdl::~ImpEdgeHdl()
1602 void ImpEdgeHdl::CreateB2dIAObject()
1604 if(nObjHdlNum
<= 1 && pObj
)
1606 // first throw away old one
1609 BitmapColorIndex eColIndex
= BitmapColorIndex::LightCyan
;
1610 BitmapMarkerKind eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
1614 SdrMarkView
* pView
= pHdlList
->GetView();
1616 if(pView
&& !pView
->areMarkHandlesHidden())
1618 const SdrEdgeObj
* pEdge
= static_cast<SdrEdgeObj
*>(pObj
);
1620 if(pEdge
->GetConnectedNode(nObjHdlNum
== 0) != nullptr)
1621 eColIndex
= BitmapColorIndex::LightRed
;
1625 // Handle with plus sign inside
1626 eKindOfMarker
= BitmapMarkerKind::Circ_7x7
;
1629 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1633 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1635 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1637 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1639 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
1642 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
1643 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(CreateOverlayObject(
1649 insertNewlyCreatedOverlayObjectForSdrHdl(
1650 std::move(pNewOverlayObject
),
1651 rPageWindow
.GetObjectContact(),
1663 SdrHdl::CreateB2dIAObject();
1667 void ImpEdgeHdl::SetLineCode(SdrEdgeLineCode eCode
)
1669 if(eLineCode
!= eCode
)
1671 // remember new value
1674 // create new display
1679 PointerStyle
ImpEdgeHdl::GetPointer() const
1681 SdrEdgeObj
* pEdge
=dynamic_cast<SdrEdgeObj
*>( pObj
);
1683 return SdrHdl::GetPointer();
1685 return PointerStyle::MovePoint
;
1687 return PointerStyle::ESize
;
1689 return PointerStyle::SSize
;
1692 bool ImpEdgeHdl::IsHorzDrag() const
1694 SdrEdgeObj
* pEdge
=dynamic_cast<SdrEdgeObj
*>( pObj
);
1700 SdrEdgeKind eEdgeKind
= pEdge
->GetObjectItem(SDRATTR_EDGEKIND
).GetValue();
1702 const SdrEdgeInfoRec
& rInfo
=pEdge
->aEdgeInfo
;
1703 if (eEdgeKind
==SdrEdgeKind::OrthoLines
|| eEdgeKind
==SdrEdgeKind::Bezier
)
1705 return !rInfo
.ImpIsHorzLine(eLineCode
,*pEdge
->pEdgeTrack
);
1707 else if (eEdgeKind
==SdrEdgeKind::ThreeLines
)
1709 tools::Long nAngle
=nObjHdlNum
==2 ? rInfo
.nAngle1
: rInfo
.nAngle2
;
1710 return nAngle
==0 || nAngle
==18000;
1716 ImpMeasureHdl::~ImpMeasureHdl()
1720 void ImpMeasureHdl::CreateB2dIAObject()
1722 // first throw away old one
1728 SdrMarkView
* pView
= pHdlList
->GetView();
1730 if(!pView
|| pView
->areMarkHandlesHidden())
1733 BitmapColorIndex eColIndex
= BitmapColorIndex::LightCyan
;
1734 BitmapMarkerKind eKindOfMarker
= BitmapMarkerKind::Rect_9x9
;
1738 eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
1743 eColIndex
= BitmapColorIndex::Cyan
;
1746 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1751 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1753 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1755 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1757 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
1760 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
1761 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(CreateOverlayObject(
1767 insertNewlyCreatedOverlayObjectForSdrHdl(
1768 std::move(pNewOverlayObject
),
1769 rPageWindow
.GetObjectContact(),
1776 PointerStyle
ImpMeasureHdl::GetPointer() const
1780 case 0: case 1: return PointerStyle::Hand
;
1781 case 2: case 3: return PointerStyle::MovePoint
;
1782 case 4: case 5: return SdrHdl::GetPointer(); // will then be rotated appropriately
1784 return PointerStyle::NotAllowed
;
1788 ImpTextframeHdl::ImpTextframeHdl(const tools::Rectangle
& rRect
) :
1789 SdrHdl(rRect
.TopLeft(),SdrHdlKind::Move
),
1794 void ImpTextframeHdl::CreateB2dIAObject()
1796 // first throw away old one
1802 SdrMarkView
* pView
= pHdlList
->GetView();
1804 if(!pView
|| pView
->areMarkHandlesHidden())
1807 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1812 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1814 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1816 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1818 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
1821 const basegfx::B2DPoint
aTopLeft(maRect
.Left(), maRect
.Top());
1822 const basegfx::B2DPoint
aBottomRight(maRect
.Right(), maRect
.Bottom());
1823 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer
;
1824 const Color
aHilightColor(aSvtOptionsDrawinglayer
.getHilightColor());
1825 const double fTransparence(aSvtOptionsDrawinglayer
.GetTransparentSelectionPercent() * 0.01);
1827 std::unique_ptr
<sdr::overlay::OverlayRectangle
> pNewOverlayObject(new sdr::overlay::OverlayRectangle(
1834 nRotationAngle
* -F_PI18000
,
1835 true)); // allow animation; the Handle is not shown at text edit time
1837 pNewOverlayObject
->setHittable(false);
1840 insertNewlyCreatedOverlayObjectForSdrHdl(
1841 std::move(pNewOverlayObject
),
1842 rPageWindow
.GetObjectContact(),
1850 static bool ImpSdrHdlListSorter(std::unique_ptr
<SdrHdl
> const& lhs
, std::unique_ptr
<SdrHdl
> const& rhs
)
1852 SdrHdlKind eKind1
=lhs
->GetKind();
1853 SdrHdlKind eKind2
=rhs
->GetKind();
1854 // Level 1: first normal handles, then Glue, then User, then Plus handles, then reference point handles
1859 if (eKind1
==SdrHdlKind::Ref1
|| eKind1
==SdrHdlKind::Ref2
|| eKind1
==SdrHdlKind::MirrorAxis
) n1
=5;
1860 else if (eKind1
==SdrHdlKind::Glue
) n1
=2;
1861 else if (eKind1
==SdrHdlKind::User
) n1
=3;
1862 else if (eKind1
==SdrHdlKind::SmartTag
) n1
=0;
1863 if (eKind2
==SdrHdlKind::Ref1
|| eKind2
==SdrHdlKind::Ref2
|| eKind2
==SdrHdlKind::MirrorAxis
) n2
=5;
1864 else if (eKind2
==SdrHdlKind::Glue
) n2
=2;
1865 else if (eKind2
==SdrHdlKind::User
) n2
=3;
1866 else if (eKind2
==SdrHdlKind::SmartTag
) n2
=0;
1868 if (lhs
->IsPlusHdl()) n1
=4;
1869 if (rhs
->IsPlusHdl()) n2
=4;
1872 // Level 2: PageView (Pointer)
1873 SdrPageView
* pPV1
=lhs
->GetPageView();
1874 SdrPageView
* pPV2
=rhs
->GetPageView();
1877 // Level 3: Position (x+y)
1878 SdrObject
* pObj1
=lhs
->GetObj();
1879 SdrObject
* pObj2
=rhs
->GetObj();
1882 sal_uInt32 nNum1
=lhs
->GetObjHdlNum();
1883 sal_uInt32 nNum2
=rhs
->GetObjHdlNum();
1887 return lhs
<rhs
; // Hack, to always get to the same sorting
1888 return static_cast<sal_uInt16
>(eKind1
)<static_cast<sal_uInt16
>(eKind2
);
1911 // Helper struct for re-sorting handles
1912 struct ImplHdlAndIndex
1922 // Helper method for sorting handles taking care of OrdNums, keeping order in
1923 // single objects and re-sorting polygon handles intuitively
1924 static int ImplSortHdlFunc( const void* pVoid1
, const void* pVoid2
)
1926 const ImplHdlAndIndex
* p1
= static_cast<ImplHdlAndIndex
const *>(pVoid1
);
1927 const ImplHdlAndIndex
* p2
= static_cast<ImplHdlAndIndex
const *>(pVoid2
);
1929 if(p1
->mpHdl
->GetObj() == p2
->mpHdl
->GetObj())
1931 if(p1
->mpHdl
->GetObj() && dynamic_cast<const SdrPathObj
*>(p1
->mpHdl
->GetObj()) != nullptr)
1933 // same object and a path object
1934 if((p1
->mpHdl
->GetKind() == SdrHdlKind::Poly
|| p1
->mpHdl
->GetKind() == SdrHdlKind::BezierWeight
)
1935 && (p2
->mpHdl
->GetKind() == SdrHdlKind::Poly
|| p2
->mpHdl
->GetKind() == SdrHdlKind::BezierWeight
))
1937 // both handles are point or control handles
1938 if(p1
->mpHdl
->GetPolyNum() == p2
->mpHdl
->GetPolyNum())
1940 if(p1
->mpHdl
->GetPointNum() < p2
->mpHdl
->GetPointNum())
1949 else if(p1
->mpHdl
->GetPolyNum() < p2
->mpHdl
->GetPolyNum())
1962 if(!p1
->mpHdl
->GetObj())
1966 else if(!p2
->mpHdl
->GetObj())
1972 // different objects, use OrdNum for sort
1973 const sal_uInt32 nOrdNum1
= p1
->mpHdl
->GetObj()->GetOrdNum();
1974 const sal_uInt32 nOrdNum2
= p2
->mpHdl
->GetObj()->GetOrdNum();
1976 if(nOrdNum1
< nOrdNum2
)
1987 // fallback to indices
1988 if(p1
->mnIndex
< p2
->mnIndex
)
2000 void SdrHdlList::TravelFocusHdl(bool bForward
)
2002 // security correction
2003 if (mnFocusIndex
>= GetHdlCount())
2004 mnFocusIndex
= SAL_MAX_SIZE
;
2009 // take care of old handle
2010 const size_t nOldHdlNum(mnFocusIndex
);
2011 SdrHdl
* pOld
= nullptr;
2012 if (nOldHdlNum
< GetHdlCount())
2013 pOld
= GetHdl(nOldHdlNum
);
2017 // switch off old handle
2018 mnFocusIndex
= SAL_MAX_SIZE
;
2022 // allocate pointer array for sorted handle list
2023 std::unique_ptr
<ImplHdlAndIndex
[]> pHdlAndIndex(new ImplHdlAndIndex
[maList
.size()]);
2025 // build sorted handle list
2026 for( size_t a
= 0; a
< maList
.size(); ++a
)
2028 pHdlAndIndex
[a
].mpHdl
= maList
[a
].get();
2029 pHdlAndIndex
[a
].mnIndex
= a
;
2032 qsort(pHdlAndIndex
.get(), maList
.size(), sizeof(ImplHdlAndIndex
), ImplSortHdlFunc
);
2034 // look for old num in sorted array
2035 size_t nOldHdl(nOldHdlNum
);
2037 if(nOldHdlNum
!= SAL_MAX_SIZE
)
2039 for(size_t a
= 0; a
< maList
.size(); ++a
)
2041 if(pHdlAndIndex
[a
].mpHdl
== pOld
)
2050 size_t nNewHdl(nOldHdl
);
2052 // do the focus travel
2055 if(nOldHdl
!= SAL_MAX_SIZE
)
2057 if(nOldHdl
== maList
.size() - 1)
2060 nNewHdl
= SAL_MAX_SIZE
;
2064 // simply the next handle
2070 // start forward run at first entry
2076 if(nOldHdl
== SAL_MAX_SIZE
)
2078 // start backward run at last entry
2079 nNewHdl
= maList
.size() - 1;
2087 nNewHdl
= SAL_MAX_SIZE
;
2091 // simply the previous handle
2098 sal_uIntPtr
nNewHdlNum(nNewHdl
);
2100 // look for old num in sorted array
2101 if(nNewHdl
!= SAL_MAX_SIZE
)
2103 SdrHdl
* pNew
= pHdlAndIndex
[nNewHdl
].mpHdl
;
2105 for(size_t a
= 0; a
< maList
.size(); ++a
)
2107 if(maList
[a
].get() == pNew
)
2115 // take care of next handle
2116 if(nOldHdlNum
!= nNewHdlNum
)
2118 mnFocusIndex
= nNewHdlNum
;
2119 if (mnFocusIndex
< GetHdlCount())
2121 SdrHdl
* pNew
= GetHdl(mnFocusIndex
);
2127 SdrHdl
* SdrHdlList::GetFocusHdl() const
2129 if(mnFocusIndex
< GetHdlCount())
2130 return GetHdl(mnFocusIndex
);
2135 void SdrHdlList::SetFocusHdl(SdrHdl
* pNew
)
2140 SdrHdl
* pActual
= GetFocusHdl();
2142 if(pActual
&& pActual
== pNew
)
2145 const size_t nNewHdlNum
= GetHdlNum(pNew
);
2147 if(nNewHdlNum
!= SAL_MAX_SIZE
)
2149 mnFocusIndex
= nNewHdlNum
;
2160 void SdrHdlList::ResetFocusHdl()
2162 SdrHdl
* pHdl
= GetFocusHdl();
2164 mnFocusIndex
= SAL_MAX_SIZE
;
2173 SdrHdlList::SdrHdlList(SdrMarkView
* pV
)
2174 : mnFocusIndex(SAL_MAX_SIZE
),
2178 bRotateShear
= false;
2179 bMoveOutside
= false;
2180 bDistortShear
= false;
2183 SdrHdlList::~SdrHdlList()
2188 void SdrHdlList::SetHdlSize(sal_uInt16 nSiz
)
2190 if(nHdlSize
!= nSiz
)
2192 // remember new value
2195 // propagate change to IAOs
2196 for(size_t i
=0; i
<GetHdlCount(); ++i
)
2198 SdrHdl
* pHdl
= GetHdl(i
);
2204 void SdrHdlList::SetMoveOutside(bool bOn
)
2206 if(bMoveOutside
!= bOn
)
2208 // remember new value
2211 // propagate change to IAOs
2212 for(size_t i
=0; i
<GetHdlCount(); ++i
)
2214 SdrHdl
* pHdl
= GetHdl(i
);
2220 void SdrHdlList::SetRotateShear(bool bOn
)
2225 void SdrHdlList::SetDistortShear(bool bOn
)
2227 bDistortShear
= bOn
;
2230 std::unique_ptr
<SdrHdl
> SdrHdlList::RemoveHdl(size_t nNum
)
2232 std::unique_ptr
<SdrHdl
> pRetval
= std::move(maList
[nNum
]);
2233 maList
.erase(maList
.begin() + nNum
);
2238 void SdrHdlList::RemoveAllByKind(SdrHdlKind eKind
)
2240 maList
.erase(std::remove_if(maList
.begin(), maList
.end(),
2241 [&eKind
](std::unique_ptr
<SdrHdl
>& rItem
) { return rItem
->GetKind() == eKind
; }),
2245 void SdrHdlList::Clear()
2250 bDistortShear
=false;
2253 void SdrHdlList::Sort()
2255 // remember currently focused handle
2256 SdrHdl
* pPrev
= GetFocusHdl();
2258 std::sort( maList
.begin(), maList
.end(), ImpSdrHdlListSorter
);
2260 // get now and compare
2261 SdrHdl
* pNow
= GetFocusHdl();
2277 size_t SdrHdlList::GetHdlNum(const SdrHdl
* pHdl
) const
2280 return SAL_MAX_SIZE
;
2281 auto it
= std::find_if( maList
.begin(), maList
.end(),
2282 [&](const std::unique_ptr
<SdrHdl
> & p
) { return p
.get() == pHdl
; });
2283 assert(it
!= maList
.end());
2284 if( it
== maList
.end() )
2285 return SAL_MAX_SIZE
;
2286 return it
- maList
.begin();
2289 void SdrHdlList::AddHdl(std::unique_ptr
<SdrHdl
> pHdl
)
2292 pHdl
->SetHdlList(this);
2293 maList
.push_back(std::move(pHdl
));
2296 SdrHdl
* SdrHdlList::IsHdlListHit(const Point
& rPnt
) const
2298 SdrHdl
* pRet
=nullptr;
2299 const size_t nCount
=GetHdlCount();
2301 while (nNum
>0 && pRet
==nullptr)
2304 SdrHdl
* pHdl
=GetHdl(nNum
);
2305 if (pHdl
->IsHdlHit(rPnt
))
2311 SdrHdl
* SdrHdlList::GetHdl(SdrHdlKind eKind1
) const
2313 SdrHdl
* pRet
=nullptr;
2314 for (size_t i
=0; i
<GetHdlCount() && pRet
==nullptr; ++i
)
2316 SdrHdl
* pHdl
=GetHdl(i
);
2317 if (pHdl
->GetKind()==eKind1
)
2323 void SdrHdlList::MoveTo(SdrHdlList
& rOther
)
2325 for (auto & pHdl
: maList
)
2326 pHdl
->SetHdlList(&rOther
);
2327 rOther
.maList
.insert(rOther
.maList
.end(),
2328 std::make_move_iterator(maList
.begin()), std::make_move_iterator(maList
.end()));
2332 SdrCropHdl::SdrCropHdl(
2334 SdrHdlKind eNewKind
,
2337 : SdrHdl(rPnt
, eNewKind
),
2339 mfRotation(fRotation
)
2344 BitmapEx
SdrCropHdl::GetBitmapForHandle( const BitmapEx
& rBitmap
, int nSize
)
2346 int nPixelSize
= 0, nX
= 0, nY
= 0, nOffset
= 0;
2353 else if( nSize
<=4 )
2366 case SdrHdlKind::UpperLeft
: nX
= 0; nY
= 0; break;
2367 case SdrHdlKind::Upper
: nX
= 1; nY
= 0; break;
2368 case SdrHdlKind::UpperRight
: nX
= 2; nY
= 0; break;
2369 case SdrHdlKind::Left
: nX
= 0; nY
= 1; break;
2370 case SdrHdlKind::Right
: nX
= 2; nY
= 1; break;
2371 case SdrHdlKind::LowerLeft
: nX
= 0; nY
= 2; break;
2372 case SdrHdlKind::Lower
: nX
= 1; nY
= 2; break;
2373 case SdrHdlKind::LowerRight
: nX
= 2; nY
= 2; break;
2377 tools::Rectangle
aSourceRect( Point( nX
* nPixelSize
+ nOffset
, nY
* nPixelSize
), Size(nPixelSize
, nPixelSize
) );
2379 BitmapEx
aRetval(rBitmap
);
2380 aRetval
.Crop(aSourceRect
);
2385 void SdrCropHdl::CreateB2dIAObject()
2387 // first throw away old one
2390 SdrMarkView
* pView
= pHdlList
? pHdlList
->GetView() : nullptr;
2391 SdrPageView
* pPageView
= pView
? pView
->GetSdrPageView() : nullptr;
2393 if( !pPageView
|| pView
->areMarkHandlesHidden() )
2396 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
2397 int nHdlSize
= pHdlList
->GetHdlSize();
2399 const BitmapEx
aHandlesBitmap(SIP_SA_CROP_MARKERS
);
2400 BitmapEx
aBmpEx1( GetBitmapForHandle( aHandlesBitmap
, nHdlSize
) );
2402 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
2404 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
2406 if(rPageWindow
.GetPaintWindow().OutputToWindow())
2408 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
2411 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
2413 std::unique_ptr
<sdr::overlay::OverlayObject
> pOverlayObject
;
2415 // animate focused handles
2416 if(IsFocusHdl() && (pHdlList
->GetFocusHdl() == this))
2421 BitmapEx
aBmpEx2( GetBitmapForHandle( aHandlesBitmap
, nHdlSize
+ 1 ) );
2423 const sal_uInt64 nBlinkTime
= rStyleSettings
.GetCursorBlinkTime();
2425 pOverlayObject
.reset(new sdr::overlay::OverlayAnimatedBitmapEx(
2430 static_cast<sal_uInt16
>(aBmpEx1
.GetSizePixel().Width() - 1) >> 1,
2431 static_cast<sal_uInt16
>(aBmpEx1
.GetSizePixel().Height() - 1) >> 1,
2432 static_cast<sal_uInt16
>(aBmpEx2
.GetSizePixel().Width() - 1) >> 1,
2433 static_cast<sal_uInt16
>(aBmpEx2
.GetSizePixel().Height() - 1) >> 1,
2439 // create centered handle as default
2440 pOverlayObject
.reset(new sdr::overlay::OverlayBitmapEx(
2443 static_cast<sal_uInt16
>(aBmpEx1
.GetSizePixel().Width() - 1) >> 1,
2444 static_cast<sal_uInt16
>(aBmpEx1
.GetSizePixel().Height() - 1) >> 1,
2451 insertNewlyCreatedOverlayObjectForSdrHdl(
2452 std::move(pOverlayObject
),
2453 rPageWindow
.GetObjectContact(),
2461 // with the correction of crop handling I could get rid of the extra mirroring flag, adapted stuff
2464 SdrCropViewHdl::SdrCropViewHdl(
2465 const basegfx::B2DHomMatrix
& rObjectTransform
,
2466 const Graphic
& rGraphic
,
2471 : SdrHdl(Point(), SdrHdlKind::User
),
2472 maObjectTransform(rObjectTransform
),
2473 maGraphic(rGraphic
),
2474 mfCropLeft(fCropLeft
),
2475 mfCropTop(fCropTop
),
2476 mfCropRight(fCropRight
),
2477 mfCropBottom(fCropBottom
)
2483 void translateRotationToMirroring(basegfx::B2DVector
& scale
, double * rotate
) {
2484 assert(rotate
!= nullptr);
2486 // detect 180 degree rotation, this is the same as mirrored in X and Y,
2487 // thus change to mirroring. Prefer mirroring here. Use the equal call
2488 // with getSmallValue here, the original which uses rtl::math::approxEqual
2489 // is too correct here. Maybe this changes with enhanced precision in aw080
2490 // to the better so that this can be reduced to the more precise call again
2491 if(basegfx::fTools::equal(fabs(*rotate
), F_PI
, 0.000000001))
2493 scale
.setX(scale
.getX() * -1.0);
2494 scale
.setY(scale
.getY() * -1.0);
2501 void SdrCropViewHdl::CreateB2dIAObject()
2504 SdrMarkView
* pView
= pHdlList
? pHdlList
->GetView() : nullptr;
2505 SdrPageView
* pPageView
= pView
? pView
->GetSdrPageView() : nullptr;
2507 if(!pPageView
|| pView
->areMarkHandlesHidden())
2512 // decompose to have current translate and scale
2513 basegfx::B2DVector aScale
, aTranslate
;
2514 double fRotate
, fShearX
;
2516 maObjectTransform
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
2518 if(aScale
.equalZero())
2523 translateRotationToMirroring(aScale
, &fRotate
);
2525 // remember mirroring, reset at Scale and adapt crop values for usage;
2526 // mirroring can stay in the object transformation, so do not have to
2527 // cope with it here (except later for the CroppedImage transformation,
2529 const bool bMirroredX(aScale
.getX() < 0.0);
2530 const bool bMirroredY(aScale
.getY() < 0.0);
2531 double fCropLeft(mfCropLeft
);
2532 double fCropTop(mfCropTop
);
2533 double fCropRight(mfCropRight
);
2534 double fCropBottom(mfCropBottom
);
2538 aScale
.setX(-aScale
.getX());
2543 aScale
.setY(-aScale
.getY());
2546 // create target translate and scale
2547 const basegfx::B2DVector
aTargetScale(
2548 aScale
.getX() + fCropRight
+ fCropLeft
,
2549 aScale
.getY() + fCropBottom
+ fCropTop
);
2550 const basegfx::B2DVector
aTargetTranslate(
2551 aTranslate
.getX() - fCropLeft
,
2552 aTranslate
.getY() - fCropTop
);
2554 // create ranges to make comparisons
2555 const basegfx::B2DRange
aCurrentForCompare(
2556 aTranslate
.getX(), aTranslate
.getY(),
2557 aTranslate
.getX() + aScale
.getX(), aTranslate
.getY() + aScale
.getY());
2558 basegfx::B2DRange
aCropped(
2559 aTargetTranslate
.getX(), aTargetTranslate
.getY(),
2560 aTargetTranslate
.getX() + aTargetScale
.getX(), aTargetTranslate
.getY() + aTargetScale
.getY());
2562 if(aCropped
.isEmpty())
2564 // nothing to return since cropped content is completely empty
2568 if(aCurrentForCompare
.equal(aCropped
))
2574 // back-transform to have values in unit coordinates
2575 basegfx::B2DHomMatrix aBackToUnit
;
2576 aBackToUnit
.translate(-aTranslate
.getX(), -aTranslate
.getY());
2578 basegfx::fTools::equalZero(aScale
.getX()) ? 1.0 : 1.0 / aScale
.getX(),
2579 basegfx::fTools::equalZero(aScale
.getY()) ? 1.0 : 1.0 / aScale
.getY());
2581 // transform cropped back to unit coordinates
2582 aCropped
.transform(aBackToUnit
);
2584 // prepare crop PolyPolygon
2585 basegfx::B2DPolygon
aGraphicOutlinePolygon(
2586 basegfx::utils::createPolygonFromRect(
2588 basegfx::B2DPolyPolygon
aCropPolyPolygon(aGraphicOutlinePolygon
);
2590 // current range is unit range
2591 basegfx::B2DRange
aOverlap(0.0, 0.0, 1.0, 1.0);
2593 aOverlap
.intersect(aCropped
);
2595 if(!aOverlap
.isEmpty())
2597 aCropPolyPolygon
.append(
2598 basegfx::utils::createPolygonFromRect(
2602 // transform to object coordinates to prepare for clip
2603 aCropPolyPolygon
.transform(maObjectTransform
);
2604 aGraphicOutlinePolygon
.transform(maObjectTransform
);
2606 // create cropped transformation
2607 basegfx::B2DHomMatrix aCroppedTransform
;
2609 aCroppedTransform
.scale(
2610 aCropped
.getWidth(),
2611 aCropped
.getHeight());
2612 aCroppedTransform
.translate(
2614 aCropped
.getMinY());
2615 aCroppedTransform
= maObjectTransform
* aCroppedTransform
;
2617 // prepare graphic primitive (transformed)
2618 const drawinglayer::primitive2d::Primitive2DReference
aGraphic(
2619 new drawinglayer::primitive2d::GraphicPrimitive2D(
2623 // prepare outline polygon for whole graphic
2624 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer
;
2625 const basegfx::BColor
aHilightColor(aSvtOptionsDrawinglayer
.getHilightColor().getBColor());
2626 const drawinglayer::primitive2d::Primitive2DReference
aGraphicOutline(
2627 new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
2628 aGraphicOutlinePolygon
,
2632 drawinglayer::primitive2d::Primitive2DContainer
aCombination(2);
2633 aCombination
[0] = aGraphic
;
2634 aCombination
[1] = aGraphicOutline
;
2636 // embed to MaskPrimitive2D
2637 const drawinglayer::primitive2d::Primitive2DReference
aMaskedGraphic(
2638 new drawinglayer::primitive2d::MaskPrimitive2D(
2642 // embed to UnifiedTransparencePrimitive2D
2643 const drawinglayer::primitive2d::Primitive2DReference
aTransparenceMaskedGraphic(
2644 new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
2645 drawinglayer::primitive2d::Primitive2DContainer
{ aMaskedGraphic
},
2648 const drawinglayer::primitive2d::Primitive2DContainer aSequence
{ aTransparenceMaskedGraphic
};
2650 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
2652 // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
2653 const SdrPageWindow
& rPageWindow
= *(pPageView
->GetPageWindow(b
));
2655 if(rPageWindow
.GetPaintWindow().OutputToWindow())
2657 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
2660 std::unique_ptr
<sdr::overlay::OverlayObject
> pNew(new sdr::overlay::OverlayPrimitive2DSequenceObject(aSequence
));
2662 // only informative object, no hit
2663 pNew
->setHittable(false);
2666 insertNewlyCreatedOverlayObjectForSdrHdl(
2668 rPageWindow
.GetObjectContact(),
2675 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */