Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/formula/source/ui/dlg/funcutl.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/event.hxx>
21
22
#include <formula/funcutl.hxx>
23
#include <formula/IControlReferenceHandler.hxx>
24
#include <vcl/svapp.hxx>
25
#include "ControlHelper.hxx"
26
#include "parawin.hxx"
27
#include <strings.hrc>
28
#include <bitmaps.hlst>
29
#include <core_resource.hxx>
30
31
namespace formula
32
{
33
34
ArgEdit::ArgEdit(std::unique_ptr<weld::Entry> xControl)
35
0
    : RefEdit(std::move(xControl))
36
0
    , pEdPrev(nullptr)
37
0
    , pEdNext(nullptr)
38
0
    , pSlider(nullptr)
39
0
    , pParaWin(nullptr)
40
0
    , nArgs(0)
41
0
{
42
0
}
43
44
void ArgEdit::Init(ArgEdit* pPrevEdit, ArgEdit* pNextEdit,
45
                   weld::ScrolledWindow& rArgSlider,
46
                   ParaWin& rParaWin, sal_uInt16 nArgCount)
47
0
{
48
0
    pEdPrev = pPrevEdit;
49
0
    pEdNext = pNextEdit;
50
0
    pSlider = &rArgSlider;
51
0
    pParaWin = &rParaWin;
52
0
    nArgs   = nArgCount;
53
0
}
54
55
// Cursor control for Edit Fields in Argument Dialog
56
bool ArgEdit::KeyInput(const KeyEvent& rKEvt)
57
0
{
58
0
    vcl::KeyCode aCode = rKEvt.GetKeyCode();
59
0
    bool bUp = (aCode.GetCode() == KEY_UP);
60
0
    bool bDown = (aCode.GetCode() == KEY_DOWN);
61
62
0
    if (   pSlider
63
0
        && ( !aCode.IsShift() && !aCode.IsMod1() && !aCode.IsMod2() )
64
0
        && ( bUp || bDown ) )
65
0
    {
66
0
        if ( nArgs > 1 )
67
0
        {
68
0
            ArgEdit* pEd = nullptr;
69
0
            int nThumb = pSlider->vadjustment_get_value();
70
0
            bool bDoScroll = false;
71
0
            bool bChangeFocus = false;
72
73
0
            if ( bDown )
74
0
            {
75
0
                if ( nArgs > 4 )
76
0
                {
77
0
                    if ( !pEdNext )
78
0
                    {
79
0
                        nThumb++;
80
0
                        bDoScroll = ( nThumb+3 < static_cast<tools::Long>(nArgs) );
81
0
                    }
82
0
                    else
83
0
                    {
84
0
                        pEd = pEdNext;
85
0
                        bChangeFocus = true;
86
0
                    }
87
0
                }
88
0
                else if ( pEdNext )
89
0
                {
90
0
                    pEd = pEdNext;
91
0
                    bChangeFocus = true;
92
0
                }
93
0
            }
94
0
            else // if ( bUp )
95
0
            {
96
0
                if ( nArgs > 4 )
97
0
                {
98
0
                    if ( !pEdPrev )
99
0
                    {
100
0
                        nThumb--;
101
0
                        bDoScroll = ( nThumb >= 0 );
102
0
                    }
103
0
                    else
104
0
                    {
105
0
                        pEd = pEdPrev;
106
0
                        bChangeFocus = true;
107
0
                    }
108
0
                }
109
0
                else if ( pEdPrev )
110
0
                {
111
0
                    pEd = pEdPrev;
112
0
                    bChangeFocus = true;
113
0
                }
114
0
            }
115
116
0
            if ( bDoScroll )
117
0
            {
118
0
                pSlider->vadjustment_set_value( nThumb );
119
0
                pParaWin->SliderMoved();
120
0
            }
121
0
            else if ( bChangeFocus )
122
0
            {
123
0
                pEd->GrabFocus();
124
0
            }
125
0
        }
126
0
        return true;
127
0
    }
128
0
    return RefEdit::KeyInput(rKEvt);
129
0
}
130
131
ArgInput::ArgInput()
132
0
{
133
0
    pFtArg=nullptr;
134
0
    pBtnFx=nullptr;
135
0
    pEdArg=nullptr;
136
0
    pRefBtn=nullptr;
137
0
}
138
139
void ArgInput::InitArgInput(weld::Label* pftArg, weld::Button* pbtnFx,
140
                            ArgEdit* pedArg, RefButton* prefBtn)
141
0
{
142
0
    pFtArg =pftArg;
143
0
    pBtnFx =pbtnFx;
144
0
    pEdArg =pedArg;
145
0
    pRefBtn=prefBtn;
146
147
0
    if(pBtnFx!=nullptr)
148
0
    {
149
0
        pBtnFx->connect_clicked( LINK( this, ArgInput, FxBtnClickHdl ) );
150
0
        pBtnFx->connect_focus_in( LINK( this, ArgInput, FxBtnFocusHdl ) );
151
0
    }
152
0
    if(pEdArg!=nullptr)
153
0
    {
154
0
        pEdArg->SetGetFocusHdl ( LINK( this, ArgInput, EdFocusHdl ) );
155
0
        pEdArg->SetModifyHdl   ( LINK( this, ArgInput, EdModifyHdl ) );
156
0
    }
157
0
}
158
159
// Sets the Name for the Argument
160
void ArgInput::SetArgName(const OUString &aArg)
161
0
{
162
0
    if (pFtArg)
163
0
        pFtArg->set_label(aArg );
164
0
}
165
166
// Returns the Name for the Argument
167
OUString ArgInput::GetArgName() const
168
0
{
169
0
    OUString aPrivArgName;
170
0
    if (pFtArg)
171
0
        aPrivArgName = pFtArg->get_label();
172
0
    return aPrivArgName;
173
0
}
174
175
//Sets the Name for the Argument
176
void ArgInput::SetArgNameFont(const vcl::Font &aFont)
177
0
{
178
0
    if (pFtArg)
179
0
        pFtArg->set_font(aFont);
180
0
}
181
182
//Sets up the Selection for the EditBox.
183
void ArgInput::SelectAll()
184
0
{
185
0
    if (pEdArg)
186
0
        pEdArg->SelectAll();
187
0
}
188
189
//Sets the Value for the Argument
190
void ArgInput::SetArgVal(const OUString &rVal)
191
0
{
192
0
    if (pEdArg)
193
0
        pEdArg->SetRefString(rVal);
194
0
}
195
196
//Returns the Value for the Argument
197
OUString ArgInput::GetArgVal() const
198
0
{
199
0
    OUString aResult;
200
0
    if (pEdArg)
201
0
        aResult=pEdArg->GetText();
202
0
    return aResult;
203
0
}
204
205
//Hides the Controls
206
void ArgInput::Hide()
207
0
{
208
0
    if (pFtArg && pBtnFx && pEdArg && pRefBtn)
209
0
    {
210
0
        pFtArg->hide();
211
0
        pBtnFx->hide();
212
0
        pEdArg->GetWidget()->hide();
213
0
        pRefBtn->GetWidget()->hide();
214
0
    }
215
0
}
216
217
//Casts the Controls again.
218
void ArgInput::Show()
219
0
{
220
0
    if (pFtArg && pBtnFx && pEdArg && pRefBtn)
221
0
    {
222
0
        pFtArg->show();
223
0
        pBtnFx->show();
224
0
        pEdArg->GetWidget()->show();
225
0
        pRefBtn->GetWidget()->show();
226
0
    }
227
0
}
228
229
void ArgInput::UpdateAccessibleNames()
230
0
{
231
0
    OUString aArgName = ":" + pFtArg->get_label();
232
233
0
    OUString aName = pBtnFx->get_tooltip_text() + aArgName;
234
0
    pBtnFx->set_accessible_name(aName);
235
236
0
    aName = pRefBtn->GetWidget()->get_tooltip_text() + aArgName;
237
0
    pRefBtn->GetWidget()->set_accessible_name(aName);
238
0
}
239
240
IMPL_LINK(ArgInput, FxBtnClickHdl, weld::Button&, rBtn, void)
241
0
{
242
0
    if (&rBtn == pBtnFx)
243
0
        aFxClickLink.Call(*this);
244
0
}
245
246
IMPL_LINK( ArgInput, FxBtnFocusHdl, weld::Widget&, rControl, void )
247
0
{
248
0
    if (&rControl == pBtnFx)
249
0
        aFxFocusLink.Call(*this);
250
0
}
251
252
IMPL_LINK( ArgInput, EdFocusHdl, RefEdit&, rControl, void )
253
0
{
254
0
    if (&rControl == pEdArg)
255
0
        aEdFocusLink.Call(*this);
256
0
}
257
258
IMPL_LINK( ArgInput, EdModifyHdl, RefEdit&, rEdit, void )
259
0
{
260
0
    if (&rEdit == pEdArg)
261
0
        aEdModifyLink.Call(*this);
262
0
}
263
264
RefEdit::RefEdit(std::unique_ptr<weld::Entry> xControl)
265
0
    : mxEntry(std::move(xControl))
266
0
    , maIdle("formula RefEdit Idle")
267
0
    , mpAnyRefDlg(nullptr)
268
0
    , mpFocusInEvent(nullptr)
269
0
    , mpFocusOutEvent(nullptr)
270
0
{
271
0
    mxEntry->connect_focus_in(LINK(this, RefEdit, GetFocusHdl));
272
0
    mxEntry->connect_focus_out(LINK(this, RefEdit, LoseFocusHdl));
273
0
    mxEntry->connect_key_press(LINK(this, RefEdit, KeyInputHdl));
274
0
    mxEntry->connect_changed(LINK(this, RefEdit, Modify));
275
0
    maIdle.SetInvokeHandler(LINK(this, RefEdit, UpdateHdl));
276
0
}
277
278
RefEdit::~RefEdit()
279
0
{
280
0
    if (mpFocusInEvent)
281
0
        Application::RemoveUserEvent(mpFocusInEvent);
282
0
    if (mpFocusOutEvent)
283
0
        Application::RemoveUserEvent(mpFocusOutEvent);
284
0
    maIdle.ClearInvokeHandler();
285
0
    maIdle.Stop();
286
0
}
287
288
void RefEdit::SetRefString( const OUString& rStr )
289
0
{
290
    // Prevent unwanted side effects by setting only a differing string.
291
    // See commit message for reasons.
292
0
    if (mxEntry->get_text() != rStr)
293
0
        mxEntry->set_text(rStr);
294
0
}
295
296
void RefEdit::SetRefValid(bool bValid)
297
0
{
298
0
    mxEntry->set_message_type(bValid ? weld::EntryMessageType::Normal
299
0
                                     : weld::EntryMessageType::Error);
300
0
}
301
302
void RefEdit::SetText(const OUString& rStr)
303
0
{
304
0
    mxEntry->set_text(rStr);
305
0
    UpdateHdl(&maIdle);
306
0
}
307
308
void RefEdit::StartUpdateData()
309
0
{
310
0
    maIdle.Start();
311
0
}
312
313
void RefEdit::SetReferences(IControlReferenceHandler* pDlg, weld::Label* pLabel)
314
0
{
315
0
    mpAnyRefDlg = pDlg;
316
0
    if (pLabel)
317
0
        maGetLabelTextForShrinkModeFunc = [pLabel] { return pLabel->get_label(); };
318
0
    else
319
0
        maGetLabelTextForShrinkModeFunc = nullptr;
320
321
0
    if( pDlg )
322
0
    {
323
0
        maIdle.SetInvokeHandler(LINK(this, RefEdit, UpdateHdl));
324
0
    }
325
0
    else
326
0
    {
327
0
        maIdle.ClearInvokeHandler();
328
0
        maIdle.Stop();
329
0
    }
330
0
}
331
332
void RefEdit::SetReferences(IControlReferenceHandler* pDlg, weld::Frame* pFrame)
333
0
{
334
0
    SetReferences(pDlg);
335
336
0
    if (pFrame)
337
0
        maGetLabelTextForShrinkModeFunc = [pFrame] { return pFrame->get_label(); };
338
0
}
339
340
OUString RefEdit::GetLabelTextForShrinkMode()
341
0
{
342
0
    if (maGetLabelTextForShrinkModeFunc)
343
0
        return maGetLabelTextForShrinkModeFunc();
344
345
0
    return OUString();
346
0
}
347
348
IMPL_LINK_NOARG(RefEdit, Modify, weld::Entry&, void)
349
0
{
350
0
    maModifyHdl.Call(*this);
351
0
    if (mpAnyRefDlg)
352
0
        mpAnyRefDlg->HideReference();
353
0
}
354
355
IMPL_LINK(RefEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool)
356
0
{
357
0
    return KeyInput(rKEvt);
358
0
}
359
360
bool RefEdit::KeyInput(const KeyEvent& rKEvt)
361
0
{
362
0
    const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
363
0
    if (mpAnyRefDlg && !rKeyCode.GetModifier() && rKeyCode.GetCode() == KEY_F2)
364
0
    {
365
0
        mpAnyRefDlg->ReleaseFocus(this);
366
0
        return true;
367
0
    }
368
369
0
    switch (rKeyCode.GetCode())
370
0
    {
371
0
        case KEY_RETURN:
372
0
        case KEY_ESCAPE:
373
0
            return maActivateHdl.Call(*GetWidget());
374
0
    }
375
376
0
    return false;
377
0
}
378
379
void RefEdit::GetFocus()
380
0
{
381
0
    maGetFocusHdl.Call(*this);
382
0
    StartUpdateData();
383
0
}
384
385
void RefEdit::LoseFocus()
386
0
{
387
0
    maLoseFocusHdl.Call(*this);
388
0
    if (mpAnyRefDlg)
389
0
        mpAnyRefDlg->HideReference();
390
0
}
391
392
IMPL_LINK_NOARG(RefEdit, GetFocusHdl, weld::Widget&, void)
393
0
{
394
    // in e.g. function wizard RefEdits we want to select all when we get focus
395
    // but in the gtk case there are pending gtk handlers which change selection
396
    // after our handler, so post our focus in event to happen after those complete
397
0
    if (mpFocusInEvent)
398
0
        Application::RemoveUserEvent(mpFocusInEvent);
399
0
    mpFocusInEvent = Application::PostUserEvent(LINK(this, RefEdit, AsyncFocusInHdl));
400
0
}
401
402
IMPL_LINK_NOARG(RefEdit, LoseFocusHdl, weld::Widget&, void)
403
0
{
404
    // tdf#127262 because focus in is async, focus out must not appear out
405
    // of sequence to focus in
406
0
    if (mpFocusOutEvent)
407
0
        Application::RemoveUserEvent(mpFocusOutEvent);
408
0
    mpFocusOutEvent = Application::PostUserEvent(LINK(this, RefEdit, AsyncFocusOutHdl));
409
0
}
410
411
IMPL_LINK_NOARG(RefEdit, AsyncFocusInHdl, void*, void)
412
0
{
413
0
    mpFocusInEvent = nullptr;
414
0
    GetFocus();
415
0
}
416
417
IMPL_LINK_NOARG(RefEdit, AsyncFocusOutHdl, void*, void)
418
0
{
419
0
    mpFocusOutEvent = nullptr;
420
0
    LoseFocus();
421
0
}
422
423
IMPL_LINK_NOARG(RefEdit, UpdateHdl, Timer *, void)
424
0
{
425
0
    if (mpAnyRefDlg)
426
0
        mpAnyRefDlg->ShowReference(mxEntry->get_text());
427
0
}
428
429
RefButton::RefButton(std::unique_ptr<weld::Button> xControl)
430
0
    : xButton(std::move(xControl))
431
0
    , pAnyRefDlg( nullptr )
432
0
    , pRefEdit( nullptr )
433
0
{
434
0
    xButton->connect_focus_in(LINK(this, RefButton, GetFocus));
435
0
    xButton->connect_focus_out(LINK(this, RefButton, LoseFocus));
436
0
    xButton->connect_key_press(LINK(this, RefButton, KeyInput));
437
0
    xButton->connect_clicked(LINK(this, RefButton, Click));
438
0
    SetStartImage();
439
0
}
440
441
RefButton::~RefButton()
442
0
{
443
0
}
444
445
void RefButton::SetStartImage()
446
0
{
447
0
    xButton->set_from_icon_name(RID_BMP_REFBTN1);
448
0
    xButton->set_tooltip_text(ForResId(RID_STR_SHRINK));
449
0
}
450
451
void RefButton::SetEndImage()
452
0
{
453
0
    xButton->set_from_icon_name(RID_BMP_REFBTN2);
454
0
    xButton->set_tooltip_text(ForResId(RID_STR_EXPAND));
455
0
}
456
457
void RefButton::SetReferences( IControlReferenceHandler* pDlg, RefEdit* pEdit )
458
0
{
459
0
    pAnyRefDlg = pDlg;
460
0
    pRefEdit = pEdit;
461
0
}
462
463
IMPL_LINK_NOARG(RefButton, Click, weld::Button&, void)
464
0
{
465
0
    maClickHdl.Call(*this);
466
0
    if( pAnyRefDlg )
467
0
        pAnyRefDlg->ToggleCollapsed( pRefEdit, this );
468
0
}
469
470
IMPL_LINK(RefButton, KeyInput, const KeyEvent&, rKEvt, bool)
471
0
{
472
0
    const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
473
0
    if (pAnyRefDlg && !rKeyCode.GetModifier() && rKeyCode.GetCode() == KEY_F2)
474
0
    {
475
0
        pAnyRefDlg->ReleaseFocus( pRefEdit );
476
0
        return true;
477
0
    }
478
479
0
    switch (rKeyCode.GetCode())
480
0
    {
481
0
        case KEY_RETURN:
482
0
        case KEY_ESCAPE:
483
0
            return maActivateHdl.Call(*GetWidget());
484
0
    }
485
486
0
    return false;
487
0
}
488
489
IMPL_LINK_NOARG(RefButton, GetFocus, weld::Widget&, void)
490
0
{
491
0
    maGetFocusHdl.Call(*this);
492
0
    if (pRefEdit)
493
0
        pRefEdit->StartUpdateData();
494
0
}
495
496
IMPL_LINK_NOARG(RefButton, LoseFocus, weld::Widget&, void)
497
0
{
498
0
    maLoseFocusHdl.Call(*this);
499
0
    if (pRefEdit)
500
0
        pRefEdit->DoModify();
501
0
}
502
503
} // formula
504
505
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */