1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
))
29 , m_nOldDigits(m_pField
->get_digits())
30 , m_eOldUnit(FieldUnit::NONE
)
31 , m_bLockAutoCalculation(false)
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
);
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
))
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
)
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
;
85 m_pField
->set_value(m_nLastPercent
, FieldUnit::NONE
);
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
;
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
);
115 // Overwrite output value, do not restore later
116 sal_Int64 nPercent
, nCurrentWidth
;
117 if (eInUnit
== FieldUnit::TWIP
)
120 = vcl::ConvertValue(nNewValue
, 0, m_nOldDigits
, FieldUnit::TWIP
, FieldUnit::TWIP
);
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
);
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
);
163 nValue
= nValue
* ImpPower10(m_nOldDigits
);
167 sal_Int64
SwPercentField::DenormalizePercent(sal_Int64 nValue
)
169 if (m_pField
->get_unit() != FieldUnit::PERCENT
)
170 nValue
= m_pField
->denormalize(nValue
);
173 int nFactor
= ImpPower10(m_nOldDigits
);
174 nValue
= ((nValue
+ (nFactor
/ 2)) / nFactor
);
179 int SwPercentField::ImpPower10(sal_uInt16 n
)
183 for (sal_uInt16 i
= 0; i
< n
; ++i
)
189 sal_Int64
SwPercentField::GetRealValue(FieldUnit eOutUnit
)
191 if (m_pField
->get_unit() != FieldUnit::PERCENT
)
192 return get_value(eOutUnit
);
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()))
203 if (eInUnit
== FieldUnit::PERCENT
)
206 sal_Int64 nTwipValue
= (m_nRefValue
* nValue
+ 50) / 100;
208 if (eOutUnit
== FieldUnit::TWIP
) // Only convert if necessary
209 return NormalizePercent(nTwipValue
);
211 return vcl::ConvertValue(NormalizePercent(nTwipValue
), 0, m_nOldDigits
, FieldUnit::TWIP
,
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
;
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: */