Coverage Report

Created: 2026-10-14 09:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/sfx2/LokControlHandler.hxx
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
10
#pragma once
11
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/XView.hpp>
21
#include <toolkit/helper/vclunohelper.hxx>
22
#include <tools/UnitConversion.hxx>
23
24
#include <optional>
25
26
namespace com::sun::star::awt
27
{
28
class XGraphics;
29
}
30
namespace com::sun::star::awt
31
{
32
class XWindowPeer;
33
}
34
35
class LokControlHandler
36
{
37
public:
38
    static bool postMouseEvent(const SdrPage* pPage, const SdrView* pDrawView,
39
                               vcl::DocWindow& rMainWindow, int nType, Point aPointHmm, int nCount,
40
                               int nButtons, int nModifier)
41
0
    {
42
0
        static std::optional<PointerStyle> eDocPointerStyle;
43
44
0
        o3tl::Length eControlUnitLength = MapToO3tlLength(rMainWindow.GetMapMode().GetMapUnit());
45
0
        SdrObjListIter aIterator(pPage, SdrIterMode::Flat);
46
0
        while (aIterator.IsMore())
47
0
        {
48
0
            SdrObject* pObject = aIterator.Next();
49
0
            SdrUnoObj* pUnoObect = dynamic_cast<SdrUnoObj*>(pObject);
50
0
            if (pUnoObect)
51
0
            {
52
0
                tools::Rectangle aControlRect = pUnoObect->GetLogicRect();
53
0
                tools::Rectangle aControlRectHMM
54
0
                    = o3tl::convert(aControlRect, eControlUnitLength, o3tl::Length::mm100);
55
56
0
                if (aControlRectHMM.Contains(aPointHmm))
57
0
                {
58
0
                    css::uno::Reference<css::awt::XControl> xControl
59
0
                        = pUnoObect->GetUnoControl(*pDrawView, *rMainWindow.GetOutDev());
60
0
                    if (!xControl.is())
61
0
                        return false;
62
63
0
                    css::uno::Reference<css::awt::XWindow> xControlWindow(xControl,
64
0
                                                                          css::uno::UNO_QUERY);
65
0
                    if (!xControlWindow.is())
66
0
                        return false;
67
68
0
                    css::uno::Reference<css::awt::XWindowPeer> xWindowPeer(xControl->getPeer());
69
70
0
                    VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindowPeer);
71
0
                    if (pWindow)
72
0
                    {
73
0
                        tools::Rectangle aControlRectPx
74
0
                            = o3tl::convert(aControlRectHMM, o3tl::Length::mm100, o3tl::Length::px);
75
                        // used by Control::LogicInvalidate
76
0
                        pWindow->SetPosPixel(aControlRectPx.TopLeft());
77
78
                        // when entering into control area save current pointer style
79
                        // and set pointer style to arrow
80
0
                        if (!eDocPointerStyle)
81
0
                        {
82
0
                            eDocPointerStyle = rMainWindow.GetPointer();
83
0
                            rMainWindow.SetPointer(pWindow->GetPointer());
84
0
                        }
85
86
0
                        Point aControlRelativePositionHMM = aPointHmm - aControlRectHMM.TopLeft();
87
0
                        Point aControlRelativePosition = o3tl::convert(
88
0
                            aControlRelativePositionHMM, o3tl::Length::mm100, o3tl::Length::px);
89
90
0
                        LokMouseEventData aMouseEventData(nType, aControlRelativePosition, nCount,
91
0
                                                          MouseEventModifiers::SIMPLECLICK,
92
0
                                                          nButtons, nModifier);
93
0
                        SfxLokHelper::postMouseEventAsync(pWindow, aMouseEventData);
94
0
                        return true;
95
0
                    }
96
0
                }
97
0
            }
98
0
        }
99
100
        // when exiting from control area restore document pointer style
101
0
        if (eDocPointerStyle)
102
0
        {
103
0
            rMainWindow.SetPointer(*eDocPointerStyle);
104
0
            eDocPointerStyle.reset();
105
0
        }
106
0
        return false;
107
0
    }
108
109
    static void drawUnoControl(const SdrView* pDrawView, const SdrUnoObj* pUnoObect,
110
                               vcl::Window const& rMainWindow, VirtualDevice& rDevice,
111
                               tools::Rectangle const& rTileRectHMM, double scaleX, double scaleY)
