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 
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)
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 
39 void SwPercentField::SetRefValue(sal_Int64 nValue)
40 {
41  sal_Int64 nRealValue = GetRealValue(m_eOldUnit);
42 
43  m_nRefValue = nValue;
44 
45  if (!m_bLockAutoCalculation && (m_pField->get_unit() == FieldUnit::PERCENT))
46  set_value(nRealValue, m_eOldUnit);
47 }
48 
49 void 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 
109 void 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 
137 void 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 
152 void 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 
158 sal_Int64 SwPercentField::NormalizePercent(sal_Int64 nValue)
159 {
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;
165 }
166 
167 sal_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 
179 int SwPercentField::ImpPower10(sal_uInt16 n)
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 
197 sal_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;
219  nValue = DenormalizePercent(nValue);
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: */
FieldUnit
void ShowPercent(bool bPercent)
Definition: prcntfld.cxx:49
sal_Int64 Convert(sal_Int64 nValue, FieldUnit eInUnit, FieldUnit eOutUnit)
Definition: prcntfld.cxx:197
int m_nOldSpinSize
Definition: prcntfld.hxx:33
void set_min(sal_Int64 nNewMin, FieldUnit eInUnit)
Definition: prcntfld.cxx:137
sal_Int64 m_nOldMax
Definition: prcntfld.hxx:31
sal_Int64 get_value(FieldUnit eOutUnit=FieldUnit::NONE)
Definition: prcntfld.cxx:132
sal_Int64 GetRealValue(FieldUnit eOutUnit)
Definition: prcntfld.cxx:189
std::unique_ptr< weld::MetricSpinButton > m_pField
Definition: prcntfld.hxx:28
SwPercentField(std::unique_ptr< weld::MetricSpinButton > pControl)
Definition: prcntfld.cxx:23
sal_Int64 m_nRefValue
Definition: prcntfld.hxx:30
int i
void SetRefValue(sal_Int64 nValue)
Definition: prcntfld.cxx:39
sal_uInt16 m_nOldDigits
Definition: prcntfld.hxx:37
sal_Int64 m_nLastValue
Definition: prcntfld.hxx:36
void set_max(sal_Int64 nNewMax, FieldUnit eInUnit)
Definition: prcntfld.cxx:152
bool m_bLockAutoCalculation
Definition: prcntfld.hxx:39
void set_value(sal_Int64 nNewValue, FieldUnit eInUnit=FieldUnit::NONE)
Definition: prcntfld.cxx:109
sal_Int64 NormalizePercent(sal_Int64 nValue)
Definition: prcntfld.cxx:158
int m_nOldPageSize
Definition: prcntfld.hxx:34
FieldUnit m_eOldUnit
Definition: prcntfld.hxx:38
sal_Int64 DenormalizePercent(sal_Int64 nValue)
Definition: prcntfld.cxx:167
sal_Int64 ConvertValue(sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, FieldUnit eInUnit, FieldUnit eOutUnit)
sal_Int64 m_nOldMin
Definition: prcntfld.hxx:32
sal_Int64 m_nLastPercent
Definition: prcntfld.hxx:35
sal_Int16 nValue
bool m_bDetectedRangeSegmentation false
static SAL_DLLPRIVATE int ImpPower10(sal_uInt16 n)
Definition: prcntfld.cxx:179