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  : FormatterBase(pEdit)
540  , mnFieldValue(0)
541  , mnLastValue(0)
542  , mnMin(0)
543  // a "large" value substantially smaller than SAL_MAX_INT64, to avoid
544  // overflow in computations using this "dummy" value
545  , mnMax(SAL_MAX_INT32)
546  , mbWrapOnLimits(false)
547  , mbFormatting(false)
548  , mnSpinSize(1)
549  // for fields
550  , mnFirst(mnMin)
551  , mnLast(mnMax)
552  , mnDecimalDigits(0)
553  , mbThousandSep(true)
554  , mbShowTrailingZeros(true)
555 {
556  ReformatAll();
557 }
558 
560 {
561 }
562 
563 void NumericFormatter::SetMin( sal_Int64 nNewMin )
564 {
565  mnMin = nNewMin;
566  if ( !IsEmptyFieldValue() )
567  ReformatAll();
568 }
569 
570 void NumericFormatter::SetMax( sal_Int64 nNewMax )
571 {
572  mnMax = nNewMax;
573  if ( !IsEmptyFieldValue() )
574  ReformatAll();
575 }
576 
578 {
579  mbThousandSep = bValue;
580  ReformatAll();
581 }
582 
583 void NumericFormatter::SetDecimalDigits( sal_uInt16 nDigits )
584 {
585  mnDecimalDigits = nDigits;
586  ReformatAll();
587 }
588 
589 void NumericFormatter::SetShowTrailingZeros( bool bShowTrailingZeros )
590 {
591  if ( mbShowTrailingZeros != bShowTrailingZeros )
592  {
593  mbShowTrailingZeros = bShowTrailingZeros;
594  ReformatAll();
595  }
596 }
597 
598 
599 void NumericFormatter::SetValue( sal_Int64 nNewValue )
600 {
601  SetUserValue( nNewValue );
603  SetEmptyFieldValueData( false );
604 }
605 
606 OUString NumericFormatter::CreateFieldText( sal_Int64 nValue ) const
607 {
609 }
610 
611 void NumericFormatter::ImplSetUserValue( sal_Int64 nNewValue, Selection const * pNewSelection )
612 {
613  nNewValue = ClipAgainstMinMax(nNewValue);
614  mnLastValue = nNewValue;
615 
616  if ( GetField() )
617  FormatValue(pNewSelection);
618 }
619 
620 void NumericFormatter::SetUserValue( sal_Int64 nNewValue )
621 {
622  ImplSetUserValue( nNewValue );
623 }
624 
625 sal_Int64 NumericFormatter::GetValueFromString(const OUString& rStr) const
626 {
627  sal_Int64 nTempValue;
628 
629  if (ImplNumericGetValue(rStr, nTempValue,
631  {
632  return ClipAgainstMinMax(nTempValue);
633  }
634  else
635  return mnLastValue;
636 }
637 
638 sal_Int64 NumericFormatter::GetValue() const
639 {
640  if (mbFormatting) //don't parse the entry if we're currently formatting what to put in it
641  return mnLastValue;
642 
643  return GetField() ? GetValueFromString(GetField()->GetText()) : 0;
644 }
645 
646 sal_Int64 NumericFormatter::Normalize( sal_Int64 nValue ) const
647 {
648  return (nValue * ImplPower10( GetDecimalDigits() ) );
649 }
650 
651 sal_Int64 NumericFormatter::Denormalize( sal_Int64 nValue ) const
652 {
653  sal_Int64 nFactor = ImplPower10( GetDecimalDigits() );
654 
655  if ((nValue < ( SAL_MIN_INT64 + nFactor )) ||
656  (nValue > ( SAL_MAX_INT64 - nFactor )))
657  {
658  return ( nValue / nFactor );
659  }
660 
661  if( nValue < 0 )
662  {
663  sal_Int64 nHalf = nFactor / 2;
664  return ((nValue - nHalf) / nFactor );
665  }
666  else
667  {
668  sal_Int64 nHalf = nFactor / 2;
669  return ((nValue + nHalf) / nFactor );
670  }
671 }
672 
674 {
675  if ( !GetField() )
676  return;
677 
678  if ( GetField()->GetText().isEmpty() && ImplGetEmptyFieldValue() )
679  return;
680 
682 }
683 
685 {
686  sal_Int64 nValue = GetValue();
687  sal_Int64 nRemainder = nValue % mnSpinSize;
688  if (nValue >= 0)
689  nValue = (nRemainder == 0) ? nValue + mnSpinSize : nValue + mnSpinSize - nRemainder;
690  else
691  nValue = (nRemainder == 0) ? nValue + mnSpinSize : nValue - nRemainder;
692 
693  nValue = ClipAgainstMinMax(nValue);
694 
695  ImplNewFieldValue( nValue );
696 }
697 
699 {
700  sal_Int64 nValue = GetValue();
701  sal_Int64 nRemainder = nValue % mnSpinSize;
702  if (nValue >= 0)
703  nValue = (nRemainder == 0) ? nValue - mnSpinSize : nValue - nRemainder;
704  else
705  nValue = (nRemainder == 0) ? nValue - mnSpinSize : nValue - mnSpinSize - nRemainder;
706 
707  nValue = ClipAgainstMinMax(nValue);
708 
709  ImplNewFieldValue( nValue );
710 }
711 
713 {
715 }
716 
718 {
720 }
721 
722 void NumericFormatter::ImplNewFieldValue( sal_Int64 nNewValue )
723 {
724  if ( GetField() )
725  {
726  // !!! We should check why we do not validate in ImplSetUserValue() if the value was
727  // changed. This should be done there as well since otherwise the call to Modify would not
728  // be allowed. Anyway, the paths from ImplNewFieldValue, ImplSetUserValue, and ImplSetText
729  // should be checked and clearly traced (with comment) in order to find out what happens.
730 
731  Selection aSelection = GetField()->GetSelection();
732  aSelection.Justify();
733  OUString aText = GetField()->GetText();
734  // leave it as is if selected until end
735  if ( static_cast<sal_Int32>(aSelection.Max()) == aText.getLength() )
736  {
737  if ( !aSelection.Len() )
738  aSelection.Min() = SELECTION_MAX;
739  aSelection.Max() = SELECTION_MAX;
740  }
741 
742  sal_Int64 nOldLastValue = mnLastValue;
743  ImplSetUserValue( nNewValue, &aSelection );
744  mnLastValue = nOldLastValue;
745 
746  // Modify during Edit is only set during KeyInput
747  if ( GetField()->GetText() != aText )
748  {
749  GetField()->SetModifyFlag();
750  GetField()->Modify();
751  }
752  }
753 }
754 
755 sal_Int64 NumericFormatter::ClipAgainstMinMax(sal_Int64 nValue) const
756 {
757  if (nValue > mnMax)
758  nValue = mbWrapOnLimits ? ((nValue - mnMin) % (mnMax + 1)) + mnMin
759  : mnMax;
760  else if (nValue < mnMin)
761  nValue = mbWrapOnLimits ? ((nValue + mnMax + 1 - mnMin) % (mnMax + 1)) + mnMin
762  : mnMin;
763  return nValue;
764 }
765 
767  : SpinField(pParent, nWinStyle)
768  , NumericFormatter(this)
769 {
770  Reformat();
771 }
772 
774 {
775  ClearField();
777 }
778 
779 bool NumericField::set_property(const OString &rKey, const OUString &rValue)
780 {
781  if (rKey == "digits")
782  SetDecimalDigits(rValue.toInt32());
783  else if (rKey == "spin-size")
784  SetSpinSize(rValue.toInt32());
785  else if (rKey == "wrap")
786  mbWrapOnLimits = toBool(rValue);
787  else
788  return SpinField::set_property(rKey, rValue);
789  return true;
790 }
791 
793 {
794  if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
795  {
796  if ( ImplNumericProcessKeyInput( *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
797  return true;
798  }
799 
800  return SpinField::PreNotify( rNEvt );
801 }
802 
804 {
805  if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
806  MarkToBeReformatted( false );
807  else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
808  {
809  if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
810  Reformat();
811  }
812 
813  return SpinField::EventNotify( rNEvt );
814 }
815 
817 {
818  SpinField::DataChanged( rDCEvt );
819 
820  if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
821  {
822  OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
823  OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
825  OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
826  OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
827  ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
828  ReformatAll();
829  }
830 }
831 
833 {
834  MarkToBeReformatted( true );
836 }
837 
839 {
840  FieldUp();
841  SpinField::Up();
842 }
843 
845 {
846  FieldDown();
847  SpinField::Down();
848 }
849 
851 {
852  FieldFirst();
854 }
855 
857 {
858  FieldLast();
859  SpinField::Last();
860 }
861 
862 boost::property_tree::ptree NumericField::DumpAsPropertyTree()
863 {
864  boost::property_tree::ptree aTree(SpinField::DumpAsPropertyTree());
865  aTree.put("min", GetMin());
866  aTree.put("max", GetMax());
867  return aTree;
868 }
869 
870 namespace
871 {
872  Size calcMinimumSize(const Edit &rSpinField, const NumericFormatter &rFormatter)
873  {
874  OUStringBuffer aBuf;
875  sal_Int32 nTextLen;
876 
877  nTextLen = OUString(OUString::number(rFormatter.GetMin())).getLength();
878  string::padToLength(aBuf, nTextLen, '9');
879  Size aMinTextSize = rSpinField.CalcMinimumSizeForText(
880  rFormatter.CreateFieldText(aBuf.toString().toInt64()));
881  aBuf.setLength(0);
882 
883  nTextLen = OUString(OUString::number(rFormatter.GetMax())).getLength();
884  string::padToLength(aBuf, nTextLen, '9');
885  Size aMaxTextSize = rSpinField.CalcMinimumSizeForText(
886  rFormatter.CreateFieldText(aBuf.toString().toInt64()));
887  aBuf.setLength(0);
888 
889  Size aRet(std::max(aMinTextSize.Width(), aMaxTextSize.Width()),
890  std::max(aMinTextSize.Height(), aMaxTextSize.Height()));
891 
892  OUStringBuffer sBuf("999999999");
893  sal_uInt16 nDigits = rFormatter.GetDecimalDigits();
894  if (nDigits)
895  {
896  sBuf.append('.');
897  string::padToLength(aBuf, aBuf.getLength() + nDigits, '9');
898  }
899  aMaxTextSize = rSpinField.CalcMinimumSizeForText(sBuf.makeStringAndClear());
900  aRet.setWidth( std::min(aRet.Width(), aMaxTextSize.Width()) );
901 
902  return aRet;
903  }
904 }
905 
907 {
908  return calcMinimumSize(*this, *this);
909 }
910 
912  : ComboBox(pParent, nWinStyle)
913  , NumericFormatter(this)
914 {
915  Reformat();
916  if ( !(nWinStyle & WB_HIDE ) )
917  Show();
918 }
919 
921 {
922  ClearField();
924 }
925 
927 {
928  Size aRet(calcMinimumSize(*this, *this));
929 
930  if (IsDropDownBox())
931  {
932  Size aComboSugg(ComboBox::CalcMinimumSize());
933  aRet.setWidth( std::max(aRet.Width(), aComboSugg.Width()) );
934  aRet.setHeight( std::max(aRet.Height(), aComboSugg.Height()) );
935  }
936 
937  return aRet;
938 }
939 
941 {
942  if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
943  {
944  if ( ImplNumericProcessKeyInput( *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
945  return true;
946  }
947 
948  return ComboBox::PreNotify( rNEvt );
949 }
950 
952 {
953  if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
954  MarkToBeReformatted( false );
955  else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
956  {
957  if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
958  Reformat();
959  }
960 
961  return ComboBox::EventNotify( rNEvt );
962 }
963 
965 {
966  ComboBox::DataChanged( rDCEvt );
967 
968  if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
969  {
970  OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
971  OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
973  OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
974  OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
975  ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
976  ReformatAll();
977  }
978 }
979 
981 {
982  MarkToBeReformatted( true );
984 }
985 
986 void NumericBox::ImplNumericReformat( const OUString& rStr, sal_Int64& rValue,
987  OUString& rOutStr )
988 {
989  if (ImplNumericGetValue(rStr, rValue, GetDecimalDigits(), ImplGetLocaleDataWrapper()))
990  {
991  sal_Int64 nTempVal = ClipAgainstMinMax(rValue);
992  rOutStr = CreateFieldText( nTempVal );
993  }
994 }
995 
997 {
998  sal_Int64 nValue;
999  OUString aStr;
1000  SetUpdateMode( false );
1001  sal_Int32 nEntryCount = GetEntryCount();
1002  for ( sal_Int32 i=0; i < nEntryCount; i++ )
1003  {
1004  ImplNumericReformat( GetEntry( i ), nValue, aStr );
1005  RemoveEntryAt(i);
1006  InsertEntry( aStr, i );
1007  }
1009  SetUpdateMode( true );
1010 }
1011 
1012 void NumericBox::InsertValue( sal_Int64 nValue, sal_Int32 nPos )
1013 {
1014  ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
1015 }
1016 
1017 static bool ImplMetricProcessKeyInput( const KeyEvent& rKEvt,
1018  bool bUseThousandSep, const LocaleDataWrapper& rWrapper )
1019 {
1020  // no meaningful strict format; therefore allow all characters
1021  return ImplNumericProcessKeyInput( rKEvt, false, bUseThousandSep, rWrapper );
1022 }
1023 
1024 static OUString ImplMetricGetUnitText(const OUString& rStr)
1025 {
1026  // fetch unit text
1027  OUStringBuffer aStr;
1028  for (sal_Int32 i = rStr.getLength()-1; i >= 0; --i)
1029  {
1030  sal_Unicode c = rStr[i];
1031  if ( (c == '\'') || (c == '\"') || (c == '%') || (c == 0x2032) || (c == 0x2033) || unicode::isAlpha(c) || unicode::isControl(c) )
1032  aStr.insert(0, c);
1033  else
1034  {
1035  if (!aStr.isEmpty())
1036  break;
1037  }
1038  }
1039  return aStr.makeStringAndClear();
1040 }
1041 
1042 // #104355# support localized measurements
1043 
1044 static OUString ImplMetricToString( FieldUnit rUnit )
1045 {
1046  // return unit's default string (ie, the first one )
1047  for (auto const& elem : ImplGetFieldUnits())
1048  {
1049  if (elem.second == rUnit)
1050  return elem.first;
1051  }
1052 
1053  return OUString();
1054 }
1055 
1056 FieldUnit MetricFormatter::StringToMetric(const OUString &rMetricString)
1057 {
1058  // return FieldUnit
1059  OUString aStr = rMetricString.toAsciiLowerCase().replaceAll(" ", "");
1060  for (auto const& elem : ImplGetCleanedFieldUnits())
1061  {
1062  if ( elem.first == aStr )
1063  return elem.second;
1064  }
1065 
1066  return FieldUnit::NONE;
1067 }
1068 
1069 static FieldUnit ImplMetricGetUnit(const OUString& rStr)
1070 {
1071  OUString aStr = ImplMetricGetUnitText(rStr);
1072  return MetricFormatter::StringToMetric(aStr);
1073 }
1074 
1075 #define K *1000L
1076 #define M *1000000LL
1077 #define X *5280L
1078 
1079 // twip in km = 254 / 14 400 000 000
1080 // expressions too big for default size 32 bit need LL to avoid overflow
1081 
1082 static const sal_Int64 aImplFactor[sal_uInt16(FieldUnit::LINE) + 1]
1083  [sal_uInt16(FieldUnit::LINE) + 1] =
1084 { /*
1085 mm/100 mm cm m km twip point pica inch foot mile char line */
1086 { 1, 100, 1 K, 100 K, 100 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X , 53340, 396240},
1087 { 1, 1, 10, 1 K, 1 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X , 5334, 396240},
1088 { 1, 1, 1, 100, 100 K, 254, 254, 254, 254, 254*12, 254*12 X , 5334, 39624},
1089 { 1, 1, 1, 1, 1 K, 254, 254, 254, 254, 254*12, 254*12 X , 533400, 39624},
1090 { 1, 1, 1, 1, 1, 254, 254, 254, 254, 254*12, 254*12 X ,533400 K, 39624},
1091 { 1440,144 K,144 K,14400 K,14400LL M, 1, 20, 240, 1440,1440*12,1440*12 X , 210, 3120},
1092 { 72, 7200, 7200, 720 K, 720 M, 1, 1, 12, 72, 72*12, 72*12 X , 210, 156},
1093 { 6, 600, 600, 60 K, 60 M, 1, 1, 1, 6, 6*12, 6*12 X , 210, 10},
1094 { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 12, 12 X , 210, 45},
1095 { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 1, 1 X , 210, 45},
1096 { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 1, 1 , 210, 45},
1097 { 144, 1440,14400, 14400, 14400, 1, 20, 240, 1440,1440*12, 1440*12 X, 1, 156 },
1098 { 720,72000,72000, 7200 K,7200LL M, 20, 10, 13, 11, 11*12, 11*12 X, 105, 1 }
1099 };
1100 #undef X
1101 #undef M
1102 #undef K
1103 
1104 static FieldUnit ImplMap2FieldUnit( MapUnit meUnit, long& nDecDigits )
1105 {
1106  switch( meUnit )
1107  {
1108  case MapUnit::Map100thMM :
1109  nDecDigits -= 2;
1110  return FieldUnit::MM;
1111  case MapUnit::Map10thMM :
1112  nDecDigits -= 1;
1113  return FieldUnit::MM;
1114  case MapUnit::MapMM :
1115  return FieldUnit::MM;
1116  case MapUnit::MapCM :
1117  return FieldUnit::CM;
1118  case MapUnit::Map1000thInch :
1119  nDecDigits -= 3;
1120  return FieldUnit::INCH;
1121  case MapUnit::Map100thInch :
1122  nDecDigits -= 2;
1123  return FieldUnit::INCH;
1124  case MapUnit::Map10thInch :
1125  nDecDigits -= 1;
1126  return FieldUnit::INCH;
1127  case MapUnit::MapInch :
1128  return FieldUnit::INCH;
1129  case MapUnit::MapPoint :
1130  return FieldUnit::POINT;
1131  case MapUnit::MapTwip :
1132  return FieldUnit::TWIP;
1133  default:
1134  OSL_FAIL( "default eInUnit" );
1135  break;
1136  }
1137  return FieldUnit::NONE;
1138 }
1139 
1140 static double nonValueDoubleToValueDouble( double nValue )
1141 {
1142  return rtl::math::isFinite( nValue ) ? nValue : 0.0;
1143 }
1144 
1145 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits,
1146  FieldUnit eInUnit, FieldUnit eOutUnit )
1147 {
1149  static_cast<double>(nValue), mnBaseValue, nDecDigits, eInUnit, eOutUnit ) );
1150  sal_Int64 nLong ;
1151 
1152  // caution: precision loss in double cast
1153  if ( nDouble <= double(SAL_MIN_INT64) )
1154  nLong = SAL_MIN_INT64;
1155  else if ( nDouble >= double(SAL_MAX_INT64) )
1156  nLong = SAL_MAX_INT64;
1157  else
1158  nLong = static_cast<sal_Int64>( nDouble );
1159 
1160  return nLong;
1161 }
1162 
1163 namespace {
1164 
1165 bool checkConversionUnits(MapUnit eInUnit, FieldUnit eOutUnit)
1166 {
1167  return eOutUnit != FieldUnit::PERCENT
1168  && eOutUnit != FieldUnit::CUSTOM
1169  && eOutUnit != FieldUnit::NONE
1170  && eInUnit != MapUnit::MapPixel
1171  && eInUnit != MapUnit::MapSysFont
1172  && eInUnit != MapUnit::MapAppFont
1173  && eInUnit != MapUnit::MapRelative;
1174 }
1175 
1176 double convertValue( double nValue, long nDigits, FieldUnit eInUnit, FieldUnit eOutUnit )
1177 {
1178  if ( nDigits < 0 )
1179  {
1180  while ( nDigits )
1181  {
1182  nValue += 5;
1183  nValue /= 10;
1184  nDigits++;
1185  }
1186  }
1187  else
1188  {
1189  nValue *= ImplPower10(nDigits);
1190  }
1191 
1192  if ( eInUnit != eOutUnit )
1193  {
1194  sal_Int64 nDiv = aImplFactor[sal_uInt16(eInUnit)][sal_uInt16(eOutUnit)];
1195  sal_Int64 nMult = aImplFactor[sal_uInt16(eOutUnit)][sal_uInt16(eInUnit)];
1196 
1197  SAL_WARN_IF( nMult <= 0, "vcl", "illegal *" );
1198  SAL_WARN_IF( nDiv <= 0, "vcl", "illegal /" );
1199 
1200  if ( nMult != 1 && nMult > 0)
1201  nValue *= nMult;
1202  if ( nDiv != 1 && nDiv > 0 )
1203  {
1204  nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2);
1205  nValue /= nDiv;
1206  }
1207  }
1208  return nValue;
1209 }
1210 
1211 }
1212 
1213 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_uInt16 nDigits,
1214  MapUnit eInUnit, FieldUnit eOutUnit )
1215 {
1216  if ( !checkConversionUnits(eInUnit, eOutUnit) )
1217  {
1218  OSL_FAIL( "invalid parameters" );
1219  return nValue;
1220  }
1221 
1222  long nDecDigits = nDigits;
1223  FieldUnit eFieldUnit = ImplMap2FieldUnit( eInUnit, nDecDigits );
1224 
1225  // Avoid sal_Int64 <-> double conversion issues if possible:
1226  if (eFieldUnit == eOutUnit && nDigits == 0)
1227  {
1228  return nValue;
1229  }
1230 
1231  return static_cast<sal_Int64>(
1233  convertValue( nValue, nDecDigits, eFieldUnit, eOutUnit ) ) );
1234 }
1235 
1236 double MetricField::ConvertDoubleValue( double nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits,
1237  FieldUnit eInUnit, FieldUnit eOutUnit )
1238 {
1239  if ( eInUnit != eOutUnit )
1240  {
1241  sal_Int64 nMult = 1, nDiv = 1;
1242 
1243  if (eInUnit == FieldUnit::PERCENT)
1244  {
1245  if ( (mnBaseValue <= 0) || (nValue <= 0) )
1246  return nValue;
1247  nDiv = 100 * ImplPower10(nDecDigits);
1248 
1249  nMult = mnBaseValue;
1250  }
1251  else if ( eOutUnit == FieldUnit::PERCENT ||
1252  eOutUnit == FieldUnit::CUSTOM ||
1253  eOutUnit == FieldUnit::NONE ||
1254  eOutUnit == FieldUnit::DEGREE ||
1255  eOutUnit == FieldUnit::SECOND ||
1256  eOutUnit == FieldUnit::MILLISECOND ||
1257  eOutUnit == FieldUnit::PIXEL ||
1258  eInUnit == FieldUnit::CUSTOM ||
1259  eInUnit == FieldUnit::NONE ||
1260  eInUnit == FieldUnit::DEGREE ||
1261  eInUnit == FieldUnit::MILLISECOND ||
1262  eInUnit == FieldUnit::PIXEL )
1263  return nValue;
1264  else
1265  {
1266  if (eOutUnit == FieldUnit::MM_100TH)
1267  eOutUnit = FieldUnit::NONE;
1268  if (eInUnit == FieldUnit::MM_100TH)
1269  eInUnit = FieldUnit::NONE;
1270 
1271  nDiv = aImplFactor[sal_uInt16(eInUnit)][sal_uInt16(eOutUnit)];
1272  nMult = aImplFactor[sal_uInt16(eOutUnit)][sal_uInt16(eInUnit)];
1273 
1274  SAL_WARN_IF( nMult <= 0, "vcl", "illegal *" );
1275  SAL_WARN_IF( nDiv <= 0, "vcl", "illegal /" );
1276  }
1277 
1278  if ( nMult != 1 && nMult > 0 )
1279  nValue *= nMult;
1280  if ( nDiv != 1 && nDiv > 0 )
1281  {
1282  nValue += ( nValue < 0 ) ? (-nDiv/2) : (nDiv/2);
1283  nValue /= nDiv;
1284  }
1285  }
1286 
1287  return nValue;
1288 }
1289 
1290 double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits,
1291  MapUnit eInUnit, FieldUnit eOutUnit )
1292 {
1293  if ( !checkConversionUnits(eInUnit, eOutUnit) )
1294  {
1295  OSL_FAIL( "invalid parameters" );
1296  return nValue;
1297  }
1298 
1299  long nDecDigits = nDigits;
1300  FieldUnit eFieldUnit = ImplMap2FieldUnit( eInUnit, nDecDigits );
1301 
1302  return convertValue(nValue, nDecDigits, eFieldUnit, eOutUnit);
1303 }
1304 
1305 double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits,
1306  FieldUnit eInUnit, MapUnit eOutUnit )
1307 {
1308  if ( eInUnit == FieldUnit::PERCENT ||
1309  eInUnit == FieldUnit::CUSTOM ||
1310  eInUnit == FieldUnit::NONE ||
1311  eInUnit == FieldUnit::DEGREE ||
1312  eInUnit == FieldUnit::SECOND ||
1313  eInUnit == FieldUnit::MILLISECOND ||
1314  eInUnit == FieldUnit::PIXEL ||
1315  eOutUnit == MapUnit::MapPixel ||
1316  eOutUnit == MapUnit::MapSysFont ||
1317  eOutUnit == MapUnit::MapAppFont ||
1318  eOutUnit == MapUnit::MapRelative )
1319  {
1320  OSL_FAIL( "invalid parameters" );
1321  return nValue;
1322  }
1323 
1324  long nDecDigits = nDigits;
1325  FieldUnit eFieldUnit = ImplMap2FieldUnit( eOutUnit, nDecDigits );
1326 
1327  if ( nDecDigits < 0 )
1328  {
1329  nValue *= ImplPower10(-nDecDigits);
1330  }
1331  else
1332  {
1333  nValue /= ImplPower10(nDecDigits);
1334  }
1335 
1336  if ( eFieldUnit != eInUnit )
1337  {
1338  sal_Int64 nDiv = aImplFactor[sal_uInt16(eInUnit)][sal_uInt16(eFieldUnit)];
1339  sal_Int64 nMult = aImplFactor[sal_uInt16(eFieldUnit)][sal_uInt16(eInUnit)];
1340 
1341  SAL_WARN_IF( nMult <= 0, "vcl", "illegal *" );
1342  SAL_WARN_IF( nDiv <= 0, "vcl", "illegal /" );
1343 
1344  if( nMult != 1 && nMult > 0 )
1345  nValue *= nMult;
1346  if( nDiv != 1 && nDiv > 0 )
1347  {
1348  nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2);
1349  nValue /= nDiv;
1350  }
1351  }
1352  return nValue;
1353 }
1354 
1355 bool MetricFormatter::TextToValue(const OUString& rStr, double& rValue, sal_Int64 nBaseValue,
1356  sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrapper, FieldUnit eUnit)
1357 {
1358  // Get value
1359  sal_Int64 nValue;
1360  if ( !ImplNumericGetValue( rStr, nValue, nDecDigits, rLocaleDataWrapper ) )
1361  return false;
1362 
1363  // Determine unit
1364  FieldUnit eEntryUnit = ImplMetricGetUnit( rStr );
1365 
1366  // Recalculate unit
1367  // caution: conversion to double loses precision
1368  rValue = MetricField::ConvertDoubleValue( static_cast<double>(nValue), nBaseValue, nDecDigits, eEntryUnit, eUnit );
1369 
1370  return true;
1371 }
1372 
1373 void MetricFormatter::ImplMetricReformat( const OUString& rStr, double& rValue, OUString& rOutStr )
1374 {
1375  if ( !TextToValue( rStr, rValue, 0, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ) )
1376  return;
1377 
1378  double nTempVal = rValue;
1379  // caution: precision loss in double cast
1380  if ( nTempVal > GetMax() )
1381  nTempVal = static_cast<double>(GetMax());
1382  else if ( nTempVal < GetMin())
1383  nTempVal = static_cast<double>(GetMin());
1384  rOutStr = CreateFieldText( static_cast<sal_Int64>(nTempVal) );
1385 }
1386 
1388  : NumericFormatter(pEdit)
1389  , meUnit(FieldUnit::NONE)
1390 {
1391 }
1392 
1394 {
1395 }
1396 
1398 {
1399  if (eNewUnit == FieldUnit::MM_100TH)
1400  {
1402  meUnit = FieldUnit::MM;
1403  }
1404  else
1405  meUnit = eNewUnit;
1406  ReformatAll();
1407 }
1408 
1409 void MetricFormatter::SetCustomUnitText( const OUString& rStr )
1410 {
1411  maCustomUnitText = rStr;
1412  ReformatAll();
1413 }
1414 
1415 void MetricFormatter::SetValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1416 {
1417  SetUserValue( nNewValue, eInUnit );
1419 }
1420 
1421 OUString MetricFormatter::CreateFieldText( sal_Int64 nValue ) const
1422 {
1423  //whether percent is separated from its number is locale
1424  //specific, pawn it off to icu to decide
1425  if (meUnit == FieldUnit::PERCENT)
1426  {
1427  double dValue = nValue;
1428  dValue /= ImplPower10(GetDecimalDigits());
1429  return unicode::formatPercent(dValue, GetLanguageTag());
1430  }
1431 
1432  OUString aStr = NumericFormatter::CreateFieldText( nValue );
1433 
1434  if( meUnit == FieldUnit::CUSTOM )
1435  aStr += maCustomUnitText;
1436  else
1437  {
1438  OUString aSuffix = ImplMetricToString( meUnit );
1439  if (meUnit != FieldUnit::NONE && meUnit != FieldUnit::DEGREE && meUnit != FieldUnit::INCH && meUnit != FieldUnit::FOOT)
1440  aStr += " ";
1441  if (meUnit == FieldUnit::INCH)
1442  {
1443  OUString sDoublePrime = u"\u2033";
1444  if (aSuffix != "\"" && aSuffix != sDoublePrime)
1445  aStr += " ";
1446  else
1447  aSuffix = sDoublePrime;
1448  }
1449  else if (meUnit == FieldUnit::FOOT)
1450  {
1451  OUString sPrime = u"\u2032";
1452  if (aSuffix != "'" && aSuffix != sPrime)
1453  aStr += " ";
1454  else
1455  aSuffix = sPrime;
1456  }
1457 
1458  assert(meUnit != FieldUnit::PERCENT);
1459  aStr += aSuffix;
1460  }
1461  return aStr;
1462 }
1463 
1464 void MetricFormatter::SetUserValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1465 {
1466  // convert to previously configured units
1467  nNewValue = MetricField::ConvertValue( nNewValue, 0, GetDecimalDigits(), eInUnit, meUnit );
1468  NumericFormatter::SetUserValue( nNewValue );
1469 }
1470 
1471 sal_Int64 MetricFormatter::GetValueFromStringUnit(const OUString& rStr, FieldUnit eOutUnit) const
1472 {
1473  double nTempValue;
1474  // caution: precision loss in double cast
1475  if (!TextToValue(rStr, nTempValue, 0, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit))
1476  nTempValue = static_cast<double>(mnLastValue);
1477 
1478  // caution: precision loss in double cast
1479  if (nTempValue > mnMax)
1480  nTempValue = static_cast<double>(mnMax);
1481  else if (nTempValue < mnMin)
1482  nTempValue = static_cast<double>(mnMin);
1483 
1484  // convert to requested units
1485  return MetricField::ConvertValue(static_cast<sal_Int64>(nTempValue), 0, GetDecimalDigits(), meUnit, eOutUnit);
1486 }
1487 
1488 sal_Int64 MetricFormatter::GetValueFromString(const OUString& rStr) const
1489 {
1490  return GetValueFromStringUnit(rStr, FieldUnit::NONE);
1491 }
1492 
1493 sal_Int64 MetricFormatter::GetValue( FieldUnit eOutUnit ) const
1494 {
1495  return GetField() ? GetValueFromStringUnit(GetField()->GetText(), eOutUnit) : 0;
1496 }
1497 
1498 void MetricFormatter::SetValue( sal_Int64 nValue )
1499 {
1500  // Implementation not inline, because it is a virtual Function
1501  SetValue( nValue, FieldUnit::NONE );
1502 }
1503 
1504 void MetricFormatter::SetMin( sal_Int64 nNewMin, FieldUnit eInUnit )
1505 {
1506  // convert to requested units
1508  eInUnit, meUnit ) );
1509 }
1510 
1511 sal_Int64 MetricFormatter::GetMin( FieldUnit eOutUnit ) const
1512 {
1513  // convert to requested units
1515  GetDecimalDigits(), meUnit, eOutUnit );
1516 }
1517 
1518 void MetricFormatter::SetMax( sal_Int64 nNewMax, FieldUnit eInUnit )
1519 {
1520  // convert to requested units
1522  eInUnit, meUnit ) );
1523 }
1524 
1525 sal_Int64 MetricFormatter::GetMax( FieldUnit eOutUnit ) const
1526 {
1527  // convert to requested units
1529  GetDecimalDigits(), meUnit, eOutUnit );
1530 }
1531 
1533 {
1534  // convert to requested units
1536  meUnit, FieldUnit::NONE );
1537 }
1538 
1540 {
1541  if ( !GetField() )
1542  return;
1543 
1544  OUString aText = GetField()->GetText();
1545 
1546  OUString aStr;
1547  // caution: precision loss in double cast
1548  double nTemp = static_cast<double>(mnLastValue);
1549  ImplMetricReformat( aText, nTemp, aStr );
1550  mnLastValue = static_cast<sal_Int64>(nTemp);
1551 
1552  if ( !aStr.isEmpty() )
1553  {
1554  ImplSetText( aStr );
1555  }
1556  else
1557  SetValue( mnLastValue );
1558 }
1559 
1561 {
1562  // convert to requested units
1563  return MetricField::ConvertValue( 0/*nCorrectedValue*/, 0, GetDecimalDigits(),
1564  meUnit, eOutUnit );
1565 }
1566 
1568  : SpinField(pParent, nWinStyle)
1569  , MetricFormatter(this)
1570 {
1571  Reformat();
1572 }
1573 
1575 {
1576  ClearField();
1578 }
1579 
1581 {
1582  return calcMinimumSize(*this, *this);
1583 }
1584 
1585 bool MetricField::set_property(const OString &rKey, const OUString &rValue)
1586 {
1587  if (rKey == "digits")
1588  SetDecimalDigits(rValue.toInt32());
1589  else if (rKey == "spin-size")
1590  SetSpinSize(rValue.toInt32());
1591  else
1592  return SpinField::set_property(rKey, rValue);
1593  return true;
1594 }
1595 
1597 {
1598  sal_Int64 nRawMax = GetMax( nNewUnit );
1599  sal_Int64 nMax = Denormalize( nRawMax );
1600  sal_Int64 nMin = Denormalize( GetMin( nNewUnit ) );
1601  sal_Int64 nFirst = Denormalize( GetFirst( nNewUnit ) );
1602  sal_Int64 nLast = Denormalize( GetLast( nNewUnit ) );
1603 
1604  MetricFormatter::SetUnit( nNewUnit );
1605 
1606  SetMax( Normalize( nMax ), nNewUnit );
1607  SetMin( Normalize( nMin ), nNewUnit );
1608  SetFirst( Normalize( nFirst ), nNewUnit );
1609  SetLast( Normalize( nLast ), nNewUnit );
1610 }
1611 
1612 void MetricField::SetFirst( sal_Int64 nNewFirst, FieldUnit eInUnit )
1613 {
1614  // convert
1615  nNewFirst = MetricField::ConvertValue( nNewFirst, 0, GetDecimalDigits(),
1616  eInUnit, meUnit );
1617  mnFirst = nNewFirst;
1618 }
1619 
1620 sal_Int64 MetricField::GetFirst( FieldUnit eOutUnit ) const
1621 {
1622  // convert
1624  meUnit, eOutUnit );
1625 }
1626 
1627 void MetricField::SetLast( sal_Int64 nNewLast, FieldUnit eInUnit )
1628 {
1629  // convert
1630  nNewLast = MetricField::ConvertValue( nNewLast, 0, GetDecimalDigits(),
1631  eInUnit, meUnit );
1632  mnLast = nNewLast;
1633 }
1634 
1635 sal_Int64 MetricField::GetLast( FieldUnit eOutUnit ) const
1636 {
1637  // convert
1639  meUnit, eOutUnit );
1640 }
1641 
1643 {
1644  if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1645  {
1647  return true;
1648  }
1649 
1650  return SpinField::PreNotify( rNEvt );
1651 }
1652 
1654 {
1655  if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
1656  MarkToBeReformatted( false );
1657  else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
1658  {
1659  if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
1660  Reformat();
1661  }
1662 
1663  return SpinField::EventNotify( rNEvt );
1664 }
1665 
1667 {
1668  SpinField::DataChanged( rDCEvt );
1669 
1670  if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
1671  {
1672  OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1673  OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1675  OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1676  OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1677  ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1678  ReformatAll();
1679  }
1680 }
1681 
1683 {
1684  MarkToBeReformatted( true );
1686 }
1687 
1689 {
1690  FieldUp();
1691  SpinField::Up();
1692 }
1693 
1695 {
1696  FieldDown();
1697  SpinField::Down();
1698 }
1699 
1701 {
1702  FieldFirst();
1703  SpinField::First();
1704 }
1705 
1707 {
1708  FieldLast();
1709  SpinField::Last();
1710 }
1711 
1712 boost::property_tree::ptree MetricField::DumpAsPropertyTree()
1713 {
1714  boost::property_tree::ptree aTree(SpinField::DumpAsPropertyTree());
1715  aTree.put("min", GetMin());
1716  aTree.put("max", GetMax());
1717  aTree.put("unit", FieldUnitToString(GetUnit()));
1718  return aTree;
1719 }
1720 
1722  : ComboBox(pParent, nWinStyle)
1723  , MetricFormatter(this)
1724 {
1725  Reformat();
1726 }
1727 
1729 {
1730  ClearField();
1732 }
1733 
1735 {
1736  Size aRet(calcMinimumSize(*this, *this));
1737 
1738  if (IsDropDownBox())
1739  {
1740  Size aComboSugg(ComboBox::CalcMinimumSize());
1741  aRet.setWidth( std::max(aRet.Width(), aComboSugg.Width()) );
1742  aRet.setHeight( std::max(aRet.Height(), aComboSugg.Height()) );
1743  }
1744 
1745  return aRet;
1746 }
1747 
1749 {
1750  if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1751  {
1753  return true;
1754  }
1755 
1756  return ComboBox::PreNotify( rNEvt );
1757 }
1758 
1760 {
1761  if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
1762  MarkToBeReformatted( false );
1763  else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
1764  {
1765  if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
1766  Reformat();
1767  }
1768 
1769  return ComboBox::EventNotify( rNEvt );
1770 }
1771 
1773 {
1774  ComboBox::DataChanged( rDCEvt );
1775 
1776  if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
1777  {
1778  OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1779  OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1781  OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1782  OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1783  ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1784  ReformatAll();
1785  }
1786 }
1787 
1789 {
1790  MarkToBeReformatted( true );
1791  ComboBox::Modify();
1792 }
1793 
1795 {
1796  double nValue;
1797  OUString aStr;
1798  SetUpdateMode( false );
1799  sal_Int32 nEntryCount = GetEntryCount();
1800  for ( sal_Int32 i=0; i < nEntryCount; i++ )
1801  {
1802  ImplMetricReformat( GetEntry( i ), nValue, aStr );
1803  RemoveEntryAt(i);
1804  InsertEntry( aStr, i );
1805  }
1807  SetUpdateMode( true );
1808 }
1809 
1810 void MetricBox::InsertValue( sal_Int64 nValue, FieldUnit eInUnit, sal_Int32 nPos )
1811 {
1812  // convert to previously configured units
1813  nValue = MetricField::ConvertValue( nValue, 0, GetDecimalDigits(),
1814  eInUnit, meUnit );
1815  ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
1816 }
1817 
1818 static bool ImplCurrencyProcessKeyInput( const KeyEvent& rKEvt,
1819  bool bUseThousandSep, const LocaleDataWrapper& rWrapper )
1820 {
1821  // no strict format set; therefore allow all characters
1822  return ImplNumericProcessKeyInput( rKEvt, false, bUseThousandSep, rWrapper );
1823 }
1824 
1825 static bool ImplCurrencyGetValue( const OUString& rStr, sal_Int64& rValue,
1826  sal_uInt16 nDecDigits, const LocaleDataWrapper& rWrapper )
1827 {
1828  // fetch number
1829  return ImplNumericGetValue( rStr, rValue, nDecDigits, rWrapper, true );
1830 }
1831 
1832 void CurrencyFormatter::ImplCurrencyReformat( const OUString& rStr, OUString& rOutStr )
1833 {
1834  sal_Int64 nValue;
1835  if ( !ImplNumericGetValue( rStr, nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), true ) )
1836  return;
1837 
1838  sal_Int64 nTempVal = nValue;
1839  if ( nTempVal > GetMax() )
1840  nTempVal = GetMax();
1841  else if ( nTempVal < GetMin())
1842  nTempVal = GetMin();
1843  rOutStr = CreateFieldText( nTempVal );
1844 }
1845 
1847  : NumericFormatter(pField)
1848 {
1849 }
1850 
1852 {
1853 }
1854 
1855 void CurrencyFormatter::SetValue( sal_Int64 nNewValue )
1856 {
1857  SetUserValue( nNewValue );
1859  SetEmptyFieldValueData( false );
1860 }
1861 
1862 OUString CurrencyFormatter::CreateFieldText( sal_Int64 nValue ) const
1863 {
1865  ImplGetLocaleDataWrapper().getCurrSymbol(),
1866  IsUseThousandSep() );
1867 }
1868 
1869 sal_Int64 CurrencyFormatter::GetValueFromString(const OUString& rStr) const
1870 {
1871  sal_Int64 nTempValue;
1872  if ( ImplCurrencyGetValue( rStr, nTempValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
1873  {
1874  return ClipAgainstMinMax(nTempValue);
1875  }
1876  else
1877  return mnLastValue;
1878 }
1879 
1881 {
1882  if ( !GetField() )
1883  return;
1884 
1885  OUString aStr;
1886  ImplCurrencyReformat( GetField()->GetText(), aStr );
1887 
1888  if ( !aStr.isEmpty() )
1889  {
1890  ImplSetText( aStr );
1891  sal_Int64 nTemp = mnLastValue;
1893  mnLastValue = nTemp;
1894  }
1895  else
1896  SetValue( mnLastValue );
1897 }
1898 
1900  : SpinField(pParent, nWinStyle)
1901  , CurrencyFormatter(this)
1902 {
1903  Reformat();
1904 }
1905 
1907 {
1908  ClearField();
1910 }
1911 
1913 {
1914  if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1915  {
1917  return true;
1918  }
1919 
1920  return SpinField::PreNotify( rNEvt );
1921 }
1922 
1924 {
1925  if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
1926  MarkToBeReformatted( false );
1927  else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
1928  {
1929  if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
1930  Reformat();
1931  }
1932 
1933  return SpinField::EventNotify( rNEvt );
1934 }
1935 
1937 {
1938  SpinField::DataChanged( rDCEvt );
1939 
1940  if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
1941  {
1942  OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1943  OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1945  OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1946  OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1947  ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1948  ReformatAll();
1949  }
1950 }
1951 
1953 {
1954  MarkToBeReformatted( true );
1956 }
1957 
1959 {
1960  FieldUp();
1961  SpinField::Up();
1962 }
1963 
1965 {
1966  FieldDown();
1967  SpinField::Down();
1968 }
1969 
1971 {
1972  FieldFirst();
1973  SpinField::First();
1974 }
1975 
1977 {
1978  FieldLast();
1979  SpinField::Last();
1980 }
1981 
1983  : ComboBox(pParent, nWinStyle)
1984  , CurrencyFormatter(this)
1985 {
1986  Reformat();
1987 }
1988 
1990 {
1991  ClearField();
1993 }
1994 
1996 {
1997  if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1998  {
2000  return true;
2001  }
2002 
2003  return ComboBox::PreNotify( rNEvt );
2004 }
2005 
2007 {
2008  if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
2009  MarkToBeReformatted( false );
2010  else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
2011  {
2012  if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
2013  Reformat();
2014  }
2015 
2016  return ComboBox::EventNotify( rNEvt );
2017 }
2018 
2020 {
2021  ComboBox::DataChanged( rDCEvt );
2022 
2023  if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
2024  {
2025  OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2026  OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2028  OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2029  OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2030  ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
2031  ReformatAll();
2032  }
2033 }
2034 
2036 {
2037  MarkToBeReformatted( true );
2038  ComboBox::Modify();
2039 }
2040 
2042 {
2043  OUString aStr;
2044  SetUpdateMode( false );
2045  sal_Int32 nEntryCount = GetEntryCount();
2046  for ( sal_Int32 i=0; i < nEntryCount; i++ )
2047  {
2048  ImplCurrencyReformat( GetEntry( i ), aStr );
2049  RemoveEntryAt(i);
2050  InsertEntry( aStr, i );
2051  }
2053  SetUpdateMode( true );
2054 }
2055 
2056 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Width() const
virtual void SetValue(sal_Int64 nNewValue) override
Definition: field.cxx:1855
sal_uInt16 getCurrNegativeFormat() const
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1748
void InsertValue(sal_Int64 nValue, sal_Int32 nPos=COMBOBOX_APPEND)
Definition: field.cxx:1012
void FieldLast()
Definition: field.cxx:717
virtual bool set_property(const OString &rKey, const OUString &rValue) override
Definition: field.cxx:1585
sal_Int64 GetFirst() const
Definition: field.hxx:133
FieldUnit
sal_Int32 nIndex
#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:1906
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:862
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: field.cxx:920
const FieldUnitStringList & ImplGetCleanedFieldUnits()
Definition: svdata.cxx:287
#define SAL_MIN_INT64
virtual void Reformat() override
Definition: field.cxx:1539
void SetShowTrailingZeros(bool bShowTrailingZeros)
Definition: field.cxx:589
void SetMax(sal_Int64 nNewMax)
Definition: field.cxx:570
bool mbFormatting
Definition: field.hxx:162
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:2006
long Height() const
virtual void ReformatAll() override
Definition: field.cxx:996
virtual sal_Int64 GetValueFromString(const OUString &rStr) const override
Definition: field.cxx:1488
void SetMin(sal_Int64 nNewMin, FieldUnit eInUnit)
Definition: field.cxx:1504
virtual Size CalcMinimumSizeForText(const OUString &rString) const
Definition: edit.cxx:2614
void SetFirst(sal_Int64 nNewFirst, FieldUnit eInUnit)
Definition: field.cxx:1612
static const AllSettings & GetSettings()
Gets the application's settings.
Definition: svapp.cxx:705
bool mbThousandSep
Definition: field.hxx:186
static OUString ImplMetricToString(FieldUnit rUnit)
Definition: field.cxx:1044
virtual OUString CreateFieldText(sal_Int64 nValue) const
Definition: field.cxx:606
#define KEYGROUP_FKEYS
Definition: keycodes.hxx:39
virtual void Last() override
Definition: field.cxx:1706
aBuf
static const sal_Int64 aImplFactor[sal_uInt16(FieldUnit::LINE)+1][sal_uInt16(FieldUnit::LINE)+1]
Definition: field.cxx:1083
virtual void Modify() override
Definition: field.cxx:1788
virtual OUString CreateFieldText(sal_Int64 nValue) const override
Definition: field.cxx:1862
NumericField(vcl::Window *pParent, WinBits nWinStyle)
Definition: field.cxx:766
void SetEmptyFieldValue()
Definition: field.cxx:513
sal_uInt16 GetGroup() const
Definition: keycod.hxx:66
long Len() const
sal_Int64 mnFieldValue
Definition: field.hxx:157
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:1518
sal_Int64 mnLastValue
Definition: field.hxx:158
virtual void SetUnit(FieldUnit meUnit)
Definition: field.cxx:1397
bool IsEmptyFieldValueEnabled() const
Definition: field.hxx:83
virtual bool set_property(const OString &rKey, const OUString &rValue) override
Definition: edit.cxx:177
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:1017
virtual void Down() override
Definition: field.cxx:844
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1759
sal_Int64 GetValue() const
Definition: field.cxx:638
virtual void First() override
Definition: field.cxx:1970
bool mbEmptyFieldValueEnabled
Definition: field.hxx:48
void SetStrictFormat(bool bStrict)
Definition: field.cxx:471
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:792
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:611
void ClearField()
Definition: field.hxx:59
virtual bool set_property(const OString &rKey, const OUString &rValue) override
Definition: field.cxx:779
void SetSpinSize(sal_Int64 nNewSize)
Definition: field.hxx:136
void SetMin(sal_Int64 nNewMin)
Definition: field.cxx:563
NONE
void SetEntryData(sal_Int32 nPos, void *pNewData)
Definition: combobox.cxx:1316
OUString GetEntry(sal_Int32 nPos) const
Definition: combobox.cxx:949
sal_Int64 WinBits
sal_uInt16 sal_Unicode
Edit * GetField() const
Definition: field.hxx:58
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:1899
static FieldUnit ImplMetricGetUnit(const OUString &rStr)
Definition: field.cxx:1069
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: combobox.cxx:122
FieldUnit GetUnit() const
Definition: field.hxx:200
OUString maCustomUnitText
Definition: field.hxx:237
#define X
Definition: field.cxx:1077
sal_Int64 GetBaseValue() const
Definition: field.cxx:1532
bool mbEmptyFieldValue
Definition: field.hxx:47
sal_uInt16 GetDecimalDigits() const
Definition: field.hxx:140
virtual Size CalcMinimumSize() const override
Definition: field.cxx:906
sal_Int16 const nValue
AllSettingsFlags GetFlags() const
Definition: event.hxx:349
virtual void SetModifyFlag()
Definition: edit.cxx:2583
bool IsEmptyFieldValue() const
Definition: field.cxx:520
virtual const Selection & GetSelection() const
Definition: edit.cxx:2463
virtual void First() override
Definition: field.cxx:850
SAL_DLLPRIVATE void ImplNewFieldValue(sal_Int64 nNewValue)
Definition: field.cxx:722
Definition: edit.hxx:55
virtual void Down()
Definition: spinfld.cxx:364
virtual void Modify() override
Definition: field.cxx:1682
sal_Int64 GetMin() const
Definition: field.hxx:126
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1923
WinBits const WB_HIDE
MetricBox(vcl::Window *pParent, WinBits nWinStyle)
Definition: field.cxx:1721
static bool ImplCurrencyGetValue(const OUString &rStr, sal_Int64 &rValue, sal_uInt16 nDecDigits, const LocaleDataWrapper &rWrapper)
Definition: field.cxx:1825
static FieldUnit ImplMap2FieldUnit(MapUnit meUnit, long &nDecDigits)
Definition: field.cxx:1104
const LanguageTag & GetLanguageTag() const
bool mbStrictFormat
Definition: field.hxx:46
const LanguageTag & GetLanguageTag() const
Definition: field.cxx:489
FieldUnit meUnit
Definition: field.hxx:227
virtual Size CalcMinimumSize() const override
Definition: field.cxx:1580
SAL_DLLPRIVATE void ImplMetricReformat(const OUString &rStr, double &rValue, OUString &rOutStr)
Definition: field.cxx:1373
SAL_DLLPRIVATE void ImplCurrencyReformat(const OUString &rStr, OUString &rOutStr)
Definition: field.cxx:1832
virtual void ReformatAll()
Definition: field.cxx:466
virtual void ReformatAll() override
Definition: field.cxx:2041
const OUString & getNumDecimalSep() const
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: combobox.cxx:684
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:3353
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: spinfld.cxx:490
bool IsDropDownBox() const
Definition: combobox.cxx:596
void Justify()
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:940
virtual void Down() override
Definition: field.cxx:1964
#define SAL_MAX_INT32
virtual bool PreNotify(NotifyEvent &rNEvt)
Definition: event.cxx:51
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1912
virtual ~CurrencyFormatter() override
Definition: field.cxx:1851
virtual void Modify() override
Definition: field.cxx:2035
static bool isAlpha(const sal_Unicode ch)
void setLanguageTag(const LanguageTag &rLanguageTag)
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: combobox.cxx:706
virtual void Reformat()
Definition: field.cxx:462
bool mbReformat
Definition: field.hxx:45
bool IsStrictFormat() const
Definition: field.hxx:71
static bool isControl(const sal_Unicode ch)
sal_Int64 GetCorrectedValue(FieldUnit eOutUnit) const
Definition: field.cxx:1560
const css::lang::Locale & GetLocale() const
Definition: field.cxx:481
virtual void First() override
Definition: field.cxx:1700
sal_Int64 Normalize(sal_Int64 nValue) const
Definition: field.cxx:646
int i
void SetEmptyFieldValueData(bool bValue)
Definition: field.hxx:54
virtual Size CalcMinimumSize() const override
Definition: field.cxx:926
void SetUpdateMode(bool bUpdate)
Definition: window.cxx:2968
virtual OUString GetText() const override
Definition: edit.cxx:2559
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:803
bool IsUpdateMode() const
Definition: window2.cxx:1168
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: field.cxx:1936
virtual void Modify()
Definition: edit.cxx:2300
float u
virtual void Last() override
Definition: field.cxx:856
void RemoveEntryAt(sal_Int32 nPos)
Definition: combobox.cxx:918
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:1810
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:72
const AllSettings & GetSettings() const
Definition: outdev.hxx:420
bool mbShowTrailingZeros
Definition: field.hxx:187
static OUString ImplMetricGetUnitText(const OUString &rStr)
Definition: field.cxx:1024
#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:1056
virtual Size CalcMinimumSize() const override
Definition: field.cxx:1734
sal_Int64 Denormalize(sal_Int64 nValue) const
Definition: field.cxx:651
sal_Int64 mnLast
Definition: field.hxx:168
void SetLast(sal_Int64 nNewLast, FieldUnit eInUnit)
Definition: field.cxx:1627
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1653
SAL_DLLPRIVATE void ImplSetText(const OUString &rText, Selection const *pNewSel=nullptr)
Definition: field.cxx:497
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1642
bool IsShowTrailingZeros() const
Definition: field.hxx:146
CurrencyFormatter(Edit *pEdit)
Definition: field.cxx:1846
virtual void Reformat() override
Definition: field.cxx:673
void FieldDown()
Definition: field.cxx:698
#define M
Definition: field.cxx:1076
const OUString & getNumDecimalSepAlt() const
virtual sal_Int64 GetValueFromStringUnit(const OUString &rStr, FieldUnit eOutUnit) const
Definition: field.cxx:1471
virtual void SetUnit(FieldUnit meUnit) override
Definition: field.cxx:1596
void SetUseThousandSep(bool b)
Definition: field.cxx:577
void MarkToBeReformatted(bool b)
Definition: field.hxx:68
sal_Int64 mnMax
Definition: field.hxx:160
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:1712
void SetCustomUnitText(const OUString &rStr)
Definition: field.cxx:1409
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:625
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:1666
virtual void Up() override
Definition: field.cxx:1958
virtual void Down() override
Definition: field.cxx:1694
sal_Int64 GetMax() const
Definition: field.hxx:128
sal_Int32 GetEntryCount() const
Definition: combobox.cxx:958
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1995
#define SAL_WARN_IF(condition, area, stream)
#define K
Definition: field.cxx:1075
MetricFormatter(Edit *pEdit)
Definition: field.cxx:1387
static sal_Int64 ConvertValue(sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, FieldUnit eInUnit, FieldUnit eOutUnit)
Definition: field.cxx:1145
void FieldFirst()
Definition: field.cxx:712
virtual void Last() override
Definition: field.cxx:1976
sal_Int64 GetLast() const
Definition: field.hxx:135
MetricField(vcl::Window *pParent, WinBits nWinStyle)
Definition: field.cxx:1567
sal_Unicode GetCharCode() const
Definition: event.hxx:52
virtual void ReformatAll() override
Definition: field.cxx:1794
virtual void Up() override
Definition: field.cxx:1688
FormatterBase(Edit *pField)
Definition: field.cxx:434
virtual void Up() override
Definition: field.cxx:838
virtual OUString CreateFieldText(sal_Int64 nValue) const override
Definition: field.cxx:1421
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: field.cxx:1574
sal_Int64 mnSpinSize
Definition: field.hxx:166
sal_Int64 mnFirst
Definition: field.hxx:167
virtual void Last()
Definition: spinfld.cxx:374
void SetDecimalDigits(sal_uInt16 nDigits)
Definition: field.cxx:583
virtual void Modify() override
Definition: field.cxx:1952
virtual void Modify() override
Definition: field.cxx:980
virtual void SetValue(sal_Int64 nNewValue, FieldUnit eInUnit)
Definition: field.cxx:1415
SAL_DLLPRIVATE void ImplNumericReformat()
Definition: field.cxx:532
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:951
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: spinfld.cxx:835
void * GetEntryData(sal_Int32 nPos) const
Definition: combobox.cxx:1321
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: field.cxx:1989
void SetUserValue(sal_Int64 nNewValue, FieldUnit eInUnit)
Definition: field.cxx:1464
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: field.cxx:816
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:684
#define SELECTION_MAX
CurrencyBox(vcl::Window *pParent, WinBits nWinStyle)
Definition: field.cxx:1982
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: field.cxx:773
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: field.cxx:2019
bool IsUseThousandSep() const
Definition: field.hxx:143
virtual ~NumericFormatter() override
Definition: field.cxx:559
MapUnit
static double ConvertDoubleValue(double nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, FieldUnit eInUnit, FieldUnit eOutUnit)
Definition: field.cxx:1236
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: field.cxx:964
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:159
virtual ~MetricFormatter() override
Definition: field.cxx:1393
sal_Int32 InsertEntry(const OUString &rStr, sal_Int32 nPos=COMBOBOX_APPEND)
Definition: combobox.cxx:872
const FieldUnitStringList & ImplGetFieldUnits()
Definition: svdata.cxx:271
virtual sal_Int64 GetValueFromString(const OUString &rStr) const override
Definition: field.cxx:1869
bool mbWrapOnLimits
Definition: field.hxx:161
virtual void SetText(const OUString &rStr) override
Definition: edit.cxx:2540
NumericFormatter(Edit *pEdit)
Definition: field.cxx:538
sal_Int64 ClipAgainstMinMax(sal_Int64 nValue) const
Definition: field.cxx:755
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:620
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: field.cxx:1772
aStr
NumericBox(vcl::Window *pParent, WinBits nWinStyle)
Definition: field.cxx:911
Size CalcMinimumSize() const override
Definition: combobox.cxx:1029
static bool ImplCurrencyProcessKeyInput(const KeyEvent &rKEvt, bool bUseThousandSep, const LocaleDataWrapper &rWrapper)
Definition: field.cxx:1818
#define SAL_MAX_INT64
virtual void Modify() override
Definition: field.cxx:832
sal_uInt16 mnDecimalDigits
Definition: field.hxx:185
virtual void SetValue(sal_Int64 nNewValue)
Definition: field.cxx:599
static bool TextToValue(const OUString &rStr, double &rValue, sal_Int64 nBaseValue, sal_uInt16 nDecDigits, const LocaleDataWrapper &rLocaleDataWrapper, FieldUnit eUnit)
Definition: field.cxx:1355
VclPtr< Edit > mpField
Definition: field.hxx:42
virtual void Modify() override
Definition: combobox.cxx:811
virtual void Reformat() override
Definition: field.cxx:1880
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: field.cxx:1728
bool IsMod2() const
Definition: keycod.hxx:62
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
Definition: window.cxx:2151
void setHeight(long nHeight)
static double nonValueDoubleToValueDouble(double nValue)
Definition: field.cxx:1140