112
0
    {
113
0
        css::uno::Reference<css::awt::XControl> xControl
114
0
            = pUnoObect->GetUnoControl(*pDrawView, *rMainWindow.GetOutDev());
115
0
        if (!xControl.is())
116
0
            return;
117
118
0
        css::uno::Reference<css::awt::XWindow> xControlWindow(xControl, css::uno::UNO_QUERY);
119
0
        if (!xControlWindow.is())
120
0
            return;
121
122
0
        css::uno::Reference<css::awt::XGraphics> xGraphics(rDevice.CreateUnoGraphics());
123
0
        if (!xGraphics.is())
124
0
            return;
125
126
0
        css::uno::Reference<css::awt::XView> xControlView(xControl, css::uno::UNO_QUERY);
127
0
        if (!xControlView.is())
128
0
            return;
129
130
0
        o3tl::Length eControlUnitLength = MapToO3tlLength(rMainWindow.GetMapMode().GetMapUnit());
131
0
        tools::Rectangle aControlRect = pUnoObect->GetLogicRect();
132
0
        tools::Rectangle aObjectRectHMM
133
0
            = o3tl::convert(aControlRect, eControlUnitLength, o3tl::Length::mm100);
134
0
        tools::Rectangle aControltRectPx
135
0
            = o3tl::convert(aObjectRectHMM, o3tl::Length::mm100, o3tl::Length::px);
136
137
0
        Point aOffsetFromTile(aObjectRectHMM.Left() - rTileRectHMM.Left(),
138
0
                              aObjectRectHMM.Top() - rTileRectHMM.Top());
139
0
        tools::Rectangle aRectangleHMM(aOffsetFromTile, aObjectRectHMM.GetSize());
140
0
        tools::Rectangle aRectanglePx
141
0
            = o3tl::convert(aRectangleHMM, o3tl::Length::mm100, o3tl::Length::px);
142
143
0
        xControlWindow->setPosSize(aControltRectPx.Left(), aControltRectPx.Top(),
144
0
                                   aRectanglePx.GetWidth(), aRectanglePx.GetHeight(),
145
0
                                   css::awt::PosSize::POSSIZE);
146
147
0
        xControlView->setGraphics(xGraphics);
148
        // required for getting text label rendered with the correct scale
149
0
        xControlView->setZoom(1, 1);
150
151
0
        xControlView->draw(aRectanglePx.Left() * scaleX, aRectanglePx.Top() * scaleY);
152
0
    }
153
154
    static void paintControlTile(const SdrPage* pPage, const SdrView* pDrawView,
155
                                 vcl::Window const& rMainWindow, VirtualDevice& rDevice,
156
                                 Size aOutputSize, tools::Rectangle const& rTileRect)
157
0
    {
158
0
        tools::Rectangle aTileRectHMM
159
0
            = o3tl::convert(rTileRect, o3tl::Length::twip, o3tl::Length::mm100);
160
161
        // Resizes the virtual device so to contain the entries context
162
0
        rDevice.SetOutputSizePixel(aOutputSize, /*bErase*/ false);
163
164
0
        auto popIt = rDevice.ScopedPush(vcl::PushFlags::MAPMODE);
165
166
0
        double scaleX(0.0);
167
0
        double scaleY(0.0);
168
0
        if (rTileRect.GetWidth() && rTileRect.GetHeight())
169
0
        {
170
0
            MapMode aDeviceMapMode(rDevice.GetMapMode());
171
0
            const double scale = conversionFract(o3tl::Length::px, o3tl::Length::twip);
172
0
            scaleX = double(aOutputSize.Width()) / rTileRect.GetWidth() * scale;
173
0
            scaleY = double(aOutputSize.Height()) / rTileRect.GetHeight() * scale;
174
0
            aDeviceMapMode.SetScaleX(scaleX);
175
0
            aDeviceMapMode.SetScaleY(scaleY);
176
0
            aDeviceMapMode.SetMapUnit(MapUnit::MapPixel);
177
0
            rDevice.SetMapMode(aDeviceMapMode);
178
0
        }
179
180
0
        o3tl::Length eControlUnitLength = MapToO3tlLength(rMainWindow.GetMapMode().GetMapUnit());
181
0
        SdrObjListIter aIterator(pPage, SdrIterMode::Flat);
182
183
0
        while (aIterator.IsMore())
184
0
        {
185
0
            SdrObject* pObject = aIterator.Next();
186
0
            SdrUnoObj* pUnoObect = dynamic_cast<SdrUnoObj*>(pObject);
187
0
            if (pUnoObect)
188
0
            {
189
0
                tools::Rectangle aControlRect = pUnoObect->GetLogicRect();
190
0
                tools::Rectangle aObjectRectHMM
191
0
                    = o3tl::convert(aControlRect, eControlUnitLength, o3tl::Length::mm100);
192
193
                // Check if we intersect with the tile rectangle and we
194
                // need to draw the control.
195
0
                if (aObjectRectHMM.Overlaps(aTileRectHMM))
196
0
                {
197
0
                    drawUnoControl(pDrawView, pUnoObect, rMainWindow, rDevice, aTileRectHMM, scaleX,
198
0
                                   scaleY);
199
0
                }
200
0
            }
201
0
        }
202
0
    }
203
};
204
205
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */