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 <sfx2/lokhelper.hxx>
13 #include <svx/svdouno.hxx>
14 #include <svx/svditer.hxx>
15 #include <vcl/virdev.hxx>
16 #include <vcl/DocWindow.hxx>
17 #include <com/sun/star/awt/PosSize.hpp>
18 #include <com/sun/star/awt/XControl.hpp>
19 #include <com/sun/star/awt/XWindow.hpp>
20 #include <com/sun/star/awt/XWindowPeer.hpp>
21 #include <com/sun/star/awt/XGraphics.hpp>
22 #include <com/sun/star/awt/XView.hpp>
23 #include <toolkit/helper/vclunohelper.hxx>
24 #include <tools/UnitConversion.hxx>
28 class LokControlHandler
31 static bool postMouseEvent(const SdrPage
* pPage
, const SdrView
* pDrawView
,
32 vcl::DocWindow
& rMainWindow
, int nType
, Point aPointHmm
, int nCount
,
33 int nButtons
, int nModifier
)
35 static std::optional
<PointerStyle
> eDocPointerStyle
;
37 o3tl::Length eControlUnitLength
= MapToO3tlLength(rMainWindow
.GetMapMode().GetMapUnit());
38 SdrObjListIter
aIterator(pPage
, SdrIterMode::Flat
);
39 while (aIterator
.IsMore())
41 SdrObject
* pObject
= aIterator
.Next();
42 SdrUnoObj
* pUnoObect
= dynamic_cast<SdrUnoObj
*>(pObject
);
45 tools::Rectangle aControlRect
= pUnoObect
->GetLogicRect();
46 tools::Rectangle aControlRectHMM
47 = o3tl::convert(aControlRect
, eControlUnitLength
, o3tl::Length::mm100
);
49 if (aControlRectHMM
.Contains(aPointHmm
))
51 css::uno::Reference
<css::awt::XControl
> xControl
52 = pUnoObect
->GetUnoControl(*pDrawView
, *rMainWindow
.GetOutDev());
56 css::uno::Reference
<css::awt::XWindow
> xControlWindow(xControl
,
58 if (!xControlWindow
.is())
61 css::uno::Reference
<css::awt::XWindowPeer
> xWindowPeer(xControl
->getPeer());
63 VclPtr
<vcl::Window
> pWindow
= VCLUnoHelper::GetWindow(xWindowPeer
);
66 tools::Rectangle aControlRectPx
67 = o3tl::convert(aControlRectHMM
, o3tl::Length::mm100
, o3tl::Length::px
);
68 // used by Control::LogicInvalidate
69 pWindow
->SetPosPixel(aControlRectPx
.TopLeft());
71 // when entering into control area save current pointer style
72 // and set pointer style to arrow
73 if (!eDocPointerStyle
)
75 eDocPointerStyle
= rMainWindow
.GetPointer();
76 rMainWindow
.SetPointer(pWindow
->GetPointer());
79 Point aControlRelativePositionHMM
= aPointHmm
- aControlRectHMM
.TopLeft();
80 Point aControlRelativePosition
= o3tl::convert(
81 aControlRelativePositionHMM
, o3tl::Length::mm100
, o3tl::Length::px
);
83 LokMouseEventData
aMouseEventData(nType
, aControlRelativePosition
, nCount
,
84 MouseEventModifiers::SIMPLECLICK
,
86 SfxLokHelper::postMouseEventAsync(pWindow
, aMouseEventData
);
93 // when exiting from control area restore document pointer style
96 rMainWindow
.SetPointer(*eDocPointerStyle
);
97 eDocPointerStyle
.reset();
102 static void drawUnoControl(const SdrView
* pDrawView
, const SdrUnoObj
* pUnoObect
,
103 vcl::Window
const& rMainWindow
, VirtualDevice
& rDevice
,
104 tools::Rectangle
const& rTileRectHMM
, double scaleX
, double scaleY
)
106 css::uno::Reference
<css::awt::XControl
> xControl
107 = pUnoObect
->GetUnoControl(*pDrawView
, *rMainWindow
.GetOutDev());
111 css::uno::Reference
<css::awt::XWindow
> xControlWindow(xControl
, css::uno::UNO_QUERY
);
112 if (!xControlWindow
.is())
115 css::uno::Reference
<css::awt::XGraphics
> xGraphics(rDevice
.CreateUnoGraphics());
119 css::uno::Reference
<css::awt::XView
> xControlView(xControl
, css::uno::UNO_QUERY
);
120 if (!xControlView
.is())
123 o3tl::Length eControlUnitLength
= MapToO3tlLength(rMainWindow
.GetMapMode().GetMapUnit());
124 tools::Rectangle aControlRect
= pUnoObect
->GetLogicRect();
125 tools::Rectangle aObjectRectHMM
126 = o3tl::convert(aControlRect
, eControlUnitLength
, o3tl::Length::mm100
);
127 tools::Rectangle aControltRectPx
128 = o3tl::convert(aObjectRectHMM
, o3tl::Length::mm100
, o3tl::Length::px
);
130 Point
aOffsetFromTile(aObjectRectHMM
.Left() - rTileRectHMM
.Left(),
131 aObjectRectHMM
.Top() - rTileRectHMM
.Top());
132 tools::Rectangle
aRectangleHMM(aOffsetFromTile
, aObjectRectHMM
.GetSize());
133 tools::Rectangle aRectanglePx
134 = o3tl::convert(aRectangleHMM
, o3tl::Length::mm100
, o3tl::Length::px
);
136 xControlWindow
->setPosSize(aControltRectPx
.Left(), aControltRectPx
.Top(),
137 aRectanglePx
.GetWidth(), aRectanglePx
.GetHeight(),
138 css::awt::PosSize::POSSIZE
);
140 xControlView
->setGraphics(xGraphics
);
141 // required for getting text label rendered with the correct scale
142 xControlView
->setZoom(1, 1);
144 xControlView
->draw(aRectanglePx
.Left() * scaleX
, aRectanglePx
.Top() * scaleY
);
147 static void paintControlTile(const SdrPage
* pPage
, const SdrView
* pDrawView
,
148 vcl::Window
const& rMainWindow
, VirtualDevice
& rDevice
,
149 Size aOutputSize
, tools::Rectangle
const& rTileRect
)
151 tools::Rectangle aTileRectHMM
152 = o3tl::convert(rTileRect
, o3tl::Length::twip
, o3tl::Length::mm100
);
154 // Resizes the virtual device so to contain the entries context
155 rDevice
.SetOutputSizePixel(aOutputSize
);
157 rDevice
.Push(vcl::PushFlags::MAPMODE
);
158 MapMode
aDeviceMapMode(rDevice
.GetMapMode());
160 const Fraction scale
= conversionFract(o3tl::Length::px
, o3tl::Length::twip
);
161 Fraction scaleX
= Fraction(aOutputSize
.Width(), rTileRect
.GetWidth()) * scale
;
162 Fraction scaleY
= Fraction(aOutputSize
.Height(), rTileRect
.GetHeight()) * scale
;
163 aDeviceMapMode
.SetScaleX(scaleX
);
164 aDeviceMapMode
.SetScaleY(scaleY
);
165 aDeviceMapMode
.SetMapUnit(MapUnit::MapPixel
);
166 rDevice
.SetMapMode(aDeviceMapMode
);
168 o3tl::Length eControlUnitLength
= MapToO3tlLength(rMainWindow
.GetMapMode().GetMapUnit());
169 SdrObjListIter
aIterator(pPage
, SdrIterMode::Flat
);
171 while (aIterator
.IsMore())
173 SdrObject
* pObject
= aIterator
.Next();
174 SdrUnoObj
* pUnoObect
= dynamic_cast<SdrUnoObj
*>(pObject
);
177 tools::Rectangle aControlRect
= pUnoObect
->GetLogicRect();
178 tools::Rectangle aObjectRectHMM
179 = o3tl::convert(aControlRect
, eControlUnitLength
, o3tl::Length::mm100
);
181 // Check if we intersect with the tile rectangle and we
182 // need to draw the control.
183 if (aObjectRectHMM
.Overlaps(aTileRectHMM
))
185 drawUnoControl(pDrawView
, pUnoObect
, rMainWindow
, rDevice
, aTileRectHMM
,
186 double(scaleX
), double(scaleY
));
195 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */