Coverage Report

Created: 2026-09-28 10:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/treelist/SvLBoxButton.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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 <SvLBoxButton.hxx>
21
22
#include <vcl/decoview.hxx>
23
#include <vcl/salnativewidgets.hxx>
24
#include <vcl/toolkit/button.hxx>
25
26
SvLBoxButtonData::SvLBoxButtonData(const Control& rControlForSettings, bool _bRadioBtn)
27
0
    : m_pEntry(nullptr)
28
0
    , m_pBox(nullptr)
29
0
    , m_bShowRadioButton(false)
30
0
{
31
0
    m_bShowRadioButton = _bRadioBtn;
32
33
0
    SetDefaultImages(rControlForSettings);
34
0
}
35
36
0
SvLBoxButtonData::~SvLBoxButtonData() {}
37
38
void SvLBoxButtonData::CallLink(SvTreeListEntry* pActEntry, SvLBoxButton* pActBox)
39
0
{
40
0
    m_pEntry = pActEntry;
41
0
    m_pBox = pActBox;
42
0
    m_aLink.Call(this);
43
0
}
44
45
SvBmp SvLBoxButtonData::GetIndex(SvItemStateFlags nItemState)
46
0
{
47
0
    SvBmp nIdx;
48
0
    if (nItemState == SvItemStateFlags::UNCHECKED)
49
0
        nIdx = SvBmp::UNCHECKED;
50
0
    else if (nItemState == SvItemStateFlags::CHECKED)
51
0
        nIdx = SvBmp::CHECKED;
52
0
    else if (nItemState == SvItemStateFlags::TRISTATE)
53
0
        nIdx = SvBmp::TRISTATE;
54
0
    else if (nItemState == (SvItemStateFlags::UNCHECKED | SvItemStateFlags::HIGHLIGHTED))
55
0
        nIdx = SvBmp::HIUNCHECKED;
56
0
    else if (nItemState == (SvItemStateFlags::CHECKED | SvItemStateFlags::HIGHLIGHTED))
57
0
        nIdx = SvBmp::HICHECKED;
58
0
    else if (nItemState == (SvItemStateFlags::TRISTATE | SvItemStateFlags::HIGHLIGHTED))
59
0
        nIdx = SvBmp::HITRISTATE;
60
0
    else
61
0
        nIdx = SvBmp::UNCHECKED;
62
0
    return nIdx;
63
0
}
64
65
0
const Size& SvLBoxButtonData::GetSize() { return m_aSize; }
66
67
SvButtonState SvLBoxButtonData::ConvertToButtonState(SvItemStateFlags nItemFlags)
68
0
{
69
0
    nItemFlags
70
0
        &= SvItemStateFlags::UNCHECKED | SvItemStateFlags::CHECKED | SvItemStateFlags::TRISTATE;
71
0
    switch (nItemFlags)
72
0
    {
73
0
        case SvItemStateFlags::UNCHECKED:
74
0
            return SvButtonState::Unchecked;
75
0
        case SvItemStateFlags::CHECKED:
76
0
            return SvButtonState::Checked;
77
0
        case SvItemStateFlags::TRISTATE:
78
0
            return SvButtonState::Tristate;
79
0
        default:
80
0
            return SvButtonState::Unchecked;
81
0
    }
82
0
}
83
84
0
SvTreeListEntry* SvLBoxButtonData::GetActEntry() const { return m_pEntry; }
85
86
0
SvLBoxButton* SvLBoxButtonData::GetActBox() const { return m_pBox; }
87
88
void SvLBoxButtonData::SetDefaultImages(const Control& rCtrl)
89
0
{
90
0
    const AllSettings& rSettings = rCtrl.GetSettings();
91
92
0
    if (m_bShowRadioButton)
93
0
    {
94
0
        m_aBmps[SvBmp::UNCHECKED] = RadioButton::GetRadioImage(rSettings, DrawButtonFlags::Default);
95
0
        m_aBmps[SvBmp::CHECKED] = RadioButton::GetRadioImage(rSettings, DrawButtonFlags::Checked);
96
0
        m_aBmps[SvBmp::HICHECKED] = RadioButton::GetRadioImage(
97
0
            rSettings, DrawButtonFlags::Checked | DrawButtonFlags::Pressed);
98
0
        m_aBmps[SvBmp::HIUNCHECKED] = RadioButton::GetRadioImage(
99
0
            rSettings, DrawButtonFlags::Default | DrawButtonFlags::Pressed);
100
0
        m_aBmps[SvBmp::TRISTATE] = RadioButton::GetRadioImage(rSettings, DrawButtonFlags::DontKnow);
101
0
        m_aBmps[SvBmp::HITRISTATE] = RadioButton::GetRadioImage(
102
0
            rSettings, DrawButtonFlags::DontKnow | DrawButtonFlags::Pressed);
103
0
    }
104
0
    else
105
0
    {
106
0
        m_aBmps[SvBmp::UNCHECKED] = CheckBox::GetCheckImage(rSettings, DrawButtonFlags::Default);
107
0
        m_aBmps[SvBmp::CHECKED] = CheckBox::GetCheckImage(rSettings, DrawButtonFlags::Checked);
108
0
        m_aBmps[SvBmp::HICHECKED] = CheckBox::GetCheckImage(
109
0
            rSettings, DrawButtonFlags::Checked | DrawButtonFlags::Pressed);
110
0
        m_aBmps[SvBmp::HIUNCHECKED] = CheckBox::GetCheckImage(
111
0
            rSettings, DrawButtonFlags::Default | DrawButtonFlags::Pressed);
112
0
        m_aBmps[SvBmp::TRISTATE] = CheckBox::GetCheckImage(rSettings, DrawButtonFlags::DontKnow);
113
0
        m_aBmps[SvBmp::HITRISTATE] = CheckBox::GetCheckImage(
114
0
            rSettings, DrawButtonFlags::DontKnow | DrawButtonFlags::Pressed);
115
0
    }
116
117
0
    m_aSize = m_aBmps.at(SvBmp::UNCHECKED).GetSizePixel();
118
0
}
119
120
0
bool SvLBoxButtonData::IsRadio() const { return m_bShowRadioButton; }
121
122
SvLBoxButton::SvLBoxButton(SvLBoxButtonData& rBData, bool bIsVis)
123
0
    : m_bIsVis(bIsVis)
124
0
    , m_rData(rBData)
125
0
    , m_nItemFlags(SvItemStateFlags::NONE)
126
0
{
127
0
    SetStateUnchecked();
128
0
}
129
130
0
SvLBoxButton::~SvLBoxButton() {}
131
132
0
SvLBoxItemType SvLBoxButton::GetType() const { return SvLBoxItemType::Button; }
133
134
void SvLBoxButton::ClickHdl(SvTreeListEntry* pEntry)
135
0
{
136
0
    if (IsStateChecked())
137
0
        SetStateUnchecked();
138
0
    else
139
0
        SetStateChecked();
140
141
0
    m_rData.CallLink(pEntry, this);
142
0
}
143
144
void SvLBoxButton::Paint(const Point& rPos, SvTreeListBox& rDev, vcl::RenderContext& rRenderContext,
145
                         const SvViewDataEntry* /*pView*/, const SvTreeListEntry& /*rEntry*/)
146
0
{
147
0
    SvBmp nIndex = SvLBoxButtonData::GetIndex(m_nItemFlags);
148
0
    DrawImageFlags nStyle
149
0
        = (rDev.IsEnabled() && !mbDisabled) ? DrawImageFlags::NONE : DrawImageFlags::Disable;
150
151
    //Native drawing
152
0
    bool bNativeOK = false;
153
0
    ControlType eCtrlType = (m_rData.IsRadio()) ? ControlType::Radiobutton : ControlType::Checkbox;
154
0
    if (rRenderContext.IsNativeControlSupported(eCtrlType, ControlPart::Entire))
155
0
    {
156
0
        Size aSize = m_rData.GetSize();
157
0
        ImplAdjustBoxSize(aSize, eCtrlType, rRenderContext);
158
0
        ImplControlValue aControlValue;
159
0
        tools::Rectangle aCtrlRegion(rPos, aSize);
160
0
        ControlState nState = ControlState::NONE;
161
162
        //states ControlState::DEFAULT, ControlState::PRESSED and ControlState::ROLLOVER are not implemented
163
0
        if (IsStateHilighted())
164
0
            nState |= ControlState::FOCUSED;
165
0
        if (nStyle != DrawImageFlags::Disable)
166
0
            nState |= ControlState::ENABLED;
167
0
        if (IsStateChecked())
168
0
            aControlValue.setTristateVal(ButtonValue::On);
169
0
        else if (IsStateUnchecked())
170
0
            aControlValue.setTristateVal(ButtonValue::Off);
171
0
        else if (IsStateTristate())
172
0
            aControlValue.setTristateVal(ButtonValue::Mixed);
173
174
0
        if (m_bIsVis)
175
0
            bNativeOK = rRenderContext.DrawNativeControl(
176
0
                eCtrlType, ControlPart::Entire, aCtrlRegion, nState, aControlValue, OUString());
177
0
    }
178
179
0
    if (!bNativeOK && m_bIsVis)
180
0
        rRenderContext.DrawImage(rPos, m_rData.GetImage(nIndex), nStyle);
181
0
}
182
183
std::unique_ptr<SvLBoxItem> SvLBoxButton::Clone(SvLBoxItem const* pSource) const
184
0
{
185
0
    return std::make_unique<SvLBoxButton>(static_cast<SvLBoxButton const*>(pSource)->m_rData,
186
0
                                          false);
187
0
}
188
189
void SvLBoxButton::ImplAdjustBoxSize(Size& io_rSize, ControlType i_eType,
190
                                     vcl::RenderContext const& rRenderContext)
191
0
{
192
0
    if (!rRenderContext.IsNativeControlSupported(i_eType, ControlPart::Entire))
193
0
        return;
194
195
0
    ImplControlValue aControlValue;
196
0
    tools::Rectangle aCtrlRegion(Point(0, 0), io_rSize);
197
198
0
    aControlValue.setTristateVal(ButtonValue::On);
199
200
0
    tools::Rectangle aNativeBounds, aNativeContent;
201
0
    bool bNativeOK = rRenderContext.GetNativeControlRegion(
202
0
        i_eType, ControlPart::Entire, aCtrlRegion, ControlState::ENABLED, aControlValue,
203
0
        aNativeBounds, aNativeContent);
204
0
    if (bNativeOK)
205
0
    {
206
0
        Size aContentSize(aNativeContent.GetSize());
207
        // leave a little space around the box image (looks better)
208
0
        if (aContentSize.Height() + 2 > io_rSize.Height())
209
0
            io_rSize.setHeight(aContentSize.Height() + 2);
210
0
        if (aContentSize.Width() + 2 > io_rSize.Width())
211
0
            io_rSize.setWidth(aContentSize.Width() + 2);
212
0
    }
213
0
}
214
215
void SvLBoxButton::InitViewData(SvTreeListBox& rView, SvTreeListEntry& rEntry,
216
                                SvViewDataItem* pViewData)
217
0
{
218
0
    if (!pViewData)
219
0
        pViewData = &rView.GetViewDataItem(rEntry, *this);
220
0
    Size aSize = m_rData.GetSize();
221
222
0
    ControlType eCtrlType = (m_rData.IsRadio()) ? ControlType::Radiobutton : ControlType::Checkbox;
223
0
    ImplAdjustBoxSize(aSize, eCtrlType, *rView.GetOutDev());
224
0
    pViewData->mnWidth = aSize.Width();
225
0
    pViewData->mnHeight = aSize.Height();
226
0
}
227
228
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */