Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/chart2/source/controller/main/ChartWindow.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
#include <config_wasm_strip.h>
21
#include <ChartWindow.hxx>
22
#include <ChartController.hxx>
23
#include <helpids.h>
24
#include <uiobject.hxx>
25
26
#include <vcl/help.hxx>
27
#include <vcl/settings.hxx>
28
29
#include <sfx2/ipclient.hxx>
30
#include <sfx2/viewsh.hxx>
31
#include <sfx2/lokhelper.hxx>
32
#include <comphelper/lok.hxx>
33
34
using namespace ::com::sun::star;
35
36
namespace
37
{
38
::tools::Rectangle lcl_AWTRectToVCLRect( const css::awt::Rectangle & rAWTRect )
39
0
{
40
0
    ::tools::Rectangle aResult(rAWTRect.X, rAWTRect.Y);
41
0
    aResult.setWidth( rAWTRect.Width );
42
0
    aResult.setHeight( rAWTRect.Height );
43
0
    return aResult;
44
0
}
45
} // anonymous namespace
46
47
namespace chart
48
{
49
50
ChartWindow::ChartWindow( ChartController* pController, vcl::Window* pParent, WinBits nStyle )
51
0
        : Window(pParent, nStyle)
52
0
        , m_pWindowController( pController )
53
0
        , m_bInPaint(false)
54
0
        , m_pViewShellWindow( nullptr )
55
0
{
56
0
    set_id(u"chart_window"_ustr);
57
0
    SetHelpId( HID_SCH_WIN_DOCUMENT );
58
0
    SetMapMode( MapMode(MapUnit::Map100thMM) );
59
0
    adjustHighContrastMode();
60
    // chart does not depend on exact pixel painting => enable antialiased drawing
61
0
    GetOutDev()->SetAntialiasing( AntialiasingFlags::Enable | GetOutDev()->GetAntialiasing() );
62
0
    EnableRTL( false );
63
0
    if( pParent )
64
0
        pParent->EnableRTL( false );// #i96215# necessary for a correct position of the context menu in rtl mode
65
0
}
Unexecuted instantiation: chart::ChartWindow::ChartWindow(chart::ChartController*, vcl::Window*, long)
Unexecuted instantiation: chart::ChartWindow::ChartWindow(chart::ChartController*, vcl::Window*, long)
66
67
ChartWindow::~ChartWindow()
68
0
{
69
0
    disposeOnce();
70
0
}
71
72
void ChartWindow::dispose()
73
0
{
74
0
    m_pWindowController = nullptr;
75
0
    m_pViewShellWindow.reset();
76
0
    vcl::Window::dispose();
77
0
}
78
79
void ChartWindow::PrePaint(vcl::RenderContext& )
80
0
{
81
    // forward VCLs PrePaint window event to DrawingLayer
82
0
    if (m_pWindowController)
83
0
    {
84
0
       m_pWindowController->PrePaint();
85
0
    }
86
0
}
87
88
void ChartWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
89
0
{
90
0
    if (comphelper::LibreOfficeKit::isActive() && !rRenderContext.IsVirtual())
91
0
        return;
92
93
0
    m_bInPaint = true;
94
0
    if (m_pWindowController)
95
0
    {
96
0
        m_pWindowController->execute_Paint(rRenderContext, rRect);
97
0
    }
98
0
    else
99
0
    {
100
0
        Window::Paint(rRenderContext, rRect);
101
0
    }
102
0
    m_bInPaint = false;
103
0
}
104
105
void ChartWindow::MouseButtonDown(const MouseEvent& rMEvt)
106
0
{
107
0
    if( m_pWindowController )
108
0
        m_pWindowController->execute_MouseButtonDown(rMEvt);
109
0
    else
110
0
        Window::MouseButtonDown(rMEvt);
111
0
}
112
113
void ChartWindow::MouseMove( const MouseEvent& rMEvt )
114
0
{
115
0
    if( m_pWindowController )
116
0
        m_pWindowController->execute_MouseMove( rMEvt );
117
0
    else
118
0
        Window::MouseMove( rMEvt );
119
0
}
120
121
void ChartWindow::Tracking( const TrackingEvent& rTEvt )
122
0
{
123
0
    if( !m_pWindowController )
124
0
        Window::Tracking( rTEvt );
125
0
}
126
127
void ChartWindow::MouseButtonUp( const MouseEvent& rMEvt )
128
0
{
129
0
    if( m_pWindowController )
130
0
        m_pWindowController->execute_MouseButtonUp( rMEvt );
131
0
    else
132
0
        Window::MouseButtonUp( rMEvt );
133
0
}
134
135
void ChartWindow::Resize()
136
0
{
137
0
    if( m_pWindowController )
138
0
        m_pWindowController->execute_Resize();
139
0
    else
140
0
        Window::Resize();
141
0
}
142
143
void ChartWindow::Activate()
144
0
{
145
0
    if( !m_pWindowController )
146
0
        Window::Activate();
147
0
}
148
void ChartWindow::Deactivate()
149
0
{
150
0
    if( !m_pWindowController )
151
0
        Window::Deactivate();
152
0
}
153
void ChartWindow::GetFocus()
154
0
{
155
0
    if( !m_pWindowController )
156
0
        Window::GetFocus();
157
0
}
158
void ChartWindow::LoseFocus()
159
0
{
160
0
    if( !m_pWindowController )
161
0
        Window::LoseFocus();
162
0
}
163
164
void ChartWindow::Command( const CommandEvent& rCEvt )
165
0
{
166
0
    if( m_pWindowController )
167
0
        m_pWindowController->execute_Command( rCEvt );
168
0
    else
169
0
        Window::Command( rCEvt );
170
0
}
171
172
void ChartWindow::KeyInput( const KeyEvent& rKEvt )
173
0
{
174
0
    if( m_pWindowController )
175
0
    {
176
0
        if( !m_pWindowController->execute_KeyInput(rKEvt) )
177
0
            Window::KeyInput(rKEvt);
178
0
    }
179
0
    else
180
0
        Window::KeyInput( rKEvt );
181
0
}
182
183
rtl::Reference<comphelper::OAccessible> ChartWindow::CreateAccessible()
184
0
{
185
0
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
186
0
    if( m_pWindowController )
187
0
        return m_pWindowController->CreateAccessible();
188
0
    else
189
0
        return Window::CreateAccessible();
190
#else
191
    return {};
192
#endif
193
0
}
194
195
void ChartWindow::DataChanged( const DataChangedEvent& rDCEvt )
196
0
{
197
0
    vcl::Window::DataChanged( rDCEvt );
198
199
0
    if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
200
0
         (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
201
0
    {
202
0
        adjustHighContrastMode();
203
0
    }
204
0
}
205
206
void ChartWindow::RequestHelp( const HelpEvent& rHEvt )
207
0
{
208
0
    bool bHelpHandled = false;
209
0
    if( ( rHEvt.GetMode() & HelpEventMode::QUICK ) &&
210
0
        m_pWindowController )
211
0
    {
212
0
        Point aLogicHitPos = PixelToLogic( GetPointerPosPixel());
213
0
        OUString aQuickHelpText;
214
0
        awt::Rectangle aHelpRect;
215
0
        bool bIsBalloonHelp( Help::IsBalloonHelpEnabled() );
216
0
        bHelpHandled = m_pWindowController->requestQuickHelp( aLogicHitPos, bIsBalloonHelp, aQuickHelpText, aHelpRect );
217
218
0
        if( bHelpHandled )
219
0
        {
220
0
            tools::Rectangle aPixelRect(LogicToPixel(lcl_AWTRectToVCLRect(aHelpRect)));
221
0
            tools::Rectangle aScreenRect(OutputToScreenPixel(aPixelRect.TopLeft()),
222
0
                                         OutputToScreenPixel(aPixelRect.BottomRight()));
223
224
0
            if( bIsBalloonHelp )
225
0
                Help::ShowBalloon(this, rHEvt.GetMousePosPixel(), aScreenRect, aQuickHelpText);
226
0
            else
227
0
                Help::ShowQuickHelp(this, aScreenRect, aQuickHelpText);
228
0
        }
229
0
    }
230
231
0
    if( !bHelpHandled )
232
0
        vcl::Window::RequestHelp( rHEvt );
233
0
}
234
235
void ChartWindow::adjustHighContrastMode()
236
0
{
237
0
    static const DrawModeFlags nContrastMode =
238
0
        DrawModeFlags::SettingsLine | DrawModeFlags::SettingsFill |
239
0
        DrawModeFlags::SettingsText | DrawModeFlags::SettingsGradient;
240
241
0
    bool bUseContrast = GetSettings().GetStyleSettings().GetHighContrastMode();
242
0
    GetOutDev()->SetDrawMode( bUseContrast ? nContrastMode : DrawModeFlags::Default );
243
0
}
244
245
void ChartWindow::ForceInvalidate()
246
0
{
247
0
    vcl::Window::Invalidate();
248
0
}
249
void ChartWindow::ImplInvalidate( const vcl::Region* rRegion, InvalidateFlags nFlags )
250
0
{
251
0
    if( m_bInPaint ) // #i101928# superfluous paint calls while entering and editing charts"
252
0
        return;
253
0
    vcl::Window::ImplInvalidate( rRegion, nFlags );
254
0
}
255
256
void ChartWindow::LogicInvalidate(const tools::Rectangle* pRectangle)
257
0
{
258
0
    SfxViewShell* pCurrentShell = SfxViewShell::Current();
259
0
    if ( nullptr == pCurrentShell )
260
0
        return;
261
0
    tools::Rectangle aResultRectangle;
262
0
    if (!pRectangle)
263
0
    {
264
        // we have to invalidate the whole chart area not the whole document
265
0
        aResultRectangle = GetBoundingBox();
266
0
    }
267
0
    else
268
0
    {
269
0
        tools::Rectangle aRectangle(*pRectangle);
270
        // When dragging shapes the map mode is disabled.
271
0
        if (IsMapModeEnabled())
272
0
        {
273
0
            if (GetMapMode().GetMapUnit() == MapUnit::Map100thMM)
274
0
            {
275
0
                aRectangle = o3tl::convert(aRectangle, o3tl::Length::mm100, o3tl::Length::twip);
276
0
            }
277
0
        }
278
0
        else
279
0
        {
280
0
            aRectangle = PixelToLogic(aRectangle, MapMode(MapUnit::MapTwip));
281
0
        }
282
283
0
        vcl::Window* pEditWin = GetParentEditWin();
284
0
        if (pEditWin)
285
0
        {
286
0
            MapMode aCWMapMode = GetMapMode();
287
0
            constexpr auto p = o3tl::getConversionMulDiv(o3tl::Length::px, o3tl::Length::twip);
288
0
            const auto& scaleX = aCWMapMode.GetScaleX();
289
0
            const auto& scaleY = aCWMapMode.GetScaleY();
290
0
            const auto nXNum = p.first * scaleX.GetDenominator();
291
0
            const auto nXDen = p.second * scaleX.GetNumerator();
292
0
            const auto nYNum = p.first * scaleY.GetDenominator();
293
0
            const auto nYDen = p.second * scaleY.GetNumerator();
294
295
0
            if (!IsMapModeEnabled())
296
0
            {
297
0
                aRectangle = aRectangle.scale(scaleX.GetDenominator(), scaleX.GetNumerator(),
298
0
                                              scaleY.GetDenominator(), scaleY.GetNumerator());
299
0
            }
300
301
0
            Point aOffset = this->GetOffsetPixelFrom(*pEditWin).scale(nXNum, nXDen, nYNum, nYDen);
302
303
0
            aRectangle = tools::Rectangle(aRectangle.TopLeft() + aOffset, aRectangle.GetSize());
304
0
        }
305
306
0
        aResultRectangle = aRectangle;
307
0
    }
308
0
    SfxLokHelper::notifyInvalidation(pCurrentShell, &aResultRectangle);
309
0
}
310
311
FactoryFunction ChartWindow::GetUITestFactory() const
312
0
{
313
0
    return ChartWindowUIObject::create;
314
0
}
315
316
ChartController* ChartWindow::GetController()
317
0
{
318
0
    return m_pWindowController;
319
0
}
320
321
vcl::Window* ChartWindow::GetParentEditWin()
322
0
{
323
0
    if (m_pViewShellWindow)
324
0
        return m_pViewShellWindow.get();
325
326
    // So, you are thinking, why do not invoke pCurrentShell->GetWindow() ?
327
    // Because in Impress the parent edit win is not view shell window.
328
0
    SfxViewShell* pCurrentShell = SfxViewShell::Current();
329
0
    if( pCurrentShell )
330
0
    {
331
0
        SfxInPlaceClient* pIPClient = pCurrentShell->GetIPClient();
332
0
        if (pIPClient)
333
0
        {
334
0
            vcl::Window* pRootWin = pIPClient->GetEditWin();
335
0
            if(pRootWin && pRootWin->IsAncestorOf(*this))
336
0
            {
337
0
                m_pViewShellWindow = pRootWin;
338
0
                return m_pViewShellWindow.get();
339
0
            }
340
0
        }
341
0
    }
342
0
    return nullptr;
343
0
}
344
345
tools::Rectangle ChartWindow::GetBoundingBox()
346
0
{
347
0
    tools::Rectangle aBBox;
348
349
0
    vcl::Window* pRootWin = GetParentEditWin();
350
0
    if (pRootWin)
351
0
    {
352
        // In all cases, the following code fragment
353
        // returns the chart bounding box in twips.
354
0
        MapMode aCWMapMode = GetMapMode();
355
0
        constexpr auto p = o3tl::getConversionMulDiv(o3tl::Length::px, o3tl::Length::twip);
356
0
        const auto& scaleX = aCWMapMode.GetScaleX();
357
0
        const auto& scaleY = aCWMapMode.GetScaleY();
358
0
        const auto nXNum = p.first * scaleX.GetDenominator();
359
0
        const auto nXDen = p.second * scaleX.GetNumerator();
360
0
        const auto nYNum = p.first * scaleY.GetDenominator();
361
0
        const auto nYDen = p.second * scaleY.GetNumerator();
362
363
0
        Point aOffset = GetOffsetPixelFrom(*pRootWin);
364
0
        aOffset.setX( o3tl::convert(aOffset.X(), nXNum, nXDen) );
365
0
        aOffset.setY( o3tl::convert(aOffset.Y(), nYNum, nYDen) );
366
0
        Size aSize = GetSizePixel();
367
0
        aSize.setWidth( o3tl::convert(aSize.Width(), nXNum, nXDen) );
368
0
        aSize.setHeight( o3tl::convert(aSize.Height(), nYNum, nYDen) );
369
0
        aBBox = tools::Rectangle(aOffset, aSize);
370
0
    }
371
0
    return aBBox;
372
0
}
373
374
} //namespace chart
375
376
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */