docthemes: Save themes def. to a file when added to ColorSets
[LibreOffice.git] / sw / source / uibase / utlui / prcntfld.cxx
blobe00377de7fb6217f0d6e2ba2691a7c687bef1f46
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 static sal_Int64 UpscaleTwoDecimalPlaces(sal_Int64 nCurrentWidth, int nOldDigits)
51 // tdf#145847 Typically nOldDigits is two so deriving percentage is direct division
52 // by m_nRefValue but it is one for points
53 for (int i = nOldDigits; i < 2; ++i)
54 nCurrentWidth *= 10;
55 return nCurrentWidth;
58 void SwPercentField::ShowPercent(bool bPercent)
60 if ((bPercent && m_pField->get_unit() == FieldUnit::PERCENT)
61 || (!bPercent && m_pField->get_unit() != FieldUnit::PERCENT))
62 return;
64 sal_Int64 nOldValue;
66 if (bPercent)
68 nOldValue = get_value();
70 m_eOldUnit = m_pField->get_unit();
71 m_nOldDigits = m_pField->get_digits();
72 m_pField->get_range(m_nOldMin, m_nOldMax, FieldUnit::NONE);
73 m_pField->get_increments(m_nOldSpinSize, m_nOldPageSize, FieldUnit::NONE);
74 m_pField->set_unit(FieldUnit::PERCENT);
75 m_pField->set_digits(0);
77 sal_Int64 nCurrentWidth
78 = vcl::ConvertValue(m_nOldMin, 0, m_nOldDigits, m_eOldUnit, FieldUnit::TWIP);
79 nCurrentWidth = UpscaleTwoDecimalPlaces(nCurrentWidth, m_nOldDigits);
81 // round to 0.5 percent
82 int nPercent = m_nRefValue ? (((nCurrentWidth * 10) / m_nRefValue + 5) / 10) : 0;
84 m_pField->set_range(std::max(1, nPercent), 100, FieldUnit::NONE);
85 m_pField->set_increments(5, 10, FieldUnit::NONE);
86 if (nOldValue != m_nLastValue)
88 nCurrentWidth
89 = vcl::ConvertValue(nOldValue, 0, m_nOldDigits, m_eOldUnit, FieldUnit::TWIP);
90 nCurrentWidth = UpscaleTwoDecimalPlaces(nCurrentWidth, m_nOldDigits);
91 nPercent = m_nRefValue ? (((nCurrentWidth * 10) / m_nRefValue + 5) / 10) : 0;
92 m_pField->set_value(nPercent, FieldUnit::NONE);
93 m_nLastPercent = nPercent;
94 m_nLastValue = nOldValue;
96 else
97 m_pField->set_value(m_nLastPercent, FieldUnit::NONE);
99 else
101 sal_Int64 nOldPercent = get_value(FieldUnit::PERCENT);
103 nOldValue = Convert(get_value(), m_pField->get_unit(), m_eOldUnit);
105 m_pField->set_unit(m_eOldUnit);
106 m_pField->set_digits(m_nOldDigits);
107 m_pField->set_range(m_nOldMin, m_nOldMax, FieldUnit::NONE);
108 m_pField->set_increments(m_nOldSpinSize, m_nOldPageSize, FieldUnit::NONE);
110 if (nOldPercent != m_nLastPercent)
112 set_value(nOldValue, m_eOldUnit);
113 m_nLastPercent = nOldPercent;
114 m_nLastValue = nOldValue;
116 else
117 set_value(m_nLastValue, m_eOldUnit);
121 void SwPercentField::set_value(sal_Int64 nNewValue, FieldUnit eInUnit)
123 if (m_pField->get_unit() != FieldUnit::PERCENT || eInUnit == FieldUnit::PERCENT)
124 m_pField->set_value(Convert(nNewValue, eInUnit, m_pField->get_unit()), FieldUnit::NONE);
125 else
127 // Overwrite output value, do not restore later
128 sal_Int64 nPercent, nCurrentWidth;
129 if (eInUnit == FieldUnit::TWIP)
131 nCurrentWidth
132 = vcl::ConvertValue(nNewValue, 0, m_nOldDigits, FieldUnit::TWIP, FieldUnit::TWIP);
134 else
136 sal_Int64 nValue = Convert(nNewValue, eInUnit, m_eOldUnit);
137 nCurrentWidth = vcl::ConvertValue(nValue, 0, m_nOldDigits, m_eOldUnit, FieldUnit::TWIP);
139 nCurrentWidth = UpscaleTwoDecimalPlaces(nCurrentWidth, m_nOldDigits);
140 nPercent = m_nRefValue ? (((nCurrentWidth * 10) / m_nRefValue + 5) / 10) : 0;
141 m_pField->set_value(nPercent, FieldUnit::NONE);
145 sal_Int64 SwPercentField::get_value(FieldUnit eOutUnit)
147 return Convert(m_pField->get_value(FieldUnit::NONE), m_pField->get_unit(), eOutUnit);
150 void SwPercentField::set_min(sal_Int64 nNewMin, FieldUnit eInUnit)
152 if (m_pField->get_unit() != FieldUnit::PERCENT)
153 m_pField->set_min(nNewMin, eInUnit);
154 else
156 if (eInUnit == FieldUnit::NONE)
157 eInUnit = m_eOldUnit;
158 m_nOldMin = Convert(nNewMin, eInUnit, m_eOldUnit);
160 int nPercent = Convert(nNewMin, eInUnit, FieldUnit::PERCENT);
161 m_pField->set_min(std::max(1, nPercent), FieldUnit::NONE);
165 void SwPercentField::set_max(sal_Int64 nNewMax, FieldUnit eInUnit)
167 if (m_pField->get_unit() != FieldUnit::PERCENT)
168 m_pField->set_max(nNewMax, eInUnit);
171 sal_Int64 SwPercentField::NormalizePercent(sal_Int64 nValue)
173 if (m_pField->get_unit() != FieldUnit::PERCENT)
174 nValue = m_pField->normalize(nValue);
175 else
176 nValue = nValue * ImpPower10(m_nOldDigits);
177 return nValue;
180 sal_Int64 SwPercentField::DenormalizePercent(sal_Int64 nValue)
182 if (m_pField->get_unit() != FieldUnit::PERCENT)
183 nValue = m_pField->denormalize(nValue);
184 else
186 int nFactor = ImpPower10(m_nOldDigits);
187 nValue = ((nValue + (nFactor / 2)) / nFactor);
189 return nValue;
192 int SwPercentField::ImpPower10(sal_uInt16 n)
194 int nValue = 1;
196 for (sal_uInt16 i = 0; i < n; ++i)
197 nValue *= 10;
199 return nValue;
202 sal_Int64 SwPercentField::GetRealValue(FieldUnit eOutUnit)
204 if (m_pField->get_unit() != FieldUnit::PERCENT)
205 return get_value(eOutUnit);
206 else
207 return Convert(get_value(), m_pField->get_unit(), eOutUnit);
210 sal_Int64 SwPercentField::Convert(sal_Int64 nValue, FieldUnit eInUnit, FieldUnit eOutUnit)
212 if (eInUnit == eOutUnit || (eInUnit == FieldUnit::NONE && eOutUnit == m_pField->get_unit())
213 || (eOutUnit == FieldUnit::NONE && eInUnit == m_pField->get_unit()))
214 return nValue;
216 if (eInUnit == FieldUnit::PERCENT)
218 // Convert to metric
219 sal_Int64 nTwipValue = (m_nRefValue * nValue + 50) / 100;
221 if (eOutUnit == FieldUnit::TWIP) // Only convert if necessary
222 return NormalizePercent(nTwipValue);
223 else
224 return vcl::ConvertValue(NormalizePercent(nTwipValue), 0, m_nOldDigits, FieldUnit::TWIP,
225 eOutUnit);
228 if (eOutUnit == FieldUnit::PERCENT)
230 // Convert to percent
231 sal_Int64 nCurrentWidth;
232 nValue = DenormalizePercent(nValue);
234 if (eInUnit == FieldUnit::TWIP) // Only convert if necessary
235 nCurrentWidth = nValue;
236 else
237 nCurrentWidth = vcl::ConvertValue(nValue, 0, m_nOldDigits, eInUnit, FieldUnit::TWIP);
238 nCurrentWidth = UpscaleTwoDecimalPlaces(nCurrentWidth, m_nOldDigits);
239 // Round to 0.5 percent
240 return m_nRefValue ? (((nCurrentWidth * 1000) / m_nRefValue + 5) / 10) : 0;
243 return vcl::ConvertValue(nValue, 0, m_nOldDigits, eInUnit, eOutUnit);
245 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */