LibreOffice Module vcl (master)  1
field.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 <sal/config.h>
21 
22 #include <string_view>
23 
24 #include <sal/log.hxx>
25 #include <osl/diagnose.h>
26 
27 #include <comphelper/string.hxx>
28 
29 #include <vcl/builder.hxx>
30 #include <vcl/field.hxx>
31 #include <vcl/event.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/settings.hxx>
34 
35 #include <svdata.hxx>
36 
37 #include <i18nutil/unicode.hxx>
38 
39 #include <rtl/math.hxx>
40 
42 #include <boost/property_tree/ptree.hpp>
43 
44 using namespace ::com::sun::star;
45 using namespace ::comphelper;
46 
47 namespace
48 {
49 
50 std::string FieldUnitToString(FieldUnit unit)
51 {
52  switch(unit)
53  {
54  case FieldUnit::NONE:
55  return "";
56 
57  case FieldUnit::MM:
58  return "mm";
59 
60  case FieldUnit::CM:
61  return "cm";
62 
63  case FieldUnit::M:
64  return "m";
65 
66  case FieldUnit::KM:
67  return "km";
68 
69  case FieldUnit::TWIP:
70  return "twip";
71 
72  case FieldUnit::POINT:
73  return "point";
74 
75  case FieldUnit::PICA:
76  return "pica";
77 
78  case FieldUnit::INCH:
79  return "inch";
80 
81  case FieldUnit::FOOT:
82  return "foot";
83 
84  case FieldUnit::MILE:
85  return "mile";
86 
87  case FieldUnit::CHAR:
88  return "char";
89 
90  case FieldUnit::LINE:
91  return "line";
92 
93  case FieldUnit::CUSTOM:
94  return "custom";
95 
96  case FieldUnit::PERCENT:
97  return "percent";
98 
99  case FieldUnit::MM_100TH:
100  return "mm100th";
101 
102  case FieldUnit::PIXEL:
103  return "pixel";
104 
105  case FieldUnit::DEGREE:
106  return "degree";
107 
108  case FieldUnit::SECOND:
109  return "second";
110 
111  case FieldUnit::MILLISECOND:
112  return "millisecond";
113  }
114 
115  return "";
116 }
117 
118 sal_Int64 ImplPower10( sal_uInt16 n )
119 {
120  sal_uInt16 i;
121  sal_Int64 nValue = 1;
122 
123  for ( i=0; i < n; i++ )
124  nValue *= 10;
125 
126  return nValue;
127 }
128 
129 bool ImplNumericProcessKeyInput( const KeyEvent& rKEvt,
130  bool bStrictFormat, bool bThousandSep,
131  const LocaleDataWrapper& rLocaleDataWrapper )
132 {
133  if ( !bStrictFormat )
134  return false;
135  else
136  {
137  sal_Unicode cChar = rKEvt.GetCharCode();
138  sal_uInt16 nGroup = rKEvt.GetKeyCode().GetGroup();
139 
140  return !((nGroup == KEYGROUP_FKEYS) ||
141  (nGroup == KEYGROUP_CURSOR) ||
142  (nGroup == KEYGROUP_MISC) ||
143  ((cChar >= '0') && (cChar <= '9')) ||
144  string::equals(rLocaleDataWrapper.getNumDecimalSep(), cChar) ||
145  (bThousandSep && string::equals(rLocaleDataWrapper.getNumThousandSep(), cChar)) ||
146  string::equals(rLocaleDataWrapper.getNumDecimalSepAlt(), cChar) ||
147  (cChar == '-'));
148  }
149 }
150 
151 bool ImplNumericGetValue( const OUString& rStr, sal_Int64& rValue,
152  sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrapper,
153  bool bCurrency = false )
154 {
155  OUString aStr = rStr;
156  OUStringBuffer aStr1, aStr2, aStrFrac, aStrNum, aStrDenom;
157  bool bNegative = false;
158  bool bFrac = false;
159  sal_Int32 nDecPos, nFracDivPos, nFracNumPos;
160  sal_Int64 nValue;
161 
162  // react on empty string
163  if ( rStr.isEmpty() )
164  return false;
165 
166  // remove leading and trailing spaces
167  aStr = aStr.trim();
168 
169 
170  // find position of decimal point
171  nDecPos = aStr.indexOf( rLocaleDataWrapper.getNumDecimalSep() );
172  if (nDecPos < 0 && !rLocaleDataWrapper.getNumDecimalSepAlt().isEmpty())
173  nDecPos = aStr.indexOf( rLocaleDataWrapper.getNumDecimalSepAlt() );
174  // find position of fraction
175  nFracDivPos = aStr.indexOf( '/' );
176 
177  // parse fractional strings
178  if (nFracDivPos > 0)
179  {
180  bFrac = true;
181  nFracNumPos = aStr.lastIndexOf(' ', nFracDivPos);
182 
183  // If in "a b/c" format.
184  if(nFracNumPos != -1 )
185  {
186  aStr1.append(std::u16string_view(aStr).substr(0, nFracNumPos));
187  aStrNum.append(std::u16string_view(aStr).substr(nFracNumPos+1, nFracDivPos-nFracNumPos-1));
188  aStrDenom.append(std::u16string_view(aStr).substr(nFracDivPos+1));
189  }
190  // "a/b" format, or not a fraction at all
191  else
192  {
193  aStrNum.append(std::u16string_view(aStr).substr(0, nFracDivPos));
194  aStrDenom.append(std::u16string_view(aStr).substr(nFracDivPos+1));
195  }
196 
197  }
198  // parse decimal strings
199  else if ( nDecPos >= 0)
200  {
201  aStr1.append(std::u16string_view(aStr).substr(0, nDecPos));
202  aStr2.append(std::u16string_view(aStr).substr(nDecPos+1));
203  }
204  else
205  aStr1 = aStr;
206 
207  // negative?
208  if ( bCurrency )
209  {
210  if ( aStr.startsWith("(") && aStr.endsWith(")") )
211  bNegative = true;
212  if ( !bNegative )
213  {
214  for (sal_Int32 i=0; i < aStr.getLength(); i++ )
215  {
216  if ( (aStr[i] >= '0') && (aStr[i] <= '9') )
217  break;
218  else if ( aStr[i] == '-' )
219  {
220  bNegative = true;
221  break;
222  }
223  }
224  }
225  if (!bNegative && !aStr.isEmpty())
226  {
227  sal_uInt16 nFormat = rLocaleDataWrapper.getCurrNegativeFormat();
228  if ( (nFormat == 3) || (nFormat == 6) || // $1- || 1-$
229  (nFormat == 7) || (nFormat == 10) ) // 1$- || 1 $-
230  {
231  for (sal_Int32 i = aStr.getLength()-1; i > 0; --i )
232  {
233  if ( (aStr[i] >= '0') && (aStr[i] <= '9') )
234  break;
235  else if ( aStr[i] == '-' )
236  {
237  bNegative = true;
238  break;
239  }
240  }
241  }
242  }
243  }
244  else
245  {
246  if ( !aStr1.isEmpty() && aStr1[0] == '-')
247  bNegative = true;
248  if ( !aStrNum.isEmpty() && aStrNum[0] == '-') // For non-mixed fractions
249  bNegative = true;
250  }
251 
252  // remove all unwanted characters
253  // For whole number
254  for (sal_Int32 i=0; i < aStr1.getLength(); )
255  {
256  if ( (aStr1[i] >= '0') && (aStr1[i] <= '9') )
257  i++;
258  else
259  aStr1.remove( i, 1 );
260  }
261  // For decimal
262  if (!bFrac) {
263  for (sal_Int32 i=0; i < aStr2.getLength(); )
264  {
265  if ((aStr2[i] >= '0') && (aStr2[i] <= '9'))
266  ++i;
267  else
268  aStr2.remove(i, 1);
269  }
270  }
271  else {
272  // for numerator
273  for (sal_Int32 i=0; i < aStrNum.getLength(); )
274  {
275  if ((aStrNum[i] >= '0') && (aStrNum[i] <= '9'))
276  ++i;
277  else
278  aStrNum.remove(i, 1);
279  }
280  // for denominator
281  for (sal_Int32 i=0; i < aStrDenom.getLength(); )
282  {
283  if ((aStrDenom[i] >= '0') && (aStrDenom[i] <= '9'))
284  ++i;
285  else
286  aStrDenom.remove(i, 1);
287  }
288  }
289 
290 
291  if ( !bFrac && aStr1.isEmpty() && aStr2.isEmpty() )
292  return false;
293  else if ( bFrac && aStr1.isEmpty() && (aStrNum.isEmpty() || aStrDenom.isEmpty()) )
294  return false;
295 
296  if ( aStr1.isEmpty() )
297  aStr1 = "0";
298  if ( bNegative )
299  aStr1.insert(0, "-");
300 
301  // Convert fractional strings
302  if (bFrac) {
303  // Convert to fraction
304  sal_Int64 nWholeNum = aStr1.makeStringAndClear().toInt64();
305  sal_Int64 nNum = aStrNum.makeStringAndClear().toInt64();
306  sal_Int64 nDenom = aStrDenom.makeStringAndClear().toInt64();
307  if (nDenom == 0) return false; // Division by zero
308  double nFrac2Dec = nWholeNum + static_cast<double>(nNum)/nDenom; // Convert to double for floating point precision
309  aStrFrac.append(nFrac2Dec);
310  // Reconvert division result to string and parse
311  nDecPos = aStrFrac.indexOf('.');
312  if ( nDecPos >= 0)
313  {
314  aStr1.append(aStrFrac.getStr(), nDecPos);
315  aStr2.append(aStrFrac.getStr()+nDecPos+1);
316  }
317  else
318  aStr1 = aStrFrac;
319  }
320 
321  // prune and round fraction
322  bool bRound = false;
323  if (aStr2.getLength() > nDecDigits)
324  {
325  if (aStr2[nDecDigits] >= '5')
326  bRound = true;
327  string::truncateToLength(aStr2, nDecDigits);
328  }
329  if (aStr2.getLength() < nDecDigits)
330  string::padToLength(aStr2, nDecDigits, '0');
331 
332  aStr = aStr1.makeStringAndClear() + aStr2.makeStringAndClear();
333 
334  // check range
335  nValue = aStr.toInt64();
336  if( nValue == 0 )
337  {
338  // check if string is equivalent to zero
339  sal_Int32 nIndex = bNegative ? 1 : 0;
340  while (nIndex < aStr.getLength() && aStr[nIndex] == '0')
341  ++nIndex;
342  if( nIndex < aStr.getLength() )
343  {
344  rValue = bNegative ? SAL_MIN_INT64 : SAL_MAX_INT64;
345  return true;
346  }
347  }
348  if (bRound)
349  {
350  if ( !bNegative )
351  nValue++;
352  else
353  nValue--;
354  }
355 
356  rValue = nValue;
357 
358  return true;
359 }
360 
361 void ImplUpdateSeparatorString( OUString& io_rText,
362  const OUString& rOldDecSep, const OUString& rNewDecSep,
363  const OUString& rOldThSep, const OUString& rNewThSep )
364 {
365  OUStringBuffer aBuf( io_rText.getLength() );
366  sal_Int32 nIndexDec = 0, nIndexTh = 0, nIndex = 0;
367 
368  const sal_Unicode* pBuffer = io_rText.getStr();
369  while( nIndex != -1 )
370  {
371  nIndexDec = io_rText.indexOf( rOldDecSep, nIndex );
372  nIndexTh = io_rText.indexOf( rOldThSep, nIndex );
373  if( (nIndexTh != -1 && nIndexDec != -1 && nIndexTh < nIndexDec )
374  || (nIndexTh != -1 && nIndexDec == -1)
375  )
376  {
377  aBuf.append( pBuffer + nIndex, nIndexTh - nIndex );
378  aBuf.append( rNewThSep );
379  nIndex = nIndexTh + rOldThSep.getLength();
380  }
381  else if( nIndexDec != -1 )
382  {
383  aBuf.append( pBuffer + nIndex, nIndexDec - nIndex );
384  aBuf.append( rNewDecSep );
385  nIndex = nIndexDec + rOldDecSep.getLength();
386  }
387  else
388  {
389  aBuf.append( pBuffer + nIndex );
390  nIndex = -1;
391  }
392  }
393 
394  io_rText = aBuf.makeStringAndClear();
395 }
396 
397 void ImplUpdateSeparators( const OUString& rOldDecSep, const OUString& rNewDecSep,
398  const OUString& rOldThSep, const OUString& rNewThSep,
399  Edit* pEdit )
400 {
401  bool bChangeDec = (rOldDecSep != rNewDecSep);
402  bool bChangeTh = (rOldThSep != rNewThSep );
403 
404  if( bChangeDec || bChangeTh )
405  {
406  bool bUpdateMode = pEdit->IsUpdateMode();
407  pEdit->SetUpdateMode( false );
408  OUString aText = pEdit->GetText();
409  ImplUpdateSeparatorString( aText, rOldDecSep, rNewDecSep, rOldThSep, rNewThSep );
410  pEdit->SetText( aText );
411 
412  ComboBox* pCombo = dynamic_cast<ComboBox*>(pEdit);
413  if( pCombo )
414  {
415  // update box entries
416  sal_Int32 nEntryCount = pCombo->GetEntryCount();
417  for ( sal_Int32 i=0; i < nEntryCount; i++ )
418  {
419  aText = pCombo->GetEntry( i );
420  void* pEntryData = pCombo->GetEntryData( i );
421  ImplUpdateSeparatorString( aText, rOldDecSep, rNewDecSep, rOldThSep, rNewThSep );
422  pCombo->RemoveEntryAt(i);
423  pCombo->InsertEntry( aText, i );
424  pCombo->SetEntryData( i, pEntryData );
425  }
426  }
427  if( bUpdateMode )
428  pEdit->SetUpdateMode( bUpdateMode );
429  }
430 }
431 
432 } // namespace
433 
435 {
436  mpField = pField;
437  mpLocaleDataWrapper = nullptr;
438  mbReformat = false;
439  mbStrictFormat = false;
440  mbEmptyFieldValue = false;
441  mbEmptyFieldValueEnabled = false;
442 }
443 
445 {
446 }
447 
449 {
450  if ( !mpLocaleDataWrapper )
451  {
452  const_cast<FormatterBase*>(this)->mpLocaleDataWrapper.reset( new LocaleDataWrapper( GetLanguageTag() ) );
453  }
454  return *mpLocaleDataWrapper;
455 }
456 
458 {
459  return ImplGetLocaleDataWrapper();
460 }
461 
463 {
464 }
465 
467 {
468  Reformat();
469 };
470 
471 void FormatterBase::SetStrictFormat( bool bStrict )
472 {
473  if ( bStrict != mbStrictFormat )
474  {
475  mbStrictFormat = bStrict;
476  if ( mbStrictFormat )
477  ReformatAll();
478  }
479 }
480 
481 const lang::Locale& FormatterBase::GetLocale() const
482 {
483  if ( mpField )
485  else
487 }
488 
490 {
491  if ( mpField )
492  return mpField->GetSettings().GetLanguageTag();
493  else
495 }
496 
497 void FormatterBase::ImplSetText( const OUString& rText, Selection const * pNewSelection )
498 {
499  if ( mpField )
500  {
501  if (pNewSelection)
502  mpField->SetText(rText, *pNewSelection);
503  else
504  {
505  Selection aSel = mpField->GetSelection();
506  aSel.Min() = aSel.Max();
507  mpField->SetText(rText, aSel);
508  }
509  MarkToBeReformatted( false );
510  }
511 }
512 
514 {
515  if ( mpField )
516  mpField->SetText( OUString() );
517  mbEmptyFieldValue = true;
518 }
519 
521 {
522  return (!mpField || mpField->GetText().isEmpty());
523 }
524 
525 void NumericFormatter::FormatValue(Selection const * pNewSelection)
526 {
527  mbFormatting = true;
528  ImplSetText(CreateFieldText(mnLastValue), pNewSelection);
529  mbFormatting = false;
530 }
531 
533 {
534  mnLastValue = GetValue();
535  FormatValue();
536 }
537 
539 {
540  mnFieldValue = 0;
541  mnLastValue = 0;
542  mnMin = 0;
544  // a "large" value substantially smaller than SAL_MAX_INT64, to avoid
545  // overflow in computations using this "dummy" value
546  mnDecimalDigits = 2;
547  mbThousandSep = true;
548  mbShowTrailingZeros = true;
549  mbWrapOnLimits = false;
550  mbFormatting = false;
551 
552  // for fields
553  mnSpinSize = 1;
554  mnFirst = mnMin;
555  mnLast = mnMax;
556 
557  SetDecimalDigits( 0 );
558 }
559 
561  : FormatterBase(pEdit)
562 {
563  ImplInit();
564 }
565 
567 {
568 }
569 
570 void NumericFormatter::SetMin( sal_Int64 nNewMin )
571 {
572  mnMin = nNewMin;
573  if ( !IsEmptyFieldValue() )
574  ReformatAll();
575 }
576 
577 void NumericFormatter::SetMax( sal_Int64 nNewMax )
578 {
579  mnMax = nNewMax;
580  if ( !IsEmptyFieldValue() )
581  ReformatAll();
582 }
583 
585 {
586  mbThousandSep = bValue;
587  ReformatAll();
588 }
589 
590 void NumericFormatter::SetDecimalDigits( sal_uInt16 nDigits )
591 {
592  mnDecimalDigits = nDigits;
593  ReformatAll();
594 }
595 
596 void NumericFormatter::SetShowTrailingZeros( bool bShowTrailingZeros )
597 {
598  if ( mbShowTrailingZeros != bShowTrailingZeros )
599  {
600  mbShowTrailingZeros = bShowTrailingZeros;
601  ReformatAll();
602  }
603 }
604 
605 
606 void NumericFormatter::SetValue( sal_Int64 nNewValue )
607 {
608  SetUserValue( nNewValue );
610  SetEmptyFieldValueData( false );
611 }
612 
613 OUString NumericFormatter::CreateFieldText( sal_Int64 nValue ) const
614 {
616 }
617 
618 void NumericFormatter::ImplSetUserValue( sal_Int64 nNewValue, Selection const * pNewSelection )
619 {
620  nNewValue = ClipAgainstMinMax(nNewValue);
621  mnLastValue = nNewValue;
622 
623  if ( GetField() )
624  FormatValue(pNewSelection);
625 }
626 
627 void NumericFormatter::SetUserValue( sal_Int64 nNewValue )
628 {
629  ImplSetUserValue( nNewValue );
630 }
631 
632 sal_Int64 NumericFormatter::GetValueFromString(const OUString& rStr) const
633 {
634  sal_Int64 nTempValue;
635 
636  if (ImplNumericGetValue(rStr, nTempValue,
638  {
639  return ClipAgainstMinMax(nTempValue);
640  }
641  else
642  return mnLastValue;
643 }
644 
645 sal_Int64 NumericFormatter::GetValue() const
646 {
647  if (mbFormatting) //don't parse the entry if we're currently formatting what to put in it
648  return mnLastValue;
649 
650  return GetField() ? GetValueFromString(GetField()->GetText()) : 0;
651 }
652 
654 {
655  if ( ImplGetEmptyFieldValue() )
656  return !IsEmptyFieldValue();
657  else if ( GetValue() != mnFieldValue )
658  return true;
659  else
660  return false;
661 }
662 
663 sal_Int64 NumericFormatter::Normalize( sal_Int64 nValue ) const
664 {
665  return (nValue * ImplPower10( GetDecimalDigits() ) );
666 }
667 
668 sal_Int64 NumericFormatter::Denormalize( sal_Int64 nValue ) const
669 {
670  sal_Int64 nFactor = ImplPower10( GetDecimalDigits() );
671 
672  if ((nValue < ( SAL_MIN_INT64 + nFactor )) ||
673  (nValue > ( SAL_MAX_INT64 - nFactor )))
674  {
675  return ( nValue / nFactor );
676  }
677 
678  if( nValue < 0 )
679  {
680  sal_Int64 nHalf = nFactor / 2;
681  return ((nValue - nHalf) / nFactor );
682  }
683  else
684  {
685  sal_Int64 nHalf = nFactor / 2;
686  return ((nValue + nHalf) / nFactor );
687  }
688 }
689 
691 {
692  if ( !GetField() )
693  return;
694 
695  if ( GetField()->GetText().isEmpty() && ImplGetEmptyFieldValue() )
696  return;
697 
699 }
700 
702 {
703  sal_Int64 nValue = GetValue();
704  sal_Int64 nRemainder = nValue % mnSpinSize;
705  if (nValue >= 0)
706  nValue = (nRemainder == 0) ? nValue + mnSpinSize : nValue + mnSpinSize - nRemainder;
707  else
708  nValue = (nRemainder == 0) ? nValue + mnSpinSize : nValue - nRemainder;
709 
710  nValue = ClipAgainstMinMax(nValue);
711 
712  ImplNewFieldValue( nValue );
713 }
714 
716 {
717  sal_Int64 nValue = GetValue();
718  sal_Int64 nRemainder = nValue % mnSpinSize;
719  if (nValue >= 0)
720  nValue = (nRemainder == 0) ? nValue - mnSpinSize : nValue - nRemainder;
721  else
722  nValue = (nRemainder == 0) ? nValue - mnSpinSize : nValue - mnSpinSize - nRemainder;
723 
724  nValue = ClipAgainstMinMax(nValue);
725 
726  ImplNewFieldValue( nValue );
727 }
728 
730 {
732 }
733 
735 {
737 }
738 
739 void NumericFormatter::ImplNewFieldValue( sal_Int64 nNewValue )
740 {
741  if ( GetField() )
742  {
743  // !!! We should check why we do not validate in ImplSetUserValue() if the value was
744  // changed. This should be done there as well since otherwise the call to Modify would not
745  // be allowed. Anyway, the paths from ImplNewFieldValue, ImplSetUserValue, and ImplSetText
746  // should be checked and clearly traced (with comment) in order to find out what happens.
747 
748  Selection aSelection = GetField()->GetSelection();
749  aSelection.Justify();
750  OUString aText = GetField()->GetText();
751  // leave it as is if selected until end
752  if ( static_cast<sal_Int32>(aSelection.Max()) == aText.getLength() )
753  {
754  if ( !aSelection.Len() )
755  aSelection.Min() = SELECTION_MAX;
756  aSelection.Max() = SELECTION_MAX;
757  }
758 
759  sal_Int64 nOldLastValue = mnLastValue;
760  ImplSetUserValue( nNewValue, &aSelection );
761  mnLastValue = nOldLastValue;
762 
763  // Modify during Edit is only set during KeyInput
764  if ( GetField()->GetText() != aText )
765  {
766  GetField()->SetModifyFlag();
767  GetField()->Modify();
768  }
769  }
770 }
771 
772 sal_Int64 NumericFormatter::ClipAgainstMinMax(sal_Int64 nValue) const
773 {
774  if (nValue > mnMax)
775  nValue = mbWrapOnLimits ? ((nValue - mnMin) % (mnMax + 1)) + mnMin
776  : mnMax;
777  else if (nValue < mnMin)
778  nValue = mbWrapOnLimits ? ((nValue + mnMax + 1 - mnMin) % (mnMax + 1)) + mnMin
779  : mnMin;
780  return nValue;
781 }
782 
784  : SpinField(pParent, nWinStyle)
785  , NumericFormatter(this)
786 {
787  Reformat();
788 }
789 
791 {
792  ClearField();
794 }
795 
796 bool NumericField::set_property(const OString &rKey, const OUString &rValue)
797 {
798  if (rKey == "digits")
799  SetDecimalDigits(rValue.toInt32());
800  else if (rKey == "spin-size")
801  SetSpinSize(rValue.toInt32());
802  else if (rKey == "wrap")
803  mbWrapOnLimits = toBool(rValue);
804  else
805  return SpinField::set_property(rKey, rValue);
806  return true;
807 }
808 
810 {
811  if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
812  {
813  if ( ImplNumericProcessKeyInput( *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
814  return true;
815  }
816 
817  return SpinField::PreNotify( rNEvt );
818 }
819 
821 {
822  if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
823  MarkToBeReformatted( false );
824  else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
825  {
826  if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
827  Reformat();
828  }
829 
830  return SpinField::EventNotify( rNEvt );
831 }
832 
834 {
835  SpinField::DataChanged( rDCEvt );
836 
837  if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
838  {
839  OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
840  OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
842  OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
843  OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
844  ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
845  ReformatAll();
846  }
847 }
848 
850 {
851  MarkToBeReformatted( true );
853 }
854 
856 {
857  FieldUp();
858  SpinField::Up();
859 }
860 
862 {
863  FieldDown();
864  SpinField::Down();
865 }
866 
868 {
869  FieldFirst();
871 }
872 
874 {
875  FieldLast();
876  SpinField::Last();
877 }
878 
879 boost::property_tree::ptree NumericField::DumpAsPropertyTree()
880 {
881  boost::property_tree::ptree aTree(SpinField::DumpAsPropertyTree());
882  aTree.put("min", GetMin());
883  aTree.put("max", GetMax());
884  return aTree;
885 }
886 
887 namespace
888 {
889  Size calcMinimumSize(const Edit &rSpinField, const NumericFormatter &rFormatter)
890  {
891  OUStringBuffer aBuf;
892  sal_Int32 nTextLen;
893 
894  nTextLen = OUString(OUString::number(rFormatter.GetMin())).getLength();
895  string::padToLength(aBuf, nTextLen, '9');
896  Size aMinTextSize = rSpinField.CalcMinimumSizeForText(
897  rFormatter.CreateFieldText(aBuf.toString().toInt64()));
898  aBuf.setLength(0);
899 
900  nTextLen = OUString(OUString::number(rFormatter.GetMax())).getLength();
901  string::padToLength(aBuf, nTextLen, '9');
902  Size aMaxTextSize = rSpinField.CalcMinimumSizeForText(
903  rFormatter.CreateFieldText(aBuf.toString().toInt64()));
904  aBuf.setLength(0);
905 
906  Size aRet(std::max(aMinTextSize.Width(), aMaxTextSize.Width()),
907  std::max(aMinTextSize.Height(), aMaxTextSize.Height()));
908 
909  OUStringBuffer sBuf("999999999");
910  sal_uInt16 nDigits = rFormatter.GetDecimalDigits();
911  if (nDigits)
912  {
913  sBuf.append('.');
914  string::padToLength(aBuf, aBuf.getLength() + nDigits, '9');
915  }
916  aMaxTextSize = rSpinField.CalcMinimumSizeForText(sBuf.makeStringAndClear());
917  aRet.setWidth( std::min(aRet.Width(), aMaxTextSize.Width()) );
918 
919  return aRet;
920  }
921 }
922 
924 {
925  return calcMinimumSize(*this, *this);
926 }
927 
929  : ComboBox(pParent, nWinStyle)
930  , NumericFormatter(this)
931 {
932  Reformat();
933  if ( !(nWinStyle & WB_HIDE ) )
934  Show();
935 }
936 
938 {
939  ClearField();
941 }
942 
944 {
945  Size aRet(calcMinimumSize(*this, *this));
946 
947  if (IsDropDownBox())
948  {
949  Size aComboSugg(ComboBox::CalcMinimumSize());
950  aRet.setWidth( std::max(aRet.Width(), aComboSugg.Width()) );
951  aRet.setHeight( std::max(aRet.Height(), aComboSugg.Height()) );
952  }
953 
954  return aRet;
955 }
956 
958 {
959  if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
960  {
961  if ( ImplNumericProcessKeyInput( *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
962  return true;
963  }
964 
965  return ComboBox::PreNotify( rNEvt );
966 }
967 
969 {
970  if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
971  MarkToBeReformatted( false );
972  else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
973  {
974  if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
975  Reformat();
976  }
977 
978  return ComboBox::EventNotify( rNEvt );
979 }
980 
982 {
983  ComboBox::DataChanged( rDCEvt );
984 
985  if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
986  {
987  OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
988  OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
990  OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
991  OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
992  ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
993  ReformatAll();
994  }
995 }
996 
998 {
999  MarkToBeReformatted( true );
1000  ComboBox::Modify();
1001 }
1002 
1003 void NumericBox::ImplNumericReformat( const OUString& rStr, sal_Int64& rValue,
1004  OUString& rOutStr )
1005 {
1006  if (ImplNumericGetValue(rStr, rValue, GetDecimalDigits(), ImplGetLocaleDataWrapper()))
1007  {
1008  sal_Int64 nTempVal = ClipAgainstMinMax(rValue);
1009  rOutStr = CreateFieldText( nTempVal );
1010  }
1011 }
1012 
1014 {
1015  sal_Int64 nValue;
1016  OUString aStr;
1017  SetUpdateMode( false );
1018  sal_Int32 nEntryCount = GetEntryCount();
1019  for ( sal_Int32 i=0; i < nEntryCount; i++ )
1020  {
1021  ImplNumericReformat( GetEntry( i ), nValue, aStr );
1022  RemoveEntryAt(i);
1023  InsertEntry( aStr, i );
1024  }
1026  SetUpdateMode( true );
1027 }
1028 
1029 void NumericBox::InsertValue( sal_Int64 nValue, sal_Int32 nPos )
1030 {
1031  ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
1032 }
1033 
1034 static bool ImplMetricProcessKeyInput( const KeyEvent& rKEvt,
1035  bool bUseThousandSep, const LocaleDataWrapper& rWrapper )
1036 {
1037  // no meaningful strict format; therefore allow all characters
1038  return ImplNumericProcessKeyInput( rKEvt, false, bUseThousandSep, rWrapper );
1039 }
1040 
1041 static OUString ImplMetricGetUnitText(const OUString& rStr)
1042 {
1043  // fetch unit text
1044  OUStringBuffer aStr;
1045  for (sal_Int32 i = rStr.getLength()-1; i >= 0; --i)
1046  {
1047  sal_Unicode c = rStr[i];
1048  if ( (c == '\'') || (c == '\"') || (c == '%' ) || unicode::isAlpha(c) || unicode::isControl(c) )
1049  aStr.insert(0, c);
1050  else
1051  {
1052  if (!aStr.isEmpty())
1053  break;
1054  }
1055  }
1056  return aStr.makeStringAndClear();
1057 }
1058 
1059 // #104355# support localized measurements
1060 
1061 static OUString ImplMetricToString( FieldUnit rUnit )
1062 {
1063  // return unit's default string (ie, the first one )
1064  for (auto const& elem : ImplGetFieldUnits())
1065  {
1066  if (elem.second == rUnit)
1067  return elem.first;
1068  }
1069 
1070  return OUString();
1071 }
1072 
1073 FieldUnit MetricFormatter::StringToMetric(const OUString &rMetricString)
1074 {
1075  // return FieldUnit
1076  OUString aStr = rMetricString.toAsciiLowerCase().replaceAll(" ", "");
1077  for (auto const& elem : ImplGetCleanedFieldUnits())
1078  {
1079  if ( elem.first == aStr )
1080  return elem.second;
1081  }
1082 
1083  return FieldUnit::NONE;
1084 }
1085 
1086 static FieldUnit ImplMetricGetUnit(const OUString& rStr)
1087 {
1088  OUString aStr = ImplMetricGetUnitText(rStr);
1089  return MetricFormatter::StringToMetric(aStr);
1090 }
1091 
1092 #define K *1000L
1093 #define M *1000000LL
1094 #define X *5280L
1095 
1096 // twip in km = 254 / 14 400 000 000
1097 // expressions too big for default size 32 bit need LL to avoid overflow
1098 
1099 static const sal_Int64 aImplFactor[sal_uInt16(FieldUnit::LINE) + 1]
1100  [sal_uInt16(FieldUnit::LINE) + 1] =
1101 { /*
1102 mm/100 mm cm m km twip point pica inch foot mile char line */
1103 { 1, 100, 1 K, 100 K, 100 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X , 53340, 396240},
1104 { 1, 1, 10, 1 K, 1 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X , 5334, 396240},
1105 { 1, 1, 1, 100, 100 K, 254, 254, 254, 254, 254*12, 254*12 X , 5334, 39624},
1106 { 1, 1, 1, 1, 1 K, 254, 254, 254, 254, 254*12, 254*12 X , 533400, 39624},
1107 { 1, 1, 1, 1, 1, 254, 254, 254, 254, 254*12, 254*12 X ,533400 K, 39624},
1108 { 1440,144 K,144 K,14400 K,14400LL M, 1, 20, 240, 1440,1440*12,1440*12 X , 210, 3120},
1109 { 72, 7200, 7200, 720 K, 720 M, 1, 1, 12, 72, 72*12, 72*12 X , 210, 156},
1110 { 6, 600, 600, 60 K, 60 M, 1, 1, 1, 6, 6*12, 6*12 X , 210, 10},
1111 { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 12, 12 X , 210, 45},
1112 { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 1, 1 X , 210, 45},
1113 { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 1, 1 , 210, 45},
1114 { 144, 1440,14400, 14400, 14400, 1, 20, 240, 1440,1440*12, 1440*12 X, 1, 156 },
1115 { 720,72000,72000, 7200 K,7200LL M, 20, 10, 13, 11, 11*12, 11*12 X, 105, 1 }
1116 };
1117 #undef X
1118 #undef M
1119 #undef K
1120 
1121 static FieldUnit eDefaultUnit = FieldUnit::NONE;
1122 
1124 void MetricField::SetDefaultUnit( FieldUnit meUnit ) { eDefaultUnit = meUnit; }
1125 
1126 static FieldUnit ImplMap2FieldUnit( MapUnit meUnit, long& nDecDigits )
1127 {
1128  switch( meUnit )
1129  {
1130  case MapUnit::Map100thMM :
1131  nDecDigits -= 2;
1132  return FieldUnit::MM;
1133  case MapUnit::Map10thMM :
1134  nDecDigits -= 1;
1135  return FieldUnit::MM;
1136  case MapUnit::MapMM :
1137  return FieldUnit::MM;
1138  case MapUnit::MapCM :
1139  return FieldUnit::CM;
1140  case MapUnit::Map1000thInch :
1141  nDecDigits -= 3;
1142  return FieldUnit::INCH;
1143  case MapUnit::Map100thInch :
1144  nDecDigits -= 2;
1145  return FieldUnit::INCH;
1146  case MapUnit::Map10thInch :
1147  nDecDigits -= 1;
1148  return FieldUnit::INCH;
1149  case MapUnit::MapInch :
1150  return FieldUnit::INCH;
1151  case MapUnit::MapPoint :
1152  return FieldUnit::POINT;
1153  case MapUnit::MapTwip :
1154  return FieldUnit::TWIP;
1155  default:
1156  OSL_FAIL( "default eInUnit" );
1157  break;
1158  }
1159  return FieldUnit::NONE;
1160 }
1161 
1162 static double nonValueDoubleToValueDouble( double nValue )
1163 {
1164  return rtl::math::isFinite( nValue ) ? nValue : 0.0;
1165 }
1166 
1167 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits,
1168  FieldUnit eInUnit, FieldUnit eOutUnit )
1169 {
1171  static_cast<double>(nValue), mnBaseValue, nDecDigits, eInUnit, eOutUnit ) );
1172  sal_Int64 nLong ;
1173 
1174  // caution: precision loss in double cast
1175  if ( nDouble <= double(SAL_MIN_INT64) )
1176  nLong = SAL_MIN_INT64;
1177  else if ( nDouble >= double(SAL_MAX_INT64) )
1178  nLong = SAL_MAX_INT64;
1179  else
1180  nLong = static_cast<sal_Int64>( nDouble );
1181 
1182  return nLong;
1183 }
1184 
1185 namespace {
1186 
1187 bool checkConversionUnits(MapUnit eInUnit, FieldUnit eOutUnit)
1188 {
1189  return eOutUnit != FieldUnit::PERCENT
1190  && eOutUnit != FieldUnit::CUSTOM
1191  && eOutUnit != FieldUnit::NONE
1192  && eInUnit != MapUnit::MapPixel
1193  && eInUnit != MapUnit::MapSysFont
1194  && eInUnit != MapUnit::MapAppFont
1195  && eInUnit != MapUnit::MapRelative;
1196 }
1197 
1198 double convertValue( double nValue, long nDigits, FieldUnit eInUnit, FieldUnit eOutUnit )
1199 {
1200  if ( nDigits < 0 )
1201  {
1202  while ( nDigits )
1203  {
1204  nValue += 5;
1205  nValue /= 10;
1206  nDigits++;
1207  }
1208  }
1209  else
1210  {
1211  nValue *= ImplPower10(nDigits);
1212  }
1213 
1214  if ( eInUnit != eOutUnit )
1215  {
1216  sal_Int64 nDiv = aImplFactor[sal_uInt16(eInUnit)][sal_uInt16(eOutUnit)];
1217  sal_Int64 nMult = aImplFactor[sal_uInt16(eOutUnit)][sal_uInt16(eInUnit)];
1218 
1219  SAL_WARN_IF( nMult <= 0, "vcl", "illegal *" );
1220  SAL_WARN_IF( nDiv <= 0, "vcl", "illegal /" );
1221 
1222  if ( nMult != 1 && nMult > 0)
1223  nValue *= nMult;
1224  if ( nDiv != 1 && nDiv > 0 )
1225  {
1226  nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2);
1227  nValue /= nDiv;
1228  }
1229  }
1230  return nValue;
1231 }
1232 
1233 }
1234 
1235 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_uInt16 nDigits,
1236  MapUnit eInUnit, FieldUnit eOutUnit )
1237 {
1238  if ( !checkConversionUnits(eInUnit, eOutUnit) )
1239  {
1240  OSL_FAIL( "invalid parameters" );
1241  return nValue;
1242  }
1243 
1244  long nDecDigits = nDigits;
1245  FieldUnit eFieldUnit = ImplMap2FieldUnit( eInUnit, nDecDigits );
1246 
1247  // Avoid sal_Int64 <-> double conversion issues if possible:
1248  if (eFieldUnit == eOutUnit && nDigits == 0)
1249  {
1250  return nValue;
1251  }
1252 
1253  return static_cast<sal_Int64>(
1255  convertValue( nValue, nDecDigits, eFieldUnit, eOutUnit ) ) );
1256 }
1257 
1258 double MetricField::ConvertDoubleValue( double nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits,
1259  FieldUnit eInUnit, FieldUnit eOutUnit )
1260 {
1261  if ( eInUnit != eOutUnit )
1262  {
1263  sal_Int64 nMult = 1, nDiv = 1;
1264 
1265  if (eInUnit == FieldUnit::PERCENT)
1266  {
1267  if ( (mnBaseValue <= 0) || (nValue <= 0) )
1268  return nValue;
1269  nDiv = 100 * ImplPower10(nDecDigits);
1270 
1271  nMult = mnBaseValue;
1272  }
1273  else if ( eOutUnit == FieldUnit::PERCENT ||
1274  eOutUnit == FieldUnit::CUSTOM ||
1275  eOutUnit == FieldUnit::NONE ||
1276  eOutUnit == FieldUnit::DEGREE ||
1277  eOutUnit == FieldUnit::SECOND ||
1278  eOutUnit == FieldUnit::MILLISECOND ||
1279  eOutUnit == FieldUnit::PIXEL ||
1280  eInUnit == FieldUnit::CUSTOM ||
1281  eInUnit == FieldUnit::NONE ||
1282  eInUnit == FieldUnit::DEGREE ||
1283  eInUnit == FieldUnit::MILLISECOND ||
1284  eInUnit == FieldUnit::PIXEL )
1285  return nValue;
1286  else
1287  {
1288  if (eOutUnit == FieldUnit::MM_100TH)
1289  eOutUnit = FieldUnit::NONE;
1290  if (eInUnit == FieldUnit::MM_100TH)
1291  eInUnit = FieldUnit::NONE;
1292 
1293  nDiv = aImplFactor[sal_uInt16(eInUnit)][sal_uInt16(eOutUnit)];
1294  nMult = aImplFactor[sal_uInt16(eOutUnit)][sal_uInt16(eInUnit)];
1295 
1296  SAL_WARN_IF( nMult <= 0, "vcl", "illegal *" );
1297  SAL_WARN_IF( nDiv <= 0, "vcl", "illegal /" );
1298  }
1299 
1300  if ( nMult != 1 && nMult > 0 )
1301  nValue *= nMult;
1302  if ( nDiv != 1 && nDiv > 0 )
1303  {
1304  nValue += ( nValue < 0 ) ? (-nDiv/2) : (nDiv/2);
1305  nValue /= nDiv;
1306  }
1307  }
1308 
1309  return nValue;
1310 }
1311 
1312 double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits,
1313  MapUnit eInUnit, FieldUnit eOutUnit )
1314 {
1315  if ( !checkConversionUnits(eInUnit, eOutUnit) )
1316  {
1317  OSL_FAIL( "invalid parameters" );
1318  return nValue;
1319  }
1320 
1321  long nDecDigits = nDigits;
1322  FieldUnit eFieldUnit = ImplMap2FieldUnit( eInUnit, nDecDigits );
1323 
1324  return convertValue(nValue, nDecDigits, eFieldUnit, eOutUnit);
1325 }
1326 
1327 double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits,
1328  FieldUnit eInUnit, MapUnit eOutUnit )
1329 {
1330  if ( eInUnit == FieldUnit::PERCENT ||
1331  eInUnit == FieldUnit::CUSTOM ||
1332  eInUnit == FieldUnit::NONE ||
1333  eInUnit == FieldUnit::DEGREE ||
1334  eInUnit == FieldUnit::SECOND ||
1335  eInUnit == FieldUnit::MILLISECOND ||
1336  eInUnit == FieldUnit::PIXEL ||
1337  eOutUnit == MapUnit::MapPixel ||
1338  eOutUnit == MapUnit::MapSysFont ||
1339  eOutUnit == MapUnit::MapAppFont ||
1340  eOutUnit == MapUnit::MapRelative )
1341  {
1342  OSL_FAIL( "invalid parameters" );
1343  return nValue;
1344  }
1345 
1346  long nDecDigits = nDigits;
1347  FieldUnit eFieldUnit = ImplMap2FieldUnit( eOutUnit, nDecDigits );
1348 
1349  if ( nDecDigits < 0 )
1350  {
1351  nValue *= ImplPower10(-nDecDigits);
1352  }
1353  else
1354  {
1355  nValue /= ImplPower10(nDecDigits);
1356  }
1357 
1358  if ( eFieldUnit != eInUnit )
1359  {
1360  sal_Int64 nDiv = aImplFactor[sal_uInt16(eInUnit)][sal_uInt16(eFieldUnit)];
1361  sal_Int64 nMult = aImplFactor[sal_uInt16(eFieldUnit)][sal_uInt16(eInUnit)];
1362 
1363  SAL_WARN_IF( nMult <= 0, "vcl", "illegal *" );
1364  SAL_WARN_IF( nDiv <= 0, "vcl", "illegal /" );
1365 
1366  if( nMult != 1 && nMult > 0 )
1367  nValue *= nMult;
1368  if( nDiv != 1 && nDiv > 0 )
1369  {
1370  nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2);
1371  nValue /= nDiv;
1372  }
1373  }
1374  return nValue;
1375 }
1376 
1377 bool MetricFormatter::TextToValue(const OUString& rStr, double& rValue, sal_Int64 nBaseValue,
1378  sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrapper, FieldUnit eUnit)
1379 {
1380  // Get value
1381  sal_Int64 nValue;
1382  if ( !ImplNumericGetValue( rStr, nValue, nDecDigits, rLocaleDataWrapper ) )
1383  return false;
1384 
1385  // Determine unit
1386  FieldUnit eEntryUnit = ImplMetricGetUnit( rStr );
1387 
1388  // Recalculate unit
1389  // caution: conversion to double loses precision
1390  rValue = MetricField::ConvertDoubleValue( static_cast<double>(nValue), nBaseValue, nDecDigits, eEntryUnit, eUnit );
1391 
1392  return true;
1393 }
1394 
1395 void MetricFormatter::ImplMetricReformat( const OUString& rStr, double& rValue, OUString& rOutStr )
1396 {
1398  return;
1399 
1400  double nTempVal = rValue;
1401  // caution: precision loss in double cast
1402  if ( nTempVal > GetMax() )
1403  nTempVal = static_cast<double>(GetMax());
1404  else if ( nTempVal < GetMin())
1405  nTempVal = static_cast<double>(GetMin());
1406  rOutStr = CreateFieldText( static_cast<sal_Int64>(nTempVal) );
1407 }
1408 
1410 {
1411  mnBaseValue = 0;
1413 }
1414 
1416  : NumericFormatter(pEdit)
1417 {
1418  ImplInit();
1419 }
1420 
1422 {
1423 }
1424 
1426 {
1427  if (eNewUnit == FieldUnit::MM_100TH)
1428  {
1430  meUnit = FieldUnit::MM;
1431  }
1432  else
1433  meUnit = eNewUnit;
1434  ReformatAll();
1435 }
1436 
1437 void MetricFormatter::SetCustomUnitText( const OUString& rStr )
1438 {
1439  maCustomUnitText = rStr;
1440  ReformatAll();
1441 }
1442 
1443 void MetricFormatter::SetValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1444 {
1445  SetUserValue( nNewValue, eInUnit );
1447 }
1448 
1449 OUString MetricFormatter::CreateFieldText( sal_Int64 nValue ) const
1450 {
1451  //whether percent is separated from its number is locale
1452  //specific, pawn it off to icu to decide
1453  if (meUnit == FieldUnit::PERCENT)
1454  {
1455  double dValue = nValue;
1456  dValue /= ImplPower10(GetDecimalDigits());
1457  return unicode::formatPercent(dValue, GetLanguageTag());
1458  }
1459 
1460  OUString aStr = NumericFormatter::CreateFieldText( nValue );
1461 
1462  if( meUnit == FieldUnit::CUSTOM )
1463  aStr += maCustomUnitText;
1464  else
1465  {
1466  OUString aSuffix = ImplMetricToString( meUnit );
1467  if (meUnit != FieldUnit::NONE && meUnit != FieldUnit::DEGREE && meUnit != FieldUnit::INCH)
1468  aStr += " ";
1469  if (meUnit == FieldUnit::INCH)
1470  {
1471  OUString sDoublePrime = u"\u2033";
1472  if (aSuffix != "\"" && aSuffix != sDoublePrime)
1473  aStr += " ";
1474  else
1475  aSuffix = sDoublePrime;
1476  }
1477  assert(meUnit != FieldUnit::PERCENT);
1478  aStr += aSuffix;
1479  }
1480  return aStr;
1481 }
1482 
1483 void MetricFormatter::SetUserValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1484 {
1485  // convert to previously configured units
1486  nNewValue = MetricField::ConvertValue( nNewValue, mnBaseValue, GetDecimalDigits(), eInUnit, meUnit );
1487  NumericFormatter::SetUserValue( nNewValue );
1488 }
1489 
1490 sal_Int64 MetricFormatter::GetValueFromStringUnit(const OUString& rStr, FieldUnit eOutUnit) const
1491 {
1492  double nTempValue;
1493  // caution: precision loss in double cast
1495  nTempValue = static_cast<double>(mnLastValue);
1496 
1497  // caution: precision loss in double cast
1498  if (nTempValue > mnMax)
1499  nTempValue = static_cast<double>(mnMax);
1500  else if (nTempValue < mnMin)
1501  nTempValue = static_cast<double>(mnMin);
1502 
1503  // convert to requested units
1504  return MetricField::ConvertValue(static_cast<sal_Int64>(nTempValue), mnBaseValue, GetDecimalDigits(), meUnit, eOutUnit);
1505 }
1506 
1507 sal_Int64 MetricFormatter::GetValueFromString(const OUString& rStr) const
1508 {
1509  return GetValueFromStringUnit(rStr, FieldUnit::NONE);
1510 }
1511 
1512 sal_Int64 MetricFormatter::GetValue( FieldUnit eOutUnit ) const
1513 {
1514  return GetField() ? GetValueFromStringUnit(GetField()->GetText(), eOutUnit) : 0;
1515 }
1516 
1517 void MetricFormatter::SetValue( sal_Int64 nValue )
1518 {
1519  // Implementation not inline, because it is a virtual Function
1520  SetValue( nValue, FieldUnit::NONE );
1521 }
1522 
1523 void MetricFormatter::SetMin( sal_Int64 nNewMin, FieldUnit eInUnit )
1524 {
1525  // convert to requested units
1527  eInUnit, meUnit ) );
1528 }
1529 
1530 sal_Int64 MetricFormatter::GetMin( FieldUnit eOutUnit ) const
1531 {
1532  // convert to requested units
1534  GetDecimalDigits(), meUnit, eOutUnit );
1535 }
1536 
1537 void MetricFormatter::SetMax( sal_Int64 nNewMax, FieldUnit eInUnit )
1538 {
1539  // convert to requested units
1541  eInUnit, meUnit ) );
1542 }
1543 
1544 sal_Int64 MetricFormatter::GetMax( FieldUnit eOutUnit ) const
1545 {
1546  // convert to requested units
1548  GetDecimalDigits(), meUnit, eOutUnit );
1549 }
1550 
1551 void MetricFormatter::SetBaseValue( sal_Int64 nNewBase, FieldUnit eInUnit )
1552 {
1554  eInUnit, meUnit );
1555 }
1556 
1558 {
1559  // convert to requested units
1561  meUnit, FieldUnit::NONE );
1562 }
1563 
1565 {
1566  if ( !GetField() )
1567  return;
1568 
1569  OUString aText = GetField()->GetText();
1570  if ( meUnit == FieldUnit::CUSTOM )
1572 
1573  OUString aStr;
1574  // caution: precision loss in double cast
1575  double nTemp = static_cast<double>(mnLastValue);
1576  ImplMetricReformat( aText, nTemp, aStr );
1577  mnLastValue = static_cast<sal_Int64>(nTemp);
1578 
1579  if ( !aStr.isEmpty() )
1580  {
1581  ImplSetText( aStr );
1582  if ( meUnit == FieldUnit::CUSTOM )
1583  CustomConvert();
1584  }
1585  else
1586  SetValue( mnLastValue );
1587  maCurUnitText.clear();
1588 }
1589 
1591 {
1592  // convert to requested units
1593  return MetricField::ConvertValue( 0/*nCorrectedValue*/, mnBaseValue, GetDecimalDigits(),
1594  meUnit, eOutUnit );
1595 }
1596 
1598  : SpinField(pParent, nWinStyle)
1599  , MetricFormatter(this)
1600 {
1601  Reformat();
1602 }
1603 
1605 {
1606  ClearField();
1608 }
1609 
1611 {
1612  return calcMinimumSize(*this, *this);
1613 }
1614 
1615 bool MetricField::set_property(const OString &rKey, const OUString &rValue)
1616 {
1617  if (rKey == "digits")
1618  SetDecimalDigits(rValue.toInt32());
1619  else if (rKey == "spin-size")
1620  SetSpinSize(rValue.toInt32());
1621  else
1622  return SpinField::set_property(rKey, rValue);
1623  return true;
1624 }
1625 
1627 {
1628  sal_Int64 nRawMax = GetMax( nNewUnit );
1629  sal_Int64 nMax = Denormalize( nRawMax );
1630  sal_Int64 nMin = Denormalize( GetMin( nNewUnit ) );
1631  sal_Int64 nFirst = Denormalize( GetFirst( nNewUnit ) );
1632  sal_Int64 nLast = Denormalize( GetLast( nNewUnit ) );
1633 
1634  MetricFormatter::SetUnit( nNewUnit );
1635 
1636  SetMax( Normalize( nMax ), nNewUnit );
1637  SetMin( Normalize( nMin ), nNewUnit );
1638  SetFirst( Normalize( nFirst ), nNewUnit );
1639  SetLast( Normalize( nLast ), nNewUnit );
1640 }
1641 
1642 void MetricField::SetFirst( sal_Int64 nNewFirst, FieldUnit eInUnit )
1643 {
1644  // convert
1645  nNewFirst = MetricField::ConvertValue( nNewFirst, mnBaseValue, GetDecimalDigits(),
1646  eInUnit, meUnit );
1647  mnFirst = nNewFirst;
1648 }
1649 
1650 sal_Int64 MetricField::GetFirst( FieldUnit eOutUnit ) const
1651 {
1652  // convert
1654  meUnit, eOutUnit );
1655 }
1656 
1657 void MetricField::SetLast( sal_Int64 nNewLast, FieldUnit eInUnit )
1658 {
1659  // convert
1660  nNewLast = MetricField::ConvertValue( nNewLast, mnBaseValue, GetDecimalDigits(),
1661  eInUnit, meUnit );
1662  mnLast = nNewLast;
1663 }
1664 
1665 sal_Int64 MetricField::GetLast( FieldUnit eOutUnit ) const
1666 {
1667  // convert
1669  meUnit, eOutUnit );
1670 }
1671 
1673 {
1674  if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1675  {
1677  return true;
1678  }
1679 
1680  return SpinField::PreNotify( rNEvt );
1681 }
1682 
1684 {
1685  if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
1686  MarkToBeReformatted( false );
1687  else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
1688  {
1689  if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
1690  Reformat();
1691  }
1692 
1693  return SpinField::EventNotify( rNEvt );
1694 }
1695 
1697 {
1698  SpinField::DataChanged( rDCEvt );
1699 
1700  if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
1701  {
1702  OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1703  OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1705  OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1706  OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1707  ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1708  ReformatAll();
1709  }
1710 }
1711 
1713 {
1714  MarkToBeReformatted( true );
1716 }
1717 
1719 {
1720  FieldUp();
1721  SpinField::Up();
1722 }
1723 
1725 {
1726  FieldDown();
1727  SpinField::Down();
1728 }
1729 
1731 {
1732  FieldFirst();
1733  SpinField::First();
1734 }
1735 
1737 {
1738  FieldLast();
1739  SpinField::Last();
1740 }
1741 
1743 {
1744  maCustomConvertLink.Call( *this );
1745 }
1746 
1747 boost::property_tree::ptree MetricField::DumpAsPropertyTree()
1748 {
1749  boost::property_tree::ptree aTree(SpinField::DumpAsPropertyTree());
1750  aTree.put("min", GetMin());
1751  aTree.put("max", GetMax());
1752  aTree.put("unit", FieldUnitToString(GetUnit()));
1753  return aTree;
1754 }
1755 
1757  : ComboBox(pParent, nWinStyle)
1758  , MetricFormatter(this)
1759 {
1760  Reformat();
1761 }
1762 
1764 {
1765  ClearField();
1767 }
1768 
1770 {
1771  Size aRet(calcMinimumSize(*this, *this));
1772 
1773  if (IsDropDownBox())
1774  {
1775  Size aComboSugg(ComboBox::CalcMinimumSize());
1776  aRet.setWidth( std::max(aRet.Width(), aComboSugg.Width()) );
1777  aRet.setHeight( std::max(aRet.Height(), aComboSugg.Height()) );
1778  }
1779 
1780  return aRet;
1781 }
1782 
1784 {
1785  if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1786  {
1788  return true;
1789  }
1790 
1791  return ComboBox::PreNotify( rNEvt );
1792 }
1793 
1795 {
1796  if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
1797  MarkToBeReformatted( false );
1798  else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
1799  {
1800  if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
1801  Reformat();
1802  }
1803 
1804  return ComboBox::EventNotify( rNEvt );
1805 }
1806 
1808 {
1809  ComboBox::DataChanged( rDCEvt );
1810 
1811  if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
1812  {
1813  OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1814  OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1816  OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1817  OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1818  ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1819  ReformatAll();
1820  }
1821 }
1822 
1824 {
1825  MarkToBeReformatted( true );
1826  ComboBox::Modify();
1827 }
1828 
1830 {
1831  double nValue;
1832  OUString aStr;
1833  SetUpdateMode( false );
1834  sal_Int32 nEntryCount = GetEntryCount();
1835  for ( sal_Int32 i=0; i < nEntryCount; i++ )
1836  {
1837  ImplMetricReformat( GetEntry( i ), nValue, aStr );
1838  RemoveEntryAt(i);
1839  InsertEntry( aStr, i );
1840  }
1842  SetUpdateMode( true );
1843 }
1844 
1846 {
1847  maCustomConvertLink.Call( *this );
1848 }
1849 
1850 void MetricBox::InsertValue( sal_Int64 nValue, FieldUnit eInUnit, sal_Int32 nPos )
1851 {
1852  // convert to previously configured units
1854  eInUnit, meUnit );
1855  ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
1856 }
1857 
1858 static bool ImplCurrencyProcessKeyInput( const KeyEvent& rKEvt,
1859  bool bUseThousandSep, const LocaleDataWrapper& rWrapper )
1860 {
1861  // no strict format set; therefore allow all characters
1862  return ImplNumericProcessKeyInput( rKEvt, false, bUseThousandSep, rWrapper );
1863 }
1864 
1865 static bool ImplCurrencyGetValue( const OUString& rStr, sal_Int64& rValue,
1866  sal_uInt16 nDecDigits, const LocaleDataWrapper& rWrapper )
1867 {
1868  // fetch number
1869  return ImplNumericGetValue( rStr, rValue, nDecDigits, rWrapper, true );
1870 }
1871 
1872 void CurrencyFormatter::ImplCurrencyReformat( const OUString& rStr, OUString& rOutStr )
1873 {
1874  sal_Int64 nValue;
1875  if ( !ImplNumericGetValue( rStr, nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), true ) )
1876  return;
1877 
1878  sal_Int64 nTempVal = nValue;
1879  if ( nTempVal > GetMax() )
1880  nTempVal = GetMax();
1881  else if ( nTempVal < GetMin())
1882  nTempVal = GetMin();
1883  rOutStr = CreateFieldText( nTempVal );
1884 }
1885 
1887  : NumericFormatter(pField)
1888 {
1889 }
1890 
1892 {
1893 }
1894 
1895 void CurrencyFormatter::SetValue( sal_Int64 nNewValue )
1896 {
1897  SetUserValue( nNewValue );
1899  SetEmptyFieldValueData( false );
1900 }
1901 
1902 OUString CurrencyFormatter::CreateFieldText( sal_Int64 nValue ) const
1903 {
1905  ImplGetLocaleDataWrapper().getCurrSymbol(),
1906  IsUseThousandSep() );
1907 }
1908 
1909 sal_Int64 CurrencyFormatter::GetValueFromString(const OUString& rStr) const
1910 {
1911  sal_Int64 nTempValue;
1912  if ( ImplCurrencyGetValue( rStr, nTempValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
1913  {
1914  return ClipAgainstMinMax(nTempValue);
1915  }
1916  else
1917  return mnLastValue;
1918 }
1919 
1921 {
1922  if ( !GetField() )
1923  return;
1924 
1925  OUString aStr;
1926  ImplCurrencyReformat( GetField()->GetText(), aStr );
1927 
1928  if ( !aStr.isEmpty() )
1929  {
1930  ImplSetText( aStr );
1931  sal_Int64 nTemp = mnLastValue;
1933  mnLastValue = nTemp;
1934  }
1935  else
1936  SetValue( mnLastValue );
1937 }
1938 
1940  : SpinField(pParent, nWinStyle)
1941  , CurrencyFormatter(this)
1942 {
1943  Reformat();
1944 }
1945 
1947 {
1948  ClearField();
1950 }
1951 
1953 {
1954  if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1955  {
1957  return true;
1958  }
1959 
1960  return SpinField::PreNotify( rNEvt );
1961 }
1962 
1964 {
1965  if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
1966  MarkToBeReformatted( false );
1967  else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
1968  {
1969  if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
1970  Reformat();
1971  }
1972 
1973  return SpinField::EventNotify( rNEvt );
1974 }
1975 
1977 {
1978  SpinField::DataChanged( rDCEvt );
1979 
1980  if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
1981  {
1982  OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1983  OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1985  OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1986  OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1987  ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1988  ReformatAll();
1989  }
1990 }
1991 
1993 {
1994  MarkToBeReformatted( true );
1996 }
1997 
1999 {
2000  FieldUp();
2001  SpinField::Up();
2002 }
2003 
2005 {
2006  FieldDown();
2007  SpinField::Down();
2008 }
2009 
2011 {
2012  FieldFirst();
2013  SpinField::First();
2014 }
2015 
2017 {
2018  FieldLast();
2019  SpinField::Last();
2020 }
2021 
2023  : ComboBox(pParent, nWinStyle)
2024  , CurrencyFormatter(this)
2025 {
2026  Reformat();
2027 }
2028 
2030 {
2031  ClearField();
2033 }
2034 
2036 {
2037  if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2038  {
2040  return true;
2041  }
2042 
2043  return ComboBox::PreNotify( rNEvt );
2044 }
2045 
2047 {
2048  if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
2049  MarkToBeReformatted( false );
2050  else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
2051  {
2052  if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
2053  Reformat();
2054  }
2055 
2056  return ComboBox::EventNotify( rNEvt );
2057 }
2058 
2060 {
2061  ComboBox::DataChanged( rDCEvt );
2062 
2063  if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
2064  {
2065  OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2066  OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2068  OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2069  OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2070  ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
2071  ReformatAll();
2072  }
2073 }
2074 
2076 {
2077  MarkToBeReformatted( true );
2078  ComboBox::Modify();
2079 }
2080 
2082 {
2083  OUString aStr;
2084  SetUpdateMode( false );
2085  sal_Int32 nEntryCount = GetEntryCount();
2086  for ( sal_Int32 i=0; i < nEntryCount; i++ )
2087  {
2088  ImplCurrencyReformat( GetEntry( i ), aStr );
2089  RemoveEntryAt(i);
2090  InsertEntry( aStr, i );
2091  }
2093  SetUpdateMode( true );
2094 }
2095 
2096 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Width() const
virtual void SetValue(sal_Int64 nNewValue) override
Definition: field.cxx:1895
sal_uInt16 getCurrNegativeFormat() const
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1783
void InsertValue(sal_Int64 nValue, sal_Int32 nPos=COMBOBOX_APPEND)
Definition: field.cxx:1029
void FieldLast()
Definition: field.cxx:734
virtual bool set_property(const OString &rKey, const OUString &rValue) override
Definition: field.cxx:1615
sal_Int64 GetFirst() const
Definition: field.hxx:133
FieldUnit
Link< MetricFormatter &, void > maCustomConvertLink
Definition: field.hxx:237
#define KEYGROUP_CURSOR
Definition: keycodes.hxx:40
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: field.cxx:1946
virtual boost::property_tree::ptree DumpAsPropertyTree() override
Dumps itself and potentially its children to a property tree, to be written easily to JSON...
Definition: field.cxx:879
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: field.cxx:937
const FieldUnitStringList & ImplGetCleanedFieldUnits()
Definition: svdata.cxx:279
#define SAL_MIN_INT64
virtual void Reformat() override
Definition: field.cxx:1564
void SetShowTrailingZeros(bool bShowTrailingZeros)
Definition: field.cxx:596
void SetMax(sal_Int64 nNewMax)
Definition: field.cxx:577
bool mbFormatting
Definition: field.hxx:163
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:2046
static FieldUnit eDefaultUnit
Definition: field.cxx:1121
long Height() const
virtual void ReformatAll() override
Definition: field.cxx:1013
virtual sal_Int64 GetValueFromString(const OUString &rStr) const override
Definition: field.cxx:1507
virtual void CustomConvert()=0
void SetMin(sal_Int64 nNewMin, FieldUnit eInUnit)
Definition: field.cxx:1523
virtual Size CalcMinimumSizeForText(const OUString &rString) const
Definition: edit.cxx:2619
void SetFirst(sal_Int64 nNewFirst, FieldUnit eInUnit)
Definition: field.cxx:1642
static const AllSettings & GetSettings()
Gets the application's settings.
Definition: svapp.cxx:704
bool mbThousandSep
Definition: field.hxx:189
OUString maCurUnitText
Definition: field.hxx:250
static OUString ImplMetricToString(FieldUnit rUnit)
Definition: field.cxx:1061
virtual OUString CreateFieldText(sal_Int64 nValue) const
Definition: field.cxx:613
#define KEYGROUP_FKEYS
Definition: keycodes.hxx:39
virtual void Last() override
Definition: field.cxx:1736
aBuf
static const sal_Int64 aImplFactor[sal_uInt16(FieldUnit::LINE)+1][sal_uInt16(FieldUnit::LINE)+1]
Definition: field.cxx:1100
virtual void Modify() override
Definition: field.cxx:1823
virtual OUString CreateFieldText(sal_Int64 nValue) const override
Definition: field.cxx:1902
NumericField(vcl::Window *pParent, WinBits nWinStyle)
Definition: field.cxx:783
void SetEmptyFieldValue()
Definition: field.cxx:513
sal_uInt16 GetGroup() const
Definition: keycod.hxx:66
long Len() const
sal_Int64 mnFieldValue
Definition: field.hxx:158
DataChangedEventType GetType() const
Definition: event.hxx:348
const KeyEvent * GetKeyEvent() const
Definition: event.hxx:302
void SetMax(sal_Int64 nNewMax, FieldUnit eInUnit)
Definition: field.cxx:1537
sal_Int64 mnLastValue
Definition: field.hxx:159
virtual void SetUnit(FieldUnit meUnit)
Definition: field.cxx:1425
bool IsEmptyFieldValueEnabled() const
Definition: field.hxx:83
virtual bool set_property(const OString &rKey, const OUString &rValue) override
Definition: edit.cxx:176
virtual void Up()
Definition: spinfld.cxx:359
std::unique_ptr< LocaleDataWrapper > mpLocaleDataWrapper
Definition: field.hxx:44
static bool ImplMetricProcessKeyInput(const KeyEvent &rKEvt, bool bUseThousandSep, const LocaleDataWrapper &rWrapper)
Definition: field.cxx:1034
virtual void Down() override
Definition: field.cxx:861
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1794
sal_Int64 GetValue() const
Definition: field.cxx:645
virtual void First() override
Definition: field.cxx:2010
bool mbEmptyFieldValueEnabled
Definition: field.hxx:48
void SetStrictFormat(bool bStrict)
Definition: field.cxx:471
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:809
void SetBaseValue(sal_Int64 nNewBase, FieldUnit eInUnit=FieldUnit::NONE)
Definition: field.cxx:1551
bool IsValueModified() const
Definition: field.cxx:653
bool MustBeReformatted() const
Definition: field.hxx:67
const css::lang::Locale & getLocale(bool bResolveSystem=true) const
SAL_DLLPRIVATE void ImplSetUserValue(sal_Int64 nNewValue, Selection const *pNewSelection=nullptr)
Definition: field.cxx:618
void ClearField()
Definition: field.hxx:59
virtual bool set_property(const OString &rKey, const OUString &rValue) override
Definition: field.cxx:796
static FieldUnit GetDefaultUnit()
Definition: field.cxx:1123
void SetSpinSize(sal_Int64 nNewSize)
Definition: field.hxx:136
void SetMin(sal_Int64 nNewMin)
Definition: field.cxx:570
void SetEntryData(sal_Int32 nPos, void *pNewData)
Definition: combobox.cxx:1312
OUString GetEntry(sal_Int32 nPos) const
Definition: combobox.cxx:945
sal_Int64 WinBits
sal_uInt16 sal_Unicode
Edit * GetField() const
Definition: field.hxx:58
sal_Int64 mnBaseValue
Definition: field.hxx:235
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: spinfld.cxx:352
CurrencyField(vcl::Window *pParent, WinBits nWinStyle)
Definition: field.cxx:1939
static FieldUnit ImplMetricGetUnit(const OUString &rStr)
Definition: field.cxx:1086
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: combobox.cxx:118
FieldUnit GetUnit() const
Definition: field.hxx:204
OUString maCustomUnitText
Definition: field.hxx:249
#define X
Definition: field.cxx:1094
sal_Int64 GetBaseValue() const
Definition: field.cxx:1557
bool mbEmptyFieldValue
Definition: field.hxx:47
sal_uInt16 GetDecimalDigits() const
Definition: field.hxx:140
virtual Size CalcMinimumSize() const override
Definition: field.cxx:923
AllSettingsFlags GetFlags() const
Definition: event.hxx:349
virtual void SetModifyFlag()
Definition: edit.cxx:2588
bool IsEmptyFieldValue() const
Definition: field.cxx:520
virtual const Selection & GetSelection() const
Definition: edit.cxx:2468
virtual void First() override
Definition: field.cxx:867
SAL_DLLPRIVATE void ImplNewFieldValue(sal_Int64 nNewValue)
Definition: field.cxx:739
Definition: edit.hxx:57
virtual void Down()
Definition: spinfld.cxx:364
virtual void Modify() override
Definition: field.cxx:1712
sal_Int64 GetMin() const
Definition: field.hxx:126
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1963
WinBits const WB_HIDE
MetricBox(vcl::Window *pParent, WinBits nWinStyle)
Definition: field.cxx:1756
static bool ImplCurrencyGetValue(const OUString &rStr, sal_Int64 &rValue, sal_uInt16 nDecDigits, const LocaleDataWrapper &rWrapper)
Definition: field.cxx:1865
static FieldUnit ImplMap2FieldUnit(MapUnit meUnit, long &nDecDigits)
Definition: field.cxx:1126
static void SetDefaultUnit(FieldUnit eDefaultUnit)
Definition: field.cxx:1124
const LanguageTag & GetLanguageTag() const
SAL_DLLPRIVATE void ImplInit()
Definition: field.cxx:538
bool mbStrictFormat
Definition: field.hxx:46
const LanguageTag & GetLanguageTag() const
Definition: field.cxx:489
FieldUnit meUnit
Definition: field.hxx:236
virtual Size CalcMinimumSize() const override
Definition: field.cxx:1610
SAL_DLLPRIVATE void ImplMetricReformat(const OUString &rStr, double &rValue, OUString &rOutStr)
Definition: field.cxx:1395
SAL_DLLPRIVATE void ImplCurrencyReformat(const OUString &rStr, OUString &rOutStr)
Definition: field.cxx:1872
virtual void ReformatAll()
Definition: field.cxx:466
virtual void ReformatAll() override
Definition: field.cxx:2081
const OUString & getNumDecimalSep() const
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: combobox.cxx:680
long Min() const
virtual boost::property_tree::ptree DumpAsPropertyTree()
Dumps itself and potentially its children to a property tree, to be written easily to JSON...
Definition: window.cxx:3354
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: spinfld.cxx:490
bool IsDropDownBox() const
Definition: combobox.cxx:592
void Justify()
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:957
virtual void Down() override
Definition: field.cxx:2004
#define SAL_MAX_INT32
virtual bool PreNotify(NotifyEvent &rNEvt)
Definition: event.cxx:51
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1952
virtual ~CurrencyFormatter() override
Definition: field.cxx:1891
virtual void Modify() override
Definition: field.cxx:2075
static bool isAlpha(const sal_Unicode ch)
void setLanguageTag(const LanguageTag &rLanguageTag)
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: combobox.cxx:702
virtual void Reformat()
Definition: field.cxx:462
bool mbReformat
Definition: field.hxx:45
virtual void CustomConvert() override
Definition: field.cxx:1742
bool IsStrictFormat() const
Definition: field.hxx:71
static bool isControl(const sal_Unicode ch)
sal_Int64 GetCorrectedValue(FieldUnit eOutUnit) const
Definition: field.cxx:1590
const css::lang::Locale & GetLocale() const
Definition: field.cxx:481
virtual void First() override
Definition: field.cxx:1730
sal_Int64 Normalize(sal_Int64 nValue) const
Definition: field.cxx:663
int i
void SetEmptyFieldValueData(bool bValue)
Definition: field.hxx:54
virtual Size CalcMinimumSize() const override
Definition: field.cxx:943
virtual void CustomConvert() override
Definition: field.cxx:1845
void SetUpdateMode(bool bUpdate)
Definition: window.cxx:2971
virtual OUString GetText() const override
Definition: edit.cxx:2564
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:820
bool IsUpdateMode() const
Definition: window2.cxx:1162
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: field.cxx:1976
virtual void Modify()
Definition: edit.cxx:2305
float u
virtual void Last() override
Definition: field.cxx:873
void RemoveEntryAt(sal_Int32 nPos)
Definition: combobox.cxx:914
void FormatValue(Selection const *pNewSelection=nullptr)
Definition: field.cxx:525
void InsertValue(sal_Int64 nValue, FieldUnit eInUnit=FieldUnit::NONE, sal_Int32 nPos=COMBOBOX_APPEND)
Definition: field.cxx:1850
MouseNotifyEvent GetType() const
Definition: event.hxx:294
OUString getCurr(sal_Int64 nNumber, sal_uInt16 nDecimals, const OUString &rCurrencySymbol, bool bUseThousandSep=true) const
static bool toBool(const OString &rValue)
Definition: builder.cxx:70
const AllSettings & GetSettings() const
Definition: outdev.hxx:420
bool mbShowTrailingZeros
Definition: field.hxx:190
static OUString ImplMetricGetUnitText(const OUString &rStr)
Definition: field.cxx:1041
#define KEYGROUP_MISC
Definition: keycodes.hxx:41
SAL_DLLPRIVATE bool ImplGetEmptyFieldValue() const
Definition: field.hxx:52
static FieldUnit StringToMetric(const OUString &rMetricString)
Definition: field.cxx:1073
virtual Size CalcMinimumSize() const override
Definition: field.cxx:1769
sal_Int64 Denormalize(sal_Int64 nValue) const
Definition: field.cxx:668
sal_Int64 mnLast
Definition: field.hxx:169
void SetLast(sal_Int64 nNewLast, FieldUnit eInUnit)
Definition: field.cxx:1657
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1683
SAL_DLLPRIVATE void ImplSetText(const OUString &rText, Selection const *pNewSel=nullptr)
Definition: field.cxx:497
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1672
bool IsShowTrailingZeros() const
Definition: field.hxx:146
CurrencyFormatter(Edit *pEdit)
Definition: field.cxx:1886
virtual void Reformat() override
Definition: field.cxx:690
void FieldDown()
Definition: field.cxx:715
#define M
Definition: field.cxx:1093
const OUString & getNumDecimalSepAlt() const
virtual sal_Int64 GetValueFromStringUnit(const OUString &rStr, FieldUnit eOutUnit) const
Definition: field.cxx:1490
virtual void SetUnit(FieldUnit meUnit) override
Definition: field.cxx:1626
void SetUseThousandSep(bool b)
Definition: field.cxx:584
void MarkToBeReformatted(bool b)
Definition: field.hxx:68
sal_Int64 mnMax
Definition: field.hxx:161
virtual boost::property_tree::ptree DumpAsPropertyTree() override
Dumps itself and potentially its children to a property tree, to be written easily to JSON...
Definition: field.cxx:1747
void SetCustomUnitText(const OUString &rStr)
Definition: field.cxx:1437
const vcl::KeyCode & GetKeyCode() const
Definition: event.hxx:53
virtual void First()
Definition: spinfld.cxx:369
virtual sal_Int64 GetValueFromString(const OUString &rStr) const
Definition: field.cxx:632
static OUString formatPercent(double dNumber, const LanguageTag &rLangTag)
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: spinfld.cxx:813
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: field.cxx:1696
virtual void Up() override
Definition: field.cxx:1998
virtual void Down() override
Definition: field.cxx:1724
sal_Int64 GetMax() const
Definition: field.hxx:128
sal_Int32 GetEntryCount() const
Definition: combobox.cxx:954
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:2035
#define SAL_WARN_IF(condition, area, stream)
#define K
Definition: field.cxx:1092
MetricFormatter(Edit *pEdit)
Definition: field.cxx:1415
static sal_Int64 ConvertValue(sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, FieldUnit eInUnit, FieldUnit eOutUnit)
Definition: field.cxx:1167
void FieldFirst()
Definition: field.cxx:729
virtual void Last() override
Definition: field.cxx:2016
sal_Int64 GetLast() const
Definition: field.hxx:135
MetricField(vcl::Window *pParent, WinBits nWinStyle)
Definition: field.cxx:1597
sal_Unicode GetCharCode() const
Definition: event.hxx:52
virtual void ReformatAll() override
Definition: field.cxx:1829
virtual void Up() override
Definition: field.cxx:1718
FormatterBase(Edit *pField)
Definition: field.cxx:434
virtual void Up() override
Definition: field.cxx:855
virtual OUString CreateFieldText(sal_Int64 nValue) const override
Definition: field.cxx:1449
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: field.cxx:1604
sal_Int64 mnSpinSize
Definition: field.hxx:167
sal_Int64 mnFirst
Definition: field.hxx:168
virtual void Last()
Definition: spinfld.cxx:374
void SetDecimalDigits(sal_uInt16 nDigits)
Definition: field.cxx:590
virtual void Modify() override
Definition: field.cxx:1992
virtual void Modify() override
Definition: field.cxx:997
virtual void SetValue(sal_Int64 nNewValue, FieldUnit eInUnit)
Definition: field.cxx:1443
SAL_DLLPRIVATE void ImplNumericReformat()
Definition: field.cxx:532
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:968
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: spinfld.cxx:835
void * GetEntryData(sal_Int32 nPos) const
Definition: combobox.cxx:1317
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: field.cxx:2029
void SetUserValue(sal_Int64 nNewValue, FieldUnit eInUnit)
Definition: field.cxx:1483
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: field.cxx:833
const OUString & getNumThousandSep() const
A widget used to choose from a list of items and which has an entry.
Definition: combobox.hxx:34
void FieldUp()
Definition: field.cxx:701
#define SELECTION_MAX
CurrencyBox(vcl::Window *pParent, WinBits nWinStyle)
Definition: field.cxx:2022
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: field.cxx:790
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: field.cxx:2059
bool IsUseThousandSep() const
Definition: field.hxx:143
virtual ~NumericFormatter() override
Definition: field.cxx:566
MapUnit
static double ConvertDoubleValue(double nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, FieldUnit eInUnit, FieldUnit eOutUnit)
Definition: field.cxx:1258
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: field.cxx:981
OUString getNum(sal_Int64 nNumber, sal_uInt16 nDecimals, bool bUseThousandSep=true, bool bTrailingZeros=true) const
SAL_DLLPRIVATE LocaleDataWrapper & ImplGetLocaleDataWrapper() const
Definition: field.cxx:448
long Max() const
sal_Int64 mnMin
Definition: field.hxx:160
virtual ~MetricFormatter() override
Definition: field.cxx:1421
sal_Int32 InsertEntry(const OUString &rStr, sal_Int32 nPos=COMBOBOX_APPEND)
Definition: combobox.cxx:868
const FieldUnitStringList & ImplGetFieldUnits()
Definition: svdata.cxx:263
virtual sal_Int64 GetValueFromString(const OUString &rStr) const override
Definition: field.cxx:1909
bool mbWrapOnLimits
Definition: field.hxx:162
virtual void SetText(const OUString &rStr) override
Definition: edit.cxx:2545
NumericFormatter(Edit *pEdit)
Definition: field.cxx:560
sal_Int64 ClipAgainstMinMax(sal_Int64 nValue) const
Definition: field.cxx:772
virtual ~FormatterBase()
Definition: field.cxx:444
const LocaleDataWrapper & GetLocaleDataWrapper() const
Definition: field.cxx:457
void setWidth(long nWidth)
void SetUserValue(sal_Int64 nNewValue)
Definition: field.cxx:627
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: field.cxx:1807
aStr
NumericBox(vcl::Window *pParent, WinBits nWinStyle)
Definition: field.cxx:928
Size CalcMinimumSize() const override
Definition: combobox.cxx:1025
static bool ImplCurrencyProcessKeyInput(const KeyEvent &rKEvt, bool bUseThousandSep, const LocaleDataWrapper &rWrapper)
Definition: field.cxx:1858
#define SAL_MAX_INT64
virtual void Modify() override
Definition: field.cxx:849
sal_uInt16 mnDecimalDigits
Definition: field.hxx:188
SAL_DLLPRIVATE void ImplInit()
Definition: field.cxx:1409
virtual void SetValue(sal_Int64 nNewValue)
Definition: field.cxx:606
static bool TextToValue(const OUString &rStr, double &rValue, sal_Int64 nBaseValue, sal_uInt16 nDecDigits, const LocaleDataWrapper &rLocaleDataWrapper, FieldUnit eUnit)
Definition: field.cxx:1377
VclPtr< Edit > mpField
Definition: field.hxx:42
virtual void Modify() override
Definition: combobox.cxx:807
virtual void Reformat() override
Definition: field.cxx:1920
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: field.cxx:1763
bool IsMod2() const
Definition: keycod.hxx:62
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
Definition: window.cxx:2150
void setHeight(long nHeight)
static double nonValueDoubleToValueDouble(double nValue)
Definition: field.cxx:1162