Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / uibase / utlui / prcntfld.cxx
blob4c8eede6619d7f11b3e8b10e718849179f7421c5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <prcntfld.hxx>
21 #include <vcl/fieldvalues.hxx>
23 SwPercentField::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)
33 sal_Int64 nMin, nMax;
34 m_pField->get_range(nMin, nMax, FieldUnit::TWIP);
35 m_nRefValue = DenormalizePercent(nMax);
36 m_pField->get_increments(m_nOldSpinSize, m_nOldPageSize, FieldUnit::NONE);
39 void SwPercentField::SetRefValue(sal_Int64 nValue)
41 sal_Int64 nRealValue = GetRealValue(m_eOldUnit);
43 m_nRefValue = nValue;
45 if (!m_bLockAutoCalculation && (m_pField->get_unit() == FieldUnit::PERCENT))
46 set_value(nRealValue, m_eOldUnit);
49 void SwPercentField::ShowPercent(bool bPercent)
51 if ((bPercent && m_pField->get_unit() == FieldUnit::PERCENT)
52 || (!bPercent && m_pField->get_unit() != FieldUnit::PERCENT))
53 return;
55 sal_Int64 nOldValue;
57 if (bPercent)
59 nOldValue = get_value();
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);
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;
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)
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;
84 else
85 m_pField->set_value(m_nLastPercent, FieldUnit::NONE);
87 else
89 sal_Int64 nOldPercent = get_value(FieldUnit::PERCENT);
91 nOldValue = Convert(get_value(), m_pField->get_unit(), m_eOldUnit);
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);
98 if (nOldPercent != m_nLastPercent)
100 set_value(nOldValue, m_eOldUnit);
101 m_nLastPercent = nOldPercent;
102 m_nLastValue = nOldValue;
104 else
105 set_value(m_nLastValue, m_eOldUnit);
109 void SwPercentField::set_value(sal_Int64 nNewValue, FieldUnit eInUnit)
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
115 // Overwrite output value, do not restore later
116 sal_Int64 nPercent, nCurrentWidth;
117 if (eInUnit == FieldUnit::TWIP)
119 nCurrentWidth
120 = vcl::ConvertValue(nNewValue, 0, m_nOldDigits, FieldUnit::TWIP, FieldUnit::TWIP);
122 else
124 sal_Int64 nValue = Convert(nNewValue, eInUnit, m_eOldUnit);
125 nCurrentWidth = vcl::ConvertValue(nValue, 0, m_nOldDigits, m_eOldUnit, FieldUnit::TWIP);
127 nPercent = m_nRefValue ? (((nCurrentWidth * 10) / m_nRefValue + 5) / 10) : 0;
128 m_pField->set_value(nPercent, FieldUnit::NONE);
132 sal_Int64 SwPercentField::get_value(FieldUnit eOutUnit)
134 return Convert(m_pField->get_value(FieldUnit::NONE), m_pField->get_unit(), eOutUnit);
137 void SwPercentField::set_min(sal_Int64 nNewMin, FieldUnit eInUnit)
139 if (m_pField->get_unit() != FieldUnit::PERCENT)
140 m_pField->set_min(nNewMin, eInUnit);
141 else
143 if (eInUnit == FieldUnit::NONE)
144 eInUnit = m_eOldUnit;
145 m_nOldMin = Convert(nNewMin, eInUnit, m_eOldUnit);
147 int nPercent = Convert(nNewMin, eInUnit, FieldUnit::PERCENT);
148 m_pField->set_min(std::max(1, nPercent), FieldUnit::NONE);
152 void SwPercentField::set_max(sal_Int64 nNewMax, FieldUnit eInUnit)
154 if (m_pField->get_unit() != FieldUnit::PERCENT)
155 m_pField->set_max(nNewMax, eInUnit);
158 sal_Int64 SwPercentField::NormalizePercent(sal_Int64 nValue)
160 if (m_pField->get_unit() != FieldUnit::PERCENT)
161 nValue = m_pField->normalize(nValue);
162 else
163 nValue = nValue * ImpPower10(m_nOldDigits);
164 return nValue;
167 sal_Int64 SwPercentField::DenormalizePercent(sal_Int64 nValue)
169 if (m_pField->get_unit() != FieldUnit::PERCENT)
170 nValue = m_pField->denormalize(nValue);
171 else
173 int nFactor = ImpPower10(m_nOldDigits);
174 nValue = ((nValue + (nFactor / 2)) / nFactor);
176 return nValue;
179 int SwPercentField::ImpPower10(sal_uInt16 n)
181 int nValue = 1;
183 for (sal_uInt16 i = 0; i < n; ++i)
184 nValue *= 10;
186 return nValue;
189 sal_Int64 SwPercentField::GetRealValue(FieldUnit eOutUnit)
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);
197 sal_Int64 SwPercentField::Convert(sal_Int64 nValue, FieldUnit eInUnit, FieldUnit eOutUnit)
199 if (eInUnit == eOutUnit || (eInUnit == FieldUnit::NONE && eOutUnit == m_pField->get_unit())
200 || (eOutUnit == FieldUnit::NONE && eInUnit == m_pField->get_unit()))
201 return nValue;
203 if (eInUnit == FieldUnit::PERCENT)
205 // Convert to metric
206 sal_Int64 nTwipValue = (m_nRefValue * nValue + 50) / 100;
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);
215 if (eOutUnit == FieldUnit::PERCENT)
217 // Convert to percent
218 sal_Int64 nCurrentWidth;
219 nValue = DenormalizePercent(nValue);
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;
229 return vcl::ConvertValue(nValue, 0, m_nOldDigits, eInUnit, eOutUnit);
231 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */