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/.
12 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
13 #include <sfx2/dllapi.h>
14 #include <sfx2/lokhelper.hxx>
15 #include <svx/svdouno.hxx>
16 #include <svx/svditer.hxx>
17 #include <vcl/virdev.hxx>
18 #include <vcl/DocWindow.hxx>
19 #include <com/sun/star/awt/PosSize.hpp>
20 #include <com/sun/star/awt/XControl.hpp>
21 #include <com/sun/star/awt/XWindow.hpp>
22 #include <com/sun/star/awt/XWindowPeer.hpp>
23 #include <com/sun/star/awt/XGraphics.hpp>
24 #include <com/sun/star/awt/XView.hpp>
25 #include <toolkit/helper/vclunohelper.hxx>
26 #include <tools/UnitConversion.hxx>
28 #include <sal/log.hxx>
32 class LokControlHandler
35 static bool postMouseEvent(const SdrPage
* pPage
, const SdrView
* pDrawView
,
36 vcl::DocWindow
& rMainWindow
, int nType
, Point aPointHmm
, int nCount
,
37 int nButtons
, int nModifier
)
39 static std::optional
<PointerStyle
> eDocPointerStyle
;
41 o3tl::Length eControlUnitLength
= MapToO3tlLength(rMainWindow
.GetMapMode().GetMapUnit());
42 SdrObjListIter
aIterator(pPage
, SdrIterMode::Flat
);
43 while (aIterator
.IsMore())
45 SdrObject
* pObject
= aIterator
.Next();
46 SdrUnoObj
* pUnoObect
= dynamic_cast<SdrUnoObj
*>(pObject
);
49 tools::Rectangle aControlRect
= pUnoObect
->GetLogicRect();
50 tools::Rectangle aControlRectHMM
51 = o3tl::convert(aControlRect
, eControlUnitLength
, o3tl::Length::mm100
);
53 if (aControlRectHMM
.Contains(aPointHmm
))
55 css::uno::Reference
<css::awt::XControl
> xControl
56 = pUnoObect
->GetUnoControl(*pDrawView
, *rMainWindow
.GetOutDev());
60 css::uno::Reference
<css::awt::XWindow
> xControlWindow(xControl
,
62 if (!xControlWindow
.is())
65 css::uno::Reference
<css::awt::XWindowPeer
> xWindowPeer(xControl
->getPeer());
67 VclPtr
<vcl::Window
> pWindow
= VCLUnoHelper::GetWindow(xWindowPeer
);
70 tools::Rectangle aControlRectPx
71 = o3tl::convert(aControlRectHMM
, o3tl::Length::mm100
, o3tl::Length::px
);
72 // used by Control::LogicInvalidate
73 pWindow
->SetPosPixel(aControlRectPx
.TopLeft());
75 // when entering into control area save current pointer style
76 // and set pointer style to arrow
77 if (!eDocPointerStyle
)
79 eDocPointerStyle
= rMainWindow
.GetPointer();
80 rMainWindow
.SetPointer(pWindow
->GetPointer());
83 Point aControlRelativePositionHMM
= aPointHmm
- aControlRectHMM
.TopLeft();
84 Point aControlRelativePosition
= o3tl::convert(
85 aControlRelativePositionHMM
, o3tl::Length::mm100
, o3tl::Length::px
);
87 LokMouseEventData
aMouseEventData(nType
, aControlRelativePosition
, nCount
,
88 MouseEventModifiers::SIMPLECLICK
,
90 SfxLokHelper::postMouseEventAsync(pWindow
, aMouseEventData
);
97 // when exiting from control area restore document pointer style
100 rMainWindow
.SetPointer(*eDocPointerStyle
);
101 eDocPointerStyle
.reset();
106 static void drawUnoControl(const SdrView
* pDrawView
, const SdrUnoObj
* pUnoObect
,
107 vcl::Window
const& rMainWindow
, VirtualDevice
& rDevice
,
108 tools::Rectangle
const& rTileRectHMM
, double scaleX
, double scaleY
)
110 css::uno::Reference
<css::awt::XControl
> xControl
111 = pUnoObect
->GetUnoControl(*pDrawView
, *rMainWindow
.GetOutDev());
115 css::uno::Reference
<css::awt::XWindow
> xControlWindow(xControl
, css::uno::UNO_QUERY
);
116 if (!xControlWindow
.is())
119 css::uno::Reference
<css::awt::XGraphics
> xGraphics(rDevice
.CreateUnoGraphics());
123 css::uno::Reference
<css::awt::XView
> xControlView(xControl
, css::uno::UNO_QUERY
);
124 if (!xControlView
.is())
127 o3tl::Length eControlUnitLength
= MapToO3tlLength(rMainWindow
.GetMapMode().GetMapUnit());
128 tools::Rectangle aControlRect
= pUnoObect
->GetLogicRect();
129 tools::Rectangle aObjectRectHMM
130 = o3tl::convert(aControlRect
, eControlUnitLength
, o3tl::Length::mm100
);
131 tools::Rectangle aControltRectPx
132 = o3tl::convert(aObjectRectHMM
, o3tl::Length::mm100
, o3tl::Length::px
);
134 Point
aOffsetFromTile(aObjectRectHMM
.Left() - rTileRectHMM
.Left(),
135 aObjectRectHMM
.Top() - rTileRectHMM
.Top());
136 tools::Rectangle
aRectangleHMM(aOffsetFromTile
, aObjectRectHMM
.GetSize());
137 tools::Rectangle aRectanglePx
138 = o3tl::convert(aRectangleHMM
, o3tl::Length::mm100
, o3tl::Length::px
);
140 xControlWindow
->setPosSize(aControltRectPx
.Left(), aControltRectPx
.Top(),
141 aRectanglePx
.GetWidth(), aRectanglePx
.GetHeight(),
142 css::awt::PosSize::POSSIZE
);
144 xControlView
->setGraphics(xGraphics
);
145 // required for getting text label rendered with the correct scale
146 xControlView
->setZoom(1, 1);
148 xControlView
->draw(aRectanglePx
.Left() * scaleX
, aRectanglePx
.Top() * scaleY
);
151 static void paintControlTile(const SdrPage
* pPage
, const SdrView
* pDrawView
,
152 vcl::Window
const& rMainWindow
, VirtualDevice
& rDevice
,
153 Size aOutputSize
, tools::Rectangle
const& rTileRect
)
155 tools::Rectangle aTileRectHMM
156 = o3tl::convert(rTileRect
, o3tl::Length::twip
, o3tl::Length::mm100
);
158 // Resizes the virtual device so to contain the entries context
159 rDevice
.SetOutputSizePixel(aOutputSize
);
161 rDevice
.Push(vcl::PushFlags::MAPMODE
);
162 MapMode
aDeviceMapMode(rDevice
.GetMapMode());
164 const Fraction scale
= conversionFract(o3tl::Length::px
, o3tl::Length::twip
);
165 Fraction scaleX
= Fraction(aOutputSize
.Width(), rTileRect
.GetWidth()) * scale
;
166 Fraction scaleY
= Fraction(aOutputSize
.Height(), rTileRect
.GetHeight()) * scale
;
167 aDeviceMapMode
.SetScaleX(scaleX
);
168 aDeviceMapMode
.SetScaleY(scaleY
);
169 aDeviceMapMode
.SetMapUnit(MapUnit::MapPixel
);
170 rDevice
.SetMapMode(aDeviceMapMode
);
172 o3tl::Length eControlUnitLength
= MapToO3tlLength(rMainWindow
.GetMapMode().GetMapUnit());
173 SdrObjListIter
aIterator(pPage
, SdrIterMode::Flat
);
175 while (aIterator
.IsMore())
177 SdrObject
* pObject
= aIterator
.Next();
178 SdrUnoObj
* pUnoObect
= dynamic_cast<SdrUnoObj
*>(pObject
);
181 tools::Rectangle aControlRect
= pUnoObect
->GetLogicRect();
182 tools::Rectangle aObjectRectHMM
183 = o3tl::convert(aControlRect
, eControlUnitLength
, o3tl::Length::mm100
);
185 // Check if we intersect with the tile rectangle and we
186 // need to draw the control.
187 if (aObjectRectHMM
.Overlaps(aTileRectHMM
))
189 drawUnoControl(pDrawView
, pUnoObect
, rMainWindow
, rDevice
, aTileRectHMM
,
190 double(scaleX
), double(scaleY
));
199 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */