LibreOffice Module sw (master) 1
prcntfld.cxx
Go to the documentation of this file.
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 <prcntfld.hxx>
21#include <vcl/fieldvalues.hxx>
22
23SwPercentField::SwPercentField(std::unique_ptr<weld::MetricSpinButton> pControl)
24 : m_pField(std::move(pControl))
25 , m_nOldMax(0)
26 , m_nOldMin(0)
27 , m_nLastPercent(-1)
28 , m_nLastValue(-1)
29 , m_nOldDigits(m_pField->get_digits())
30 , m_eOldUnit(FieldUnit::NONE)
31 , m_bLockAutoCalculation(false)
32{
33 sal_Int64 nMin, nMax;
34 m_pField->get_range(nMin, nMax, FieldUnit::TWIP);
36 m_pField->get_increments(m_nOldSpinSize, m_nOldPageSize, FieldUnit::NONE);
37}
38
39void SwPercentField::SetRefValue(sal_Int64 nValue)
40{
41 sal_Int64 nRealValue = GetRealValue(m_eOldUnit);
42
44
45 if (!m_bLockAutoCalculation && (m_pField->get_unit() == FieldUnit::PERCENT))
46 set_value(nRealValue, m_eOldUnit);
47}
48
49void SwPercentField::ShowPercent(bool bPercent)
50{
51 if ((bPercent && m_pField->get_unit() == FieldUnit::PERCENT)
52 || (!bPercent && m_pField->get_unit() != FieldUnit::PERCENT))
53 return;
54
55 sal_Int64 nOldValue;
56
57 if (bPercent)
58 {
59 nOldValue = get_value();
60
61 m_eOldUnit = m_pField->get_unit();
62 m_nOldDigits = m_pField->get_digits();
63 m_pField->get_range(m_nOldMin, m_nOldMax, FieldUnit::NONE);
64 m_pField->get_increments(m_nOldSpinSize, m_nOldPageSize, FieldUnit::NONE);
65 m_pField->set_unit(FieldUnit::PERCENT);
66 m_pField->set_digits(0);
67
68 sal_Int64 nCurrentWidth
69 = vcl::ConvertValue(m_nOldMin, 0, m_nOldDigits, m_eOldUnit, FieldUnit::TWIP);
70 // round to 0.5 percent
71 int nPercent = m_nRefValue ? (((nCurrentWidth * 10) / m_nRefValue + 5) / 10) : 0;
72
73 m_pField->set_range(std::max(1, nPercent), 100, FieldUnit::NONE);
74 m_pField->set_increments(5, 10, FieldUnit::NONE);
75 if (nOldValue != m_nLastValue)
76 {
77 nCurrentWidth
78 = vcl::ConvertValue(nOldValue, 0, m_nOldDigits, m_eOldUnit, FieldUnit::TWIP);
79 nPercent = m_nRefValue ? (((nCurrentWidth * 10) / m_nRefValue + 5) / 10) : 0;
80 m_pField->set_value(nPercent, FieldUnit::NONE);
81 m_nLastPercent = nPercent;
82 m_nLastValue = nOldValue;
83 }
84 else
85 m_pField->set_value(m_nLastPercent, FieldUnit::NONE);
86 }
87 else
88 {
89 sal_Int64 nOldPercent = get_value(FieldUnit::PERCENT);
90
91 nOldValue = Convert(get_value(), m_pField->get_unit(), m_eOldUnit);
92
93 m_pField->set_unit(m_eOldUnit);
94 m_pField->set_digits(m_nOldDigits);
95 m_pField->set_range(m_nOldMin, m_nOldMax, FieldUnit::NONE);
96 m_pField->set_increments(m_nOldSpinSize, m_nOldPageSize, FieldUnit::NONE);
97
98 if (nOldPercent != m_nLastPercent)
99 {
100 set_value(nOldValue, m_eOldUnit);
101 m_nLastPercent = nOldPercent;
102 m_nLastValue = nOldValue;
103 }
104 else
106 }
107}
108
109void SwPercentField::set_value(sal_Int64 nNewValue, FieldUnit eInUnit)
110{
111 if (m_pField->get_unit() != FieldUnit::PERCENT || eInUnit == FieldUnit::PERCENT)
112 m_pField->set_value(Convert(nNewValue, eInUnit, m_pField->get_unit()), FieldUnit::NONE);
113 else
114 {
115 // Overwrite output value, do not restore later
116 sal_Int64 nPercent, nCurrentWidth;
117 if (eInUnit == FieldUnit::TWIP)
118 {
119 nCurrentWidth
120 = vcl::ConvertValue(nNewValue, 0, m_nOldDigits, FieldUnit::TWIP, FieldUnit::TWIP);
121 }
122 else
123 {
124 sal_Int64 nValue = Convert(nNewValue, eInUnit, m_eOldUnit);
125 nCurrentWidth = vcl::ConvertValue(nValue, 0, m_nOldDigits, m_eOldUnit, FieldUnit::TWIP);
126 }
127 nPercent = m_nRefValue ? (((nCurrentWidth * 10) / m_nRefValue + 5) / 10) : 0;
128 m_pField->set_value(nPercent, FieldUnit::NONE);
129 }
130}
131
133{
134 return Convert(m_pField->get_value(FieldUnit::NONE), m_pField->get_unit(), eOutUnit);
135}
136
137void SwPercentField::set_min(sal_Int64 nNewMin, FieldUnit eInUnit)
138{
139 if (m_pField->get_unit() != FieldUnit::PERCENT)
140 m_pField->set_min(nNewMin, eInUnit);
141 else
142 {
143 if (eInUnit == FieldUnit::NONE)
144 eInUnit = m_eOldUnit;
145 m_nOldMin = Convert(nNewMin, eInUnit, m_eOldUnit);
146
147 int nPercent = Convert(nNewMin, eInUnit, FieldUnit::PERCENT);
148 m_pField->set_min(std::max(1, nPercent), FieldUnit::NONE);
149 }
150}
151
152void SwPercentField::set_max(sal_Int64 nNewMax, FieldUnit eInUnit)
153{
154 if (m_pField->get_unit() != FieldUnit::PERCENT)
155 m_pField->set_max(nNewMax, eInUnit);
156}
157
158sal_Int64 SwPercentField::NormalizePercent(sal_Int64 nValue)
159{
160 if (m_pField->get_unit() != FieldUnit::PERCENT)
161 nValue = m_pField->normalize(nValue);
162 else
164 return nValue;
165}
166
167sal_Int64 SwPercentField::DenormalizePercent(sal_Int64 nValue)
168{
169 if (m_pField->get_unit() != FieldUnit::PERCENT)
170 nValue = m_pField->denormalize(nValue);
171 else
172 {
173 int nFactor = ImpPower10(m_nOldDigits);
174 nValue = ((nValue + (nFactor / 2)) / nFactor);
175 }
176 return nValue;
177}
178
180{
181 int nValue = 1;
182
183 for (sal_uInt16 i = 0; i < n; ++i)
184 nValue *= 10;
185
186 return nValue;
187}
188
190{
191 if (m_pField->get_unit() != FieldUnit::PERCENT)
192 return get_value(eOutUnit);
193 else
194 return Convert(get_value(), m_pField->get_unit(), eOutUnit);
195}
196
197sal_Int64 SwPercentField::Convert(sal_Int64 nValue, FieldUnit eInUnit, FieldUnit eOutUnit)
198{
199 if (eInUnit == eOutUnit || (eInUnit == FieldUnit::NONE && eOutUnit == m_pField->get_unit())
200 || (eOutUnit == FieldUnit::NONE && eInUnit == m_pField->get_unit()))
201 return nValue;
202
203 if (eInUnit == FieldUnit::PERCENT)
204 {
205 // Convert to metric
206 sal_Int64 nTwipValue = (m_nRefValue * nValue + 50) / 100;
207
208 if (eOutUnit == FieldUnit::TWIP) // Only convert if necessary
209 return NormalizePercent(nTwipValue);
210 else
211 return vcl::ConvertValue(NormalizePercent(nTwipValue), 0, m_nOldDigits, FieldUnit::TWIP,
212 eOutUnit);
213 }
214
215 if (eOutUnit == FieldUnit::PERCENT)
216 {
217 // Convert to percent
218 sal_Int64 nCurrentWidth;
220
221 if (eInUnit == FieldUnit::TWIP) // Only convert if necessary
222 nCurrentWidth = nValue;
223 else
224 nCurrentWidth = vcl::ConvertValue(nValue, 0, m_nOldDigits, eInUnit, FieldUnit::TWIP);
225 // Round to 0.5 percent
226 return m_nRefValue ? (((nCurrentWidth * 1000) / m_nRefValue + 5) / 10) : 0;
227 }
228
229 return vcl::ConvertValue(nValue, 0, m_nOldDigits, eInUnit, eOutUnit);
230}
231/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int64 m_nLastValue
Definition: prcntfld.hxx:36
SwPercentField(std::unique_ptr< weld::MetricSpinButton > pControl)
Definition: prcntfld.cxx:23
sal_Int64 m_nRefValue
Definition: prcntfld.hxx:30
int m_nOldPageSize
Definition: prcntfld.hxx:34
int m_nOldSpinSize
Definition: prcntfld.hxx:33
void SetRefValue(sal_Int64 nValue)
Definition: prcntfld.cxx:39
sal_Int64 m_nOldMin
Definition: prcntfld.hxx:32
void ShowPercent(bool bPercent)
Definition: prcntfld.cxx:49
void set_value(sal_Int64 nNewValue, FieldUnit eInUnit=FieldUnit::NONE)
Definition: prcntfld.cxx:109
sal_Int64 m_nOldMax
Definition: prcntfld.hxx:31
sal_Int64 DenormalizePercent(sal_Int64 nValue)
Definition: prcntfld.cxx:167
sal_Int64 NormalizePercent(sal_Int64 nValue)
Definition: prcntfld.cxx:158
sal_uInt16 m_nOldDigits
Definition: prcntfld.hxx:37
sal_Int64 m_nLastPercent
Definition: prcntfld.hxx:35
static SAL_DLLPRIVATE int ImpPower10(sal_uInt16 n)
Definition: prcntfld.cxx:179
FieldUnit m_eOldUnit
Definition: prcntfld.hxx:38
sal_Int64 GetRealValue(FieldUnit eOutUnit)
Definition: prcntfld.cxx:189
std::unique_ptr< weld::MetricSpinButton > m_pField
Definition: prcntfld.hxx:28
sal_Int64 Convert(sal_Int64 nValue, FieldUnit eInUnit, FieldUnit eOutUnit)
Definition: prcntfld.cxx:197
void set_max(sal_Int64 nNewMax, FieldUnit eInUnit)
Definition: prcntfld.cxx:152
void set_min(sal_Int64 nNewMin, FieldUnit eInUnit)
Definition: prcntfld.cxx:137
bool m_bLockAutoCalculation
Definition: prcntfld.hxx:39
sal_Int64 get_value(FieldUnit eOutUnit=FieldUnit::NONE)
Definition: prcntfld.cxx:132
FieldUnit
sal_Int16 nValue
sal_Int64 n
int i
sal_Int64 ConvertValue(sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, FieldUnit eInUnit, FieldUnit eOutUnit)