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