Coverage Report

Created: 2026-04-09 11:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/weld/MetricSpinButton.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
10
#include <svdata.hxx>
11
12
#include <i18nutil/unicode.hxx>
13
#include <unotools/localedatawrapper.hxx>
14
#include <vcl/fieldvalues.hxx>
15
#include <vcl/weld/MetricSpinButton.hxx>
16
17
namespace weld
18
{
19
OUString MetricSpinButton::MetricToString(FieldUnit rUnit)
20
0
{
21
0
    const FieldUnitStringList& rList = ImplGetFieldUnits();
22
    // return unit's default string (ie, the first one )
23
0
    auto it = std::find_if(
24
0
        rList.begin(), rList.end(),
25
0
        [&rUnit](const std::pair<OUString, FieldUnit>& rItem) { return rItem.second == rUnit; });
26
0
    if (it != rList.end())
27
0
        return it->first;
28
29
0
    return OUString();
30
0
}
31
32
IMPL_LINK_NOARG(MetricSpinButton, spin_button_value_changed, SpinButton&, void)
33
0
{
34
0
    signal_value_changed();
35
0
}
36
37
IMPL_LINK(MetricSpinButton, spin_button_output, sal_Int64, nValue, OUString)
38
0
{
39
0
    return format_number(nValue);
40
0
}
41
42
void MetricSpinButton::update_width_chars()
43
0
{
44
0
    sal_Int64 min, max;
45
0
    m_xSpinButton->get_range(min, max);
46
0
    auto width = std::max(m_xSpinButton->get_pixel_size(format_number(min)).Width(),
47
0
                          m_xSpinButton->get_pixel_size(format_number(max)).Width());
48
0
    int chars = ceil(width / m_xSpinButton->get_approximate_digit_width());
49
0
    m_xSpinButton->set_width_chars(chars);
50
0
}
51
52
OUString MetricSpinButton::format_number(sal_Int64 nValue) const
53
0
{
54
0
    OUString aStr;
55
56
0
    const LocaleDataWrapper& rLocaleData = Application::GetSettings().GetLocaleDataWrapper();
57
58
0
    unsigned int nDecimalDigits = m_xSpinButton->get_digits();
59
    //pawn percent off to icu to decide whether percent is separated from its number for this locale
60
0
    if (m_eSrcUnit == FieldUnit::PERCENT)
61
0
    {
62
0
        double fValue = nValue;
63
0
        fValue /= SpinButton::Power10(nDecimalDigits);
64
0
        aStr = unicode::formatPercent(fValue, rLocaleData.getLanguageTag());
65
0
    }
66
0
    else
67
0
    {
68
0
        aStr = rLocaleData.getNum(nValue, nDecimalDigits, true, true);
69
0
        OUString aSuffix = MetricToString(m_eSrcUnit);
70
0
        if (m_eSrcUnit != FieldUnit::NONE && m_eSrcUnit != FieldUnit::DEGREE
71
0
            && m_eSrcUnit != FieldUnit::INCH && m_eSrcUnit != FieldUnit::FOOT)
72
0
            aStr += " ";
73
0
        if (m_eSrcUnit == FieldUnit::INCH)
74
0
        {
75
0
            OUString sDoublePrime = u"\u2033"_ustr;
76
0
            if (aSuffix != "\"" && aSuffix != sDoublePrime)
77
0
                aStr += " ";
78
0
            else
79
0
                aSuffix = sDoublePrime;
80
0
        }
81
0
        else if (m_eSrcUnit == FieldUnit::FOOT)
82
0
        {
83
0
            OUString sPrime = u"\u2032"_ustr;
84
0
            if (aSuffix != "'" && aSuffix != sPrime)
85
0
                aStr += " ";
86
0
            else
87
0
                aSuffix = sPrime;
88
0
        }
89
90
0
        assert(m_eSrcUnit != FieldUnit::PERCENT);
91
0
        aStr += aSuffix;
92
0
    }
93
94
0
    return aStr;
95
0
}
96
97
void MetricSpinButton::set_digits(unsigned int digits)
98
0
{
99
0
    sal_Int64 step, page;
100
0
    get_increments(step, page, m_eSrcUnit);
101
0
    sal_Int64 value = get_value(m_eSrcUnit);
102
0
    m_xSpinButton->set_digits(digits);
103
0
    set_increments(step, page, m_eSrcUnit);
104
0
    set_value(value, m_eSrcUnit);
105
0
    update_width_chars();
106
0
}
107
108
void MetricSpinButton::set_unit(FieldUnit eUnit)
109
0
{
110
0
    if (eUnit != m_eSrcUnit)
111
0
    {
112
0
        sal_Int64 step, page;
113
0
        get_increments(step, page, m_eSrcUnit);
114
0
        sal_Int64 value = get_value(m_eSrcUnit);
115
0
        m_eSrcUnit = eUnit;
116
0
        set_increments(step, page, m_eSrcUnit);
117
0
        set_value(value, m_eSrcUnit);
118
0
        const OUString sText = format_number(m_xSpinButton->get_value());
119
0
        m_xSpinButton->set_text(sText);
120
0
        update_width_chars();
121
0
    }
122
0
}
123
124
sal_Int64 MetricSpinButton::ConvertValue(sal_Int64 nValue, FieldUnit eInUnit,
125
                                         FieldUnit eOutUnit) const
126
0
{
127
0
    return vcl::ConvertValue(nValue, 0, m_xSpinButton->get_digits(), eInUnit, eOutUnit);
128
0
}
129
130
IMPL_LINK(MetricSpinButton, spin_button_input, const OUString&, rText, std::optional<int>)
131
0
{
132
0
    const LocaleDataWrapper& rLocaleData = Application::GetSettings().GetLocaleDataWrapper();
133
0
    double fResult(0.0);
134
0
    bool bRet
135
0
        = vcl::TextToValue(rText, fResult, 0, m_xSpinButton->get_digits(), rLocaleData, m_eSrcUnit);
136
0
    if (!bRet)
137
0
        return {};
138
139
0
    if (fResult > SAL_MAX_INT32)
140
0
        fResult = SAL_MAX_INT32;
141
0
    else if (fResult < SAL_MIN_INT32)
142
0
        fResult = SAL_MIN_INT32;
143
144
0
    return std::optional<int>(std::round(fResult));
145
0
}
146
}
147
148
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */