Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/toolkit/source/helper/btndlg.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 <vcl/toolkit/button.hxx>
21
#include <vcl/stdtext.hxx>
22
#include <helper/btndlg.hxx>
23
#include <sal/log.hxx>
24
#include <map>
25
#include <memory>
26
27
struct ImplBtnDlgItem
28
{
29
    sal_uInt16              mnId;
30
    bool                    mbOwnButton;
31
    tools::Long                    mnSepSize;
32
    VclPtr<PushButton>      mpPushButton;
33
34
0
    ImplBtnDlgItem() : mnId(0), mbOwnButton(false), mnSepSize(0) {}
35
};
36
37
void ButtonDialog::ImplInitButtonDialogData()
38
0
{
39
0
    mnButtonSize            = 0;
40
0
    mnCurButtonId           = 0;
41
0
    mnFocusButtonId         = BUTTONDIALOG_BUTTON_NOTFOUND;
42
0
    mbFormat                = true;
43
0
}
44
45
ButtonDialog::ButtonDialog( WindowType eType ) :
46
0
    Dialog( eType )
47
0
{
48
0
    ImplInitButtonDialogData();
49
0
}
Unexecuted instantiation: ButtonDialog::ButtonDialog(WindowType)
Unexecuted instantiation: ButtonDialog::ButtonDialog(WindowType)
50
51
ButtonDialog::~ButtonDialog()
52
0
{
53
0
    disposeOnce();
54
0
}
55
56
void ButtonDialog::dispose()
57
0
{
58
0
    for (auto & it : m_ItemList)
59
0
    {
60
0
        if ( it->mbOwnButton )
61
0
            it->mpPushButton.disposeAndClear();
62
0
    }
63
0
    m_ItemList.clear();
64
0
    Dialog::dispose();
65
0
}
66
67
VclPtr<PushButton> ButtonDialog::ImplCreatePushButton( ButtonDialogFlags nBtnFlags )
68
0
{
69
0
    VclPtr<PushButton> pBtn;
70
0
    WinBits     nStyle = 0;
71
72
0
    if ( nBtnFlags & ButtonDialogFlags::Default )
73
0
        nStyle |= WB_DEFBUTTON;
74
0
    if ( nBtnFlags & ButtonDialogFlags::Cancel )
75
0
        pBtn = VclPtr<CancelButton>::Create( this, nStyle );
76
0
    else if ( nBtnFlags & ButtonDialogFlags::OK )
77
0
        pBtn = VclPtr<OKButton>::Create( this, nStyle );
78
0
    else if ( nBtnFlags & ButtonDialogFlags::Help )
79
0
        pBtn = VclPtr<HelpButton>::Create( this, nStyle );
80
0
    else
81
0
        pBtn = VclPtr<PushButton>::Create( this, nStyle );
82
83
0
    if ( !(nBtnFlags & ButtonDialogFlags::Help) )
84
0
        pBtn->SetClickHdl( LINK( this, ButtonDialog, ImplClickHdl ) );
85
86
0
    return pBtn;
87
0
}
88
89
tools::Long ButtonDialog::ImplGetButtonSize()
90
0
{
91
0
    if ( !mbFormat )
92
0
        return mnButtonSize;
93
94
    // Calculate ButtonSize
95
0
    tools::Long nLastSepSize = 0;
96
0
    tools::Long nSepSize = 0;
97
0
    maCtrlSize = Size( IMPL_MINSIZE_BUTTON_WIDTH, IMPL_MINSIZE_BUTTON_HEIGHT );
98
99
0
    for (const auto & it : m_ItemList)
100
0
    {
101
0
        nSepSize += nLastSepSize;
102
103
0
        tools::Long nTxtWidth = it->mpPushButton->GetOutDev()->GetCtrlTextWidth(it->mpPushButton->GetText());
104
0
        nTxtWidth += IMPL_EXTRA_BUTTON_WIDTH;
105
106
0
        if ( nTxtWidth > maCtrlSize.Width() )
107
0
            maCtrlSize.setWidth( nTxtWidth );
108
109
0
        tools::Long nTxtHeight = it->mpPushButton->GetTextHeight();
110
0
        nTxtHeight += IMPL_EXTRA_BUTTON_HEIGHT;
111
112
0
        if ( nTxtHeight > maCtrlSize.Height() )
113
0
            maCtrlSize.setHeight( nTxtHeight );
114
115
0
        nSepSize += it->mnSepSize;
116
117
0
        if ( GetStyle() & WB_HORZ )
118
0
            nLastSepSize = IMPL_SEP_BUTTON_X;
119
0
        else
120
0
            nLastSepSize = IMPL_SEP_BUTTON_Y;
121
0
    }
122
123
0
    size_t const nButtonCount = m_ItemList.size();
124
125
0
    if ( GetStyle() & WB_HORZ )
126
0
        mnButtonSize  = nSepSize + (nButtonCount*maCtrlSize.Width());
127
0
    else
128
0
        mnButtonSize = nSepSize + (nButtonCount*maCtrlSize.Height());
129
130
0
    return mnButtonSize;
131
0
}
132
133
void ButtonDialog::ImplPosControls()
134
0
{
135
0
    if ( !mbFormat )
136
0
        return;
137
138
    // Create PushButtons and determine Sizes
139
0
    ImplGetButtonSize();
140
141
    // determine dialog size
142
0
    Size            aDlgSize = maPageSize;
143
0
    tools::Long            nX;
144
0
    tools::Long            nY;
145
0
    if ( GetStyle() & WB_HORZ )
146
0
    {
147
0
        if ( mnButtonSize+(IMPL_DIALOG_OFFSET*2) > aDlgSize.Width() )
148
0
            aDlgSize.setWidth( mnButtonSize+(IMPL_DIALOG_OFFSET*2) );
149
0
        if ( GetStyle() & WB_LEFT )
150
0
            nX = IMPL_DIALOG_OFFSET;
151
0
        else if ( GetStyle() & WB_RIGHT )
152
0
            nX = aDlgSize.Width()-mnButtonSize-IMPL_DIALOG_OFFSET;
153
0
        else
154
0
            nX = (aDlgSize.Width()-mnButtonSize)/2;
155
156
0
        aDlgSize.AdjustHeight(IMPL_DIALOG_OFFSET+maCtrlSize.Height() );
157
0
        nY = aDlgSize.Height()-maCtrlSize.Height()-IMPL_DIALOG_OFFSET;
158
0
    }
159
0
    else
160
0
    {
161
0
        if ( mnButtonSize+(IMPL_DIALOG_OFFSET*2) > aDlgSize.Height() )
162
0
            aDlgSize.setHeight( mnButtonSize+(IMPL_DIALOG_OFFSET*2) );
163
0
        if ( GetStyle() & WB_BOTTOM )
164
0
            nY = aDlgSize.Height()-mnButtonSize-IMPL_DIALOG_OFFSET;
165
0
        else if ( GetStyle() & WB_VCENTER )
166
0
            nY = (aDlgSize.Height()-mnButtonSize)/2;
167
0
        else
168
0
            nY = IMPL_DIALOG_OFFSET;
169
170
0
        aDlgSize.AdjustWidth(IMPL_DIALOG_OFFSET+maCtrlSize.Width() );
171
0
        nX = aDlgSize.Width()-maCtrlSize.Width()-IMPL_DIALOG_OFFSET;
172
0
    }
173
174
    // Arrange PushButtons
175
0
    for (auto & it : m_ItemList)
176
0
    {
177
0
        if ( GetStyle() & WB_HORZ )
178
0
            nX += it->mnSepSize;
179
0
        else
180
0
            nY += it->mnSepSize;
181
182
0
        it->mpPushButton->SetPosSizePixel( Point( nX, nY ), maCtrlSize );
183
0
        it->mpPushButton->Show();
184
185
0
        if ( GetStyle() & WB_HORZ )
186
0
            nX += maCtrlSize.Width()+IMPL_SEP_BUTTON_X;
187
0
        else
188
0
            nY += maCtrlSize.Height()+IMPL_SEP_BUTTON_Y;
189
0
    }
190
191
0
    SetOutputSizePixel(aDlgSize);
192
0
    SetMinOutputSizePixel(aDlgSize);
193
194
0
    mbFormat = false;
195
0
}
196
197
IMPL_LINK( ButtonDialog, ImplClickHdl, Button*, pBtn, void )
198
0
{
199
0
    for (const auto & it : m_ItemList)
200
0
    {
201
0
        if ( it->mpPushButton == pBtn )
202
0
        {
203
0
            mnCurButtonId = it->mnId;
204
0
            if ( IsInExecute() )
205
0
                EndDialog( mnCurButtonId );
206
0
            break;
207
0
        }
208
0
    }
209
0
}
210
211
void ButtonDialog::Resize()
212
0
{
213
0
}
214
215
void ButtonDialog::StateChanged( StateChangedType nType )
216
0
{
217
0
    if ( nType == StateChangedType::InitShow )
218
0
    {
219
0
        ImplPosControls();
220
0
        for (auto & it : m_ItemList)
221
0
        {
222
0
            if ( it->mpPushButton && it->mbOwnButton )
223
0
                it->mpPushButton->SetZOrder(nullptr, ZOrderFlags::Last);
224
0
        }
225
226
        // Set focus on default button.
227
0
        if ( mnFocusButtonId != BUTTONDIALOG_BUTTON_NOTFOUND )
228
0
        {
229
0
            for (auto & it : m_ItemList)
230
0
            {
231
0
                if (it->mnId == mnFocusButtonId )
232
0
                {
233
0
                    if (it->mpPushButton->IsVisible())
234
0
                        it->mpPushButton->GrabFocus();
235
236
0
                    break;
237
0
                }
238
0
            }
239
0
        }
240
0
    }
241
242
0
    Dialog::StateChanged( nType );
243
0
}
244
245
void ButtonDialog::AddButton( StandardButtonType eType, sal_uInt16 nId,
246
                              ButtonDialogFlags nBtnFlags, tools::Long nSepPixel )
247
0
{
248
    // PageItem anlegen
249
0
    std::unique_ptr<ImplBtnDlgItem> pItem(new ImplBtnDlgItem);
250
0
    pItem->mnId             = nId;
251
0
    pItem->mbOwnButton      = true;
252
0
    pItem->mnSepSize        = nSepPixel;
253
254
0
    if ( eType == StandardButtonType::OK )
255
0
        nBtnFlags |= ButtonDialogFlags::OK;
256
0
    else if ( eType == StandardButtonType::Help )
257
0
        nBtnFlags |= ButtonDialogFlags::Help;
258
0
    else if ( (eType == StandardButtonType::Cancel) || (eType == StandardButtonType::Close) )
259
0
        nBtnFlags |= ButtonDialogFlags::Cancel;
260
0
    pItem->mpPushButton = ImplCreatePushButton( nBtnFlags );
261
262
    // Standard-Buttons have the right text already
263
0
    if ( !((eType == StandardButtonType::OK     && pItem->mpPushButton->GetType() == WindowType::OKBUTTON) ||
264
0
           (eType == StandardButtonType::Cancel && pItem->mpPushButton->GetType() == WindowType::CANCELBUTTON) ||
265
0
           (eType == StandardButtonType::Help   && pItem->mpPushButton->GetType() == WindowType::HELPBUTTON)) )
266
0
    {
267
0
        std::map<StandardButtonType, OUString> mapButtonTypeToID = {{StandardButtonType::Yes, "yes"},
268
0
            {StandardButtonType::No, "no"}, {StandardButtonType::Retry, "retry"},
269
0
            {StandardButtonType::Close, "close"}, {StandardButtonType::More, "more"},
270
0
            {StandardButtonType::Ignore, "ignore"}, {StandardButtonType::Abort, "abort"},
271
0
            {StandardButtonType::Less, "less"}, {StandardButtonType::Count, "count"}};
272
0
        auto itr = mapButtonTypeToID.find(eType);
273
0
        if (itr != mapButtonTypeToID.end())
274
0
            pItem->mpPushButton->set_id(itr->second);
275
0
        pItem->mpPushButton->SetText( GetStandardText( eType ) );
276
0
    }
277
278
0
    if ( nBtnFlags & ButtonDialogFlags::Focus )
279
0
        mnFocusButtonId = nId;
280
281
0
    m_ItemList.push_back(std::move(pItem));
282
283
0
    mbFormat = true;
284
0
}
285
286
void ButtonDialog::RemoveButton( sal_uInt16 nId )
287
0
{
288
0
    auto it = std::find_if(m_ItemList.begin(), m_ItemList.end(),
289
0
        [&nId](const std::unique_ptr<ImplBtnDlgItem>& rItem) { return rItem->mnId == nId; });
290
0
    if (it != m_ItemList.end())
291
0
    {
292
0
        (*it)->mpPushButton->Hide();
293
0
        if ((*it)->mbOwnButton)
294
0
            (*it)->mpPushButton.disposeAndClear();
295
0
        else
296
0
            (*it)->mpPushButton.reset();
297
0
        m_ItemList.erase(it);
298
0
        return;
299
0
    }
300
301
0
    SAL_WARN( "vcl.window", "ButtonDialog::RemoveButton(): ButtonId invalid" );
302
0
}
303
304
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */