LibreOffice Module vcl (master)  1
fmtfield.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 <tools/debug.hxx>
22 #include <comphelper/string.hxx>
24 #include <vcl/event.hxx>
25 #include <vcl/settings.hxx>
26 #include <vcl/commandevent.hxx>
27 #include <svl/zformat.hxx>
28 #include <vcl/fmtfield.hxx>
29 #include <vcl/weld.hxx>
31 #include <unotools/syslocale.hxx>
32 #include <map>
33 #include <rtl/math.hxx>
34 #include <rtl/ustrbuf.hxx>
35 #include <sal/log.hxx>
36 #include <osl/diagnose.h>
37 
38 using namespace ::com::sun::star::lang;
39 using namespace ::com::sun::star::util;
40 
41 // hmm. No support for regular expression. Well, I always (not really :) wanted to write a finite automat
42 // so here comes a finite automat ...
43 
44 namespace validation
45 {
46  // the states of our automat.
47  enum State
48  {
49  START, // at the very start of the string
50  NUM_START, // the very start of the number
51 
52  DIGIT_PRE_COMMA, // some pre-comma digits are read, perhaps including some thousand separators
53 
54  DIGIT_POST_COMMA, // reading digits after the comma
55  EXPONENT_START, // at the very start of the exponent value
56  // (means: not including the "e" which denotes the exponent)
57  EXPONENT_DIGIT, // currently reading the digits of the exponent
58 
59  END // reached the end of the string
60  };
61 
62  // a row in the transition table (means the set of states to be reached from a given state)
63  typedef ::std::map< sal_Unicode, State > StateTransitions;
64 
65  // a single transition
66  typedef StateTransitions::value_type Transition;
67 
68  // the complete transition table
69  typedef ::std::map< State, StateTransitions > TransitionTable;
70 
71  // the validator class
73  {
74  private:
75  TransitionTable m_aTransitions;
76 
77  public:
78  NumberValidator( const sal_Unicode _cThSep, const sal_Unicode _cDecSep );
79 
80  bool isValidNumericFragment( const OUString& _rText );
81 
82  private:
83  bool implValidateNormalized( const OUString& _rText );
84  };
85 
86  static void lcl_insertStopTransition( StateTransitions& _rRow )
87  {
88  _rRow.insert( Transition( '_', END ) );
89  }
90 
91  static void lcl_insertStartExponentTransition( StateTransitions& _rRow )
92  {
93  _rRow.insert( Transition( 'e', EXPONENT_START ) );
94  }
95 
96  static void lcl_insertSignTransitions( StateTransitions& _rRow, const State eNextState )
97  {
98  _rRow.insert( Transition( '-', eNextState ) );
99  _rRow.insert( Transition( '+', eNextState ) );
100  }
101 
102  static void lcl_insertDigitTransitions( StateTransitions& _rRow, const State eNextState )
103  {
104  for ( sal_Unicode aChar = '0'; aChar <= '9'; ++aChar )
105  _rRow.insert( Transition( aChar, eNextState ) );
106  }
107 
108  static void lcl_insertCommonPreCommaTransitions( StateTransitions& _rRow, const sal_Unicode _cThSep, const sal_Unicode _cDecSep )
109  {
110  // digits are allowed
112 
113  // the thousand separator is allowed
114  _rRow.insert( Transition( _cThSep, DIGIT_PRE_COMMA ) );
115 
116  // a comma is allowed
117  _rRow.insert( Transition( _cDecSep, DIGIT_POST_COMMA ) );
118  }
119 
121  {
122  // build up our transition table
123 
124  // how to proceed from START
125  {
126  StateTransitions& rRow = m_aTransitions[ START ];
127  rRow.insert( Transition( '_', NUM_START ) );
128  // if we encounter the normalizing character, we want to proceed with the number
129  }
130 
131  // how to proceed from NUM_START
132  {
133  StateTransitions& rRow = m_aTransitions[ NUM_START ];
134 
135  // a sign is allowed
137 
138  // common transitions for the two pre-comma states
139  lcl_insertCommonPreCommaTransitions( rRow, _cThSep, _cDecSep );
140 
141  // the exponent may start here
142  // (this would mean string like "_+e10_", but this is a valid fragment, though no valid number)
144  }
145 
146  // how to proceed from DIGIT_PRE_COMMA
147  {
148  StateTransitions& rRow = m_aTransitions[ DIGIT_PRE_COMMA ];
149 
150  // common transitions for the two pre-comma states
151  lcl_insertCommonPreCommaTransitions( rRow, _cThSep, _cDecSep );
152 
153  // the exponent may start here
155 
156  // the final transition indicating the end of the string
157  // (if there is no comma and no post-comma, then the string may end here)
158  lcl_insertStopTransition( rRow );
159  }
160 
161  // how to proceed from DIGIT_POST_COMMA
162  {
163  StateTransitions& rRow = m_aTransitions[ DIGIT_POST_COMMA ];
164 
165  // there might be digits, which would keep the state at DIGIT_POST_COMMA
167 
168  // the exponent may start here
170 
171  // the string may end here
172  lcl_insertStopTransition( rRow );
173  }
174 
175  // how to proceed from EXPONENT_START
176  {
177  StateTransitions& rRow = m_aTransitions[ EXPONENT_START ];
178 
179  // there may be a sign
181 
182  // there may be digits
184 
185  // the string may end here
186  lcl_insertStopTransition( rRow );
187  }
188 
189  // how to proceed from EXPONENT_DIGIT
190  {
191  StateTransitions& rRow = m_aTransitions[ EXPONENT_DIGIT ];
192 
193  // there may be digits
195 
196  // the string may end here
197  lcl_insertStopTransition( rRow );
198  }
199 
200  // how to proceed from END
201  {
202  /*StateTransitions& rRow =*/ m_aTransitions[ EXPONENT_DIGIT ];
203  // no valid transition to leave this state
204  // (note that we, for consistency, nevertheless want to have a row in the table)
205  }
206  }
207 
208  bool NumberValidator::implValidateNormalized( const OUString& _rText )
209  {
210  const sal_Unicode* pCheckPos = _rText.getStr();
211  State eCurrentState = START;
212 
213  while ( END != eCurrentState )
214  {
215  // look up the transition row for the current state
216  TransitionTable::const_iterator aRow = m_aTransitions.find( eCurrentState );
217  DBG_ASSERT( m_aTransitions.end() != aRow,
218  "NumberValidator::implValidateNormalized: invalid transition table (row not found)!" );
219 
220  if ( m_aTransitions.end() != aRow )
221  {
222  // look up the current character in this row
223  StateTransitions::const_iterator aTransition = aRow->second.find( *pCheckPos );
224  if ( aRow->second.end() != aTransition )
225  {
226  // there is a valid transition for this character
227  eCurrentState = aTransition->second;
228  ++pCheckPos;
229  continue;
230  }
231  }
232 
233  // if we're here, there is no valid transition
234  break;
235  }
236 
237  DBG_ASSERT( ( END != eCurrentState ) || ( 0 == *pCheckPos ),
238  "NumberValidator::implValidateNormalized: inconsistency!" );
239  // if we're at END, then the string should be done, too - the string should be normalized, means ending
240  // a "_" and not containing any other "_" (except at the start), and "_" is the only possibility
241  // to reach the END state
242 
243  // the string is valid if and only if we reached the final state
244  return ( END == eCurrentState );
245  }
246 
247  bool NumberValidator::isValidNumericFragment( const OUString& _rText )
248  {
249  if ( _rText.isEmpty() )
250  // empty strings are always allowed
251  return true;
252 
253  // normalize the string
254  OUString sNormalized( "_" );
255  sNormalized += _rText;
256  sNormalized += "_";
257 
258  return implValidateNormalized( sNormalized );
259  }
260 }
261 
264 
266 {
267  if (!s_cFormatter)
268  {
269  // get the Office's locale and translate
270  LanguageType eSysLanguage = SvtSysLocale().GetLanguageTag().getLanguageType( false);
273  eSysLanguage);
274  }
275  return s_cFormatter;
276 }
277 
279 {
280  ++s_nReferences;
281 }
282 
284 {
285  if (--s_nReferences == 0)
286  {
287  delete s_cFormatter;
288  s_cFormatter = nullptr;
289  }
290 }
291 
292 
294  :SpinField(pParent, nStyle)
295  ,m_aLastSelection(0,0)
296  ,m_dMinValue(0)
297  ,m_dMaxValue(0)
298  ,m_bHasMin(false)
299  ,m_bHasMax(false)
300  ,m_bStrictFormat(true)
301  ,m_bEnableEmptyField(true)
302  ,m_bAutoColor(false)
303  ,m_bEnableNaN(false)
306  ,m_dCurrentValue(0)
307  ,m_dDefaultValue(0)
308  ,m_nFormatKey(0)
309  ,m_pFormatter(nullptr)
310  ,m_dSpinSize(1)
311  ,m_dSpinFirst(-1000000)
312  ,m_dSpinLast(1000000)
313  ,m_bTreatAsNumber(true)
314  ,m_pLastOutputColor(nullptr)
316 {
317 }
318 
319 void FormattedField::SetText(const OUString& rStr)
320 {
321 
322  SpinField::SetText(rStr);
324 }
325 
326 void FormattedField::SetText( const OUString& rStr, const Selection& rNewSelection )
327 {
328 
329  SpinField::SetText( rStr, rNewSelection );
331 }
332 
333 void FormattedField::SetTextFormatted(const OUString& rStr)
334 {
335  SAL_INFO_IF(ImplGetFormatter()->IsTextFormat(m_nFormatKey), "svtools",
336  "FormattedField::SetTextFormatted : valid only with text formats !");
337 
338  m_sCurrentTextValue = rStr;
339 
340  OUString sFormatted;
341  double dNumber = 0.0;
342  // IsNumberFormat changes the format key parameter
343  sal_uInt32 nTempFormatKey = static_cast< sal_uInt32 >( m_nFormatKey );
345  ImplGetFormatter()->IsNumberFormat(m_sCurrentTextValue, nTempFormatKey, dNumber) )
346  {
347  ImplGetFormatter()->GetInputLineString(dNumber, m_nFormatKey, sFormatted);
348  }
349  else
350  {
352  m_nFormatKey,
353  sFormatted,
355  }
356 
357  // calculate the new selection
358  Selection aSel(GetSelection());
359  Selection aNewSel(aSel);
360  aNewSel.Justify();
361  sal_Int32 nNewLen = sFormatted.getLength();
362  sal_Int32 nCurrentLen = GetText().getLength();
363  if ((nNewLen > nCurrentLen) && (aNewSel.Max() == nCurrentLen))
364  { // the new text is longer and the cursor was behind the last char (of the old text)
365  if (aNewSel.Min() == 0)
366  { // the whole text was selected -> select the new text on the whole, too
367  aNewSel.Max() = nNewLen;
368  if (!nCurrentLen)
369  { // there wasn't really a previous selection (as there was no previous text), we're setting a new one -> check the selection options
371  if (nSelOptions & SelectionOptions::ShowFirst)
372  { // selection should be from right to left -> swap min and max
373  aNewSel.Min() = aNewSel.Max();
374  aNewSel.Max() = 0;
375  }
376  }
377  }
378  else if (aNewSel.Max() == aNewSel.Min())
379  { // there was no selection -> set the cursor behind the new last char
380  aNewSel.Max() = nNewLen;
381  aNewSel.Min() = nNewLen;
382  }
383  }
384  else if (aNewSel.Max() > nNewLen)
385  aNewSel.Max() = nNewLen;
386  else
387  aNewSel = aSel; // don't use the justified version
388  SpinField::SetText(sFormatted, aNewSel);
390 }
391 
392 OUString const & FormattedField::GetTextValue() const
393 {
394  if (m_ValueState != valueString )
395  {
396  const_cast<FormattedField*>(this)->m_sCurrentTextValue = GetText();
397  const_cast<FormattedField*>(this)->m_ValueState = valueString;
398  }
399  return m_sCurrentTextValue;
400 }
401 
402 void FormattedField::EnableNotANumber( bool _bEnable )
403 {
404  if ( m_bEnableNaN == _bEnable )
405  return;
406 
407  m_bEnableNaN = _bEnable;
408 }
409 
410 void FormattedField::SetAutoColor(bool _bAutomatic)
411 {
412  if (_bAutomatic == m_bAutoColor)
413  return;
414 
415  m_bAutoColor = _bAutomatic;
416  if (m_bAutoColor)
417  { // if auto color is switched on, adjust the current text color, too
418  if (m_pLastOutputColor)
420  else
422  }
423 }
424 
425 void FormattedField::impl_Modify(bool makeValueDirty)
426 {
427 
428  if (!IsStrictFormat())
429  {
430  if(makeValueDirty)
433  return;
434  }
435 
436  OUString sCheck = GetText();
437  if (CheckText(sCheck))
438  {
439  m_sLastValidText = sCheck;
441  if(makeValueDirty)
443  }
444  else
445  {
447  }
448 
450 }
451 
453 {
454 
455  impl_Modify();
456 }
457 
458 void FormattedField::ImplSetTextImpl(const OUString& rNew, Selection const * pNewSel)
459 {
460 
461  if (m_bAutoColor)
462  {
463  if (m_pLastOutputColor)
465  else
467  }
468 
469  if (pNewSel)
470  SpinField::SetText(rNew, *pNewSel);
471  else
472  {
473  Selection aSel(GetSelection());
474  aSel.Justify();
475 
476  sal_Int32 nNewLen = rNew.getLength();
477  sal_Int32 nCurrentLen = GetText().getLength();
478 
479  if ((nNewLen > nCurrentLen) && (aSel.Max() == nCurrentLen))
480  { // new text is longer and the cursor is behind the last char
481  if (aSel.Min() == 0)
482  {
483  if (!nCurrentLen)
484  { // there wasn't really a previous selection (as there was no previous text)
485  aSel.Max() = 0;
486  }
487  else
488  { // the whole text was selected -> select the new text on the whole, too
489  aSel.Max() = nNewLen;
490  }
491  }
492  else if (aSel.Max() == aSel.Min())
493  { // there was no selection -> set the cursor behind the new last char
494  aSel.Max() = nNewLen;
495  aSel.Min() = nNewLen;
496  }
497  }
498  else if (aSel.Max() > nNewLen)
499  aSel.Max() = nNewLen;
500  SpinField::SetText(rNew, aSel);
501  }
502 
503  m_ValueState = valueDirty; // not always necessary, but better re-evaluate for safety reasons
504 }
505 
507 {
508  if (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT)
510  return SpinField::PreNotify(rNEvt);
511 }
512 
514 {
515 
516  m_nFormatKey = nFormatKey;
517  bool bNeedFormatter = (m_pFormatter == nullptr) && (nFormatKey != 0);
518  if (bNeedFormatter)
519  {
520  ImplGetFormatter(); // this creates a standard formatter
521 
522  // It might happen that the standard formatter makes no sense here, but it takes a default
523  // format. Thus, it is possible to set one of the other standard keys (which are spanning
524  // across multiple formatters).
525  m_nFormatKey = nFormatKey;
526  // When calling SetFormatKey without a formatter, the key must be one of the standard values
527  // that is available for all formatters (and, thus, also in this new one).
528  DBG_ASSERT(m_pFormatter->GetEntry(nFormatKey) != nullptr, "FormattedField::ImplSetFormatKey : invalid format key !");
529  }
530 }
531 
533 {
534  bool bNoFormatter = (m_pFormatter == nullptr);
535  ImplSetFormatKey(nFormatKey);
537 }
538 
539 void FormattedField::SetFormatter(SvNumberFormatter* pFormatter, bool bResetFormat)
540 {
541 
542  if (bResetFormat)
543  {
544  m_pFormatter = pFormatter;
545 
546  // calc the default format key from the Office's UI locale
547  if ( m_pFormatter )
548  {
549  // get the Office's locale and translate
550  LanguageType eSysLanguage = SvtSysLocale().GetLanguageTag().getLanguageType( false);
551  // get the standard numeric format for this language
552  m_nFormatKey = m_pFormatter->GetStandardFormat( SvNumFormatType::NUMBER, eSysLanguage );
553  }
554  else
555  m_nFormatKey = 0;
556  }
557  else
558  {
559  LanguageType aOldLang;
560  OUString sOldFormat = GetFormat(aOldLang);
561 
562  sal_uInt32 nDestKey = pFormatter->TestNewString(sOldFormat);
563  if (nDestKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
564  {
565  // language of the new formatter
566  const SvNumberformat* pDefaultEntry = pFormatter->GetEntry(0);
567  LanguageType aNewLang = pDefaultEntry ? pDefaultEntry->GetLanguage() : LANGUAGE_DONTKNOW;
568 
569  // convert the old format string into the new language
570  sal_Int32 nCheckPos;
572  pFormatter->PutandConvertEntry(sOldFormat, nCheckPos, nType, nDestKey, aOldLang, aNewLang, true);
573  m_nFormatKey = nDestKey;
574  }
575  m_pFormatter = pFormatter;
576  }
577 
579 }
580 
582 {
583  const SvNumberformat* pFormatEntry = ImplGetFormatter()->GetEntry(m_nFormatKey);
584  DBG_ASSERT(pFormatEntry != nullptr, "FormattedField::GetFormat: no number format for the given format key.");
585  OUString sFormatString = pFormatEntry ? pFormatEntry->GetFormatstring() : OUString();
586  eLang = pFormatEntry ? pFormatEntry->GetLanguage() : LANGUAGE_DONTKNOW;
587 
588  return sFormatString;
589 }
590 
591 bool FormattedField::SetFormat(const OUString& rFormatString, LanguageType eLang)
592 {
593  sal_uInt32 nNewKey = ImplGetFormatter()->TestNewString(rFormatString, eLang);
594  if (nNewKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
595  {
596  sal_Int32 nCheckPos;
598  OUString rFormat(rFormatString);
599  if (!ImplGetFormatter()->PutEntry(rFormat, nCheckPos, nType, nNewKey, eLang))
600  return false;
601  DBG_ASSERT(nNewKey != NUMBERFORMAT_ENTRY_NOT_FOUND, "FormattedField::SetFormatString : PutEntry returned an invalid key !");
602  }
603 
604  if (nNewKey != m_nFormatKey)
605  SetFormatKey(nNewKey);
606  return true;
607 }
608 
610 {
611  DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
612  "FormattedField::GetThousandsSep : Are you sure what you are doing when setting the precision of a text format?");
613 
614  bool bThousand, IsRed;
615  sal_uInt16 nPrecision, nLeadingCnt;
616  ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nLeadingCnt);
617 
618  return bThousand;
619 }
620 
621 void FormattedField::SetThousandsSep(bool _bUseSeparator)
622 {
623  DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
624  "FormattedField::SetThousandsSep : Are you sure what you are doing when setting the precision of a text format?");
625 
626  // get the current settings
627  bool bThousand, IsRed;
628  sal_uInt16 nPrecision, nLeadingCnt;
629  ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nLeadingCnt);
630  if (bThousand == _bUseSeparator)
631  return;
632 
633  // we need the language for the following
634  LanguageType eLang;
635  GetFormat(eLang);
636 
637  // generate a new format ...
638  OUString sFmtDescription = ImplGetFormatter()->GenerateFormat(m_nFormatKey, eLang, _bUseSeparator, IsRed, nPrecision, nLeadingCnt);
639  // ... and introduce it to the formatter
640  sal_Int32 nCheckPos = 0;
641  sal_uInt32 nNewKey;
643  ImplGetFormatter()->PutEntry(sFmtDescription, nCheckPos, nType, nNewKey, eLang);
644 
645  // set the new key
646  ImplSetFormatKey(nNewKey);
648 }
649 
651 {
652  DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
653  "FormattedField::GetDecimalDigits : Are you sure what you are doing when setting the precision of a text format?");
654 
655  bool bThousand, IsRed;
656  sal_uInt16 nPrecision, nLeadingCnt;
657  ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nLeadingCnt);
658 
659  return nPrecision;
660 }
661 
662 void FormattedField::SetDecimalDigits(sal_uInt16 _nPrecision)
663 {
664  DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
665  "FormattedField::SetDecimalDigits : Are you sure what you are doing when setting the precision of a text format?");
666 
667  // get the current settings
668  bool bThousand, IsRed;
669  sal_uInt16 nPrecision, nLeadingCnt;
670  ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nLeadingCnt);
671  if (nPrecision == _nPrecision)
672  return;
673 
674  // we need the language for the following
675  LanguageType eLang;
676  GetFormat(eLang);
677 
678  // generate a new format ...
679  OUString sFmtDescription = ImplGetFormatter()->GenerateFormat(m_nFormatKey, eLang, bThousand, IsRed, _nPrecision, nLeadingCnt);
680  // ... and introduce it to the formatter
681  sal_Int32 nCheckPos = 0;
682  sal_uInt32 nNewKey;
684  ImplGetFormatter()->PutEntry(sFmtDescription, nCheckPos, nType, nNewKey, eLang);
685 
686  // set the new key
687  ImplSetFormatKey(nNewKey);
689 }
690 
692 {
693  m_pLastOutputColor = nullptr;
694 
695  if ( (_nWhat == FORMAT_CHANGE_TYPE::FORMATTER) && m_pFormatter )
697 
698  ReFormat();
699 }
700 
702 {
703  // remember the old text
704  OUString sOld( GetText() );
705 
706  // do the reformat
707  ReFormat();
708 
709  // did the text change?
710  if ( GetText() != sOld )
711  { // consider the field as modified,
712  // but we already have the most recent value;
713  // don't reparse it from the text
714  // (can lead to data loss when the format is lossy,
715  // as is e.g. our default date format: 2-digit year!)
716  impl_Modify(false);
717  }
718 }
719 
721 {
722  if (!IsEmptyFieldEnabled() || !GetText().isEmpty())
723  {
724  if (TreatingAsNumber())
725  {
726  double dValue = GetValue();
727  if ( m_bEnableNaN && ::rtl::math::isNan( dValue ) )
728  return;
729  ImplSetValue( dValue, true );
730  }
731  else
733  }
734 }
735 
737 {
738 
739  if ((rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !IsReadOnly())
740  {
741  const KeyEvent& rKEvt = *rNEvt.GetKeyEvent();
742  sal_uInt16 nMod = rKEvt.GetKeyCode().GetModifier();
743  switch ( rKEvt.GetKeyCode().GetCode() )
744  {
745  case KEY_UP:
746  case KEY_DOWN:
747  case KEY_PAGEUP:
748  case KEY_PAGEDOWN:
749  if (!nMod && ImplGetFormatter()->IsTextFormat(m_nFormatKey))
750  {
751  // the base class would translate this into calls to Up/Down/First/Last,
752  // but we don't want this if we are text-formatted
753  return true;
754  }
755  }
756  }
757 
758  if ((rNEvt.GetType() == MouseNotifyEvent::COMMAND) && !IsReadOnly())
759  {
760  const CommandEvent* pCommand = rNEvt.GetCommandEvent();
761  if (pCommand->GetCommand() == CommandEventId::Wheel)
762  {
763  const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData();
765  {
766  // same as above : prevent the base class from doing Up/Down-calls
767  // (normally I should put this test into the Up/Down methods itself, shouldn't I ?)
768  // FS - 71553 - 19.01.00
769  return true;
770  }
771  }
772  }
773 
774  if (rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS)
775  {
776  // special treatment for empty texts
777  if (GetText().isEmpty())
778  {
779  if (!IsEmptyFieldEnabled())
780  {
781  if (TreatingAsNumber())
782  {
784  Modify();
786  }
787  else
788  {
789  OUString sNew = GetTextValue();
790  if (!sNew.isEmpty())
791  SetTextFormatted(sNew);
792  else
795  }
796  }
797  }
798  else
799  {
800  Commit();
801  }
802  }
803 
804  return SpinField::EventNotify( rNEvt );
805 }
806 
808 {
809  DBG_ASSERT(m_bTreatAsNumber, "FormattedField::SetMinValue : only to be used in numeric mode !");
810 
811  m_dMinValue = dMin;
812  m_bHasMin = true;
813  // for checking the current value at the new border -> ImplSetValue
814  ReFormat();
815 }
816 
818 {
819  DBG_ASSERT(m_bTreatAsNumber, "FormattedField::SetMaxValue : only to be used in numeric mode !");
820 
821  m_dMaxValue = dMax;
822  m_bHasMax = true;
823  // for checking the current value at the new border -> ImplSetValue
824  ReFormat();
825 }
826 
827 void FormattedField::SetTextValue(const OUString& rText)
828 {
829  SetText(rText);
830  ReFormat();
831 }
832 
834 {
835  if (bEnable == m_bEnableEmptyField)
836  return;
837 
838  m_bEnableEmptyField = bEnable;
839  if (!m_bEnableEmptyField && GetText().isEmpty())
841 }
842 
843 void FormattedField::ImplSetValue(double dVal, bool bForce)
844 {
845 
846  if (m_bHasMin && (dVal<m_dMinValue))
847  dVal = m_dMinValue;
848  if (m_bHasMax && (dVal>m_dMaxValue))
849  dVal = m_dMaxValue;
850  if (!bForce && (dVal == GetValue()))
851  return;
852 
853  DBG_ASSERT(ImplGetFormatter() != nullptr, "FormattedField::ImplSetValue : can't set a value without a formatter !");
854 
856  m_dCurrentValue = dVal;
857 
858  if (!m_aOutputHdl.IsSet() || !m_aOutputHdl.Call(*this))
859  {
860  OUString sNewText;
862  {
863  // first convert the number as string in standard format
864  OUString sTemp;
866  // then encode the string in the corresponding text format
868  }
869  else
870  {
872  {
874  }
875  else
876  {
878  }
879  }
880  ImplSetTextImpl(sNewText, nullptr);
881  DBG_ASSERT(CheckText(sNewText), "FormattedField::ImplSetValue : formatted string doesn't match the criteria !");
882  }
883 
885 }
886 
887 bool FormattedField::ImplGetValue(double& dNewVal)
888 {
889  dNewVal = m_dCurrentValue;
890  if (m_ValueState == valueDouble)
891  return true;
892 
893  dNewVal = m_dDefaultValue;
894  OUString sText(GetText());
895  if (sText.isEmpty())
896  return true;
897 
898  bool bUseExternalFormatterValue = false;
899  if (m_aInputHdl.IsSet())
900  {
901  sal_Int64 nResult;
902  auto eState = m_aInputHdl.Call(&nResult);
903  bUseExternalFormatterValue = eState != TRISTATE_INDET;
904  if (bUseExternalFormatterValue)
905  {
906  if (eState == TRISTATE_TRUE)
907  {
908  dNewVal = nResult;
910  }
911  else
912  dNewVal = m_dCurrentValue;
913  }
914  }
915 
916  if (!bUseExternalFormatterValue)
917  {
918  DBG_ASSERT(ImplGetFormatter() != nullptr, "FormattedField::ImplGetValue : can't give you a current value without a formatter !");
919 
920  sal_uInt32 nFormatKey = m_nFormatKey; // IsNumberFormat changes the FormatKey!
921 
922  if (ImplGetFormatter()->IsTextFormat(nFormatKey) && m_bTreatAsNumber)
923  // for detection of values like "1,1" in fields that are formatted as text
924  nFormatKey = 0;
925 
926  // special treatment for percentage formatting
927  if (ImplGetFormatter()->GetType(m_nFormatKey) == SvNumFormatType::PERCENT)
928  {
929  // the language of our format
931  // the default number format for this language
932  sal_uLong nStandardNumericFormat = m_pFormatter->GetStandardFormat(SvNumFormatType::NUMBER, eLanguage);
933 
934  sal_uInt32 nTempFormat = nStandardNumericFormat;
935  double dTemp;
936  if (m_pFormatter->IsNumberFormat(sText, nTempFormat, dTemp) &&
937  SvNumFormatType::NUMBER == m_pFormatter->GetType(nTempFormat))
938  // the string is equivalent to a number formatted one (has no % sign) -> append it
939  sText += "%";
940  // (with this, an input of '3' becomes '3%', which then by the formatter is translated
941  // into 0.03. Without this, the formatter would give us the double 3 for an input '3',
942  // which equals 300 percent.
943  }
944  if (!ImplGetFormatter()->IsNumberFormat(sText, nFormatKey, dNewVal))
945  return false;
946  }
947 
948  if (m_bHasMin && (dNewVal<m_dMinValue))
949  dNewVal = m_dMinValue;
950  if (m_bHasMax && (dNewVal>m_dMaxValue))
951  dNewVal = m_dMaxValue;
952  return true;
953 }
954 
955 void FormattedField::SetValue(double dVal)
956 {
958 }
959 
961 {
962 
963  if ( !ImplGetValue( m_dCurrentValue ) )
964  {
965  if ( m_bEnableNaN )
966  ::rtl::math::setNan( &m_dCurrentValue );
967  else
969  }
970 
972  return m_dCurrentValue;
973 }
974 
976 {
978 }
979 
980 bool FormattedField::set_property(const OString &rKey, const OUString &rValue)
981 {
982  if (rKey == "digits")
983  SetDecimalDigits(rValue.toInt32());
984  else
985  return SpinField::set_property(rKey, rValue);
986  return true;
987 }
988 
990 {
992 
993  sal_Int64 nValue = std::round(GetValue() * nScale);
994  sal_Int64 nSpinSize = std::round(m_dSpinSize * nScale);
995  sal_Int64 nRemainder = m_bDisableRemainderFactor ? 0 : nValue % nSpinSize;
996  if (nValue >= 0)
997  nValue = (nRemainder == 0) ? nValue + nSpinSize : nValue + nSpinSize - nRemainder;
998  else
999  nValue = (nRemainder == 0) ? nValue + nSpinSize : nValue - nRemainder;
1000 
1001  // setValue handles under- and overflows (min/max) automatically
1002  SetValue(static_cast<double>(nValue) / nScale);
1003  SetModifyFlag();
1004  Modify();
1005 
1006  SpinField::Up();
1007 }
1008 
1010 {
1012 
1013  sal_Int64 nValue = std::round(GetValue() * nScale);
1014  sal_Int64 nSpinSize = std::round(m_dSpinSize * nScale);
1015  sal_Int64 nRemainder = m_bDisableRemainderFactor ? 0 : nValue % nSpinSize;
1016  if (nValue >= 0)
1017  nValue = (nRemainder == 0) ? nValue - nSpinSize : nValue - nRemainder;
1018  else
1019  nValue = (nRemainder == 0) ? nValue - nSpinSize : nValue - nSpinSize - nRemainder;
1020 
1021  // setValue handles under- and overflows (min/max) automatically
1022  SetValue(static_cast<double>(nValue) / nScale);
1023  SetModifyFlag();
1024  Modify();
1025 
1026  SpinField::Down();
1027 }
1028 
1030 {
1031  if (m_bHasMin)
1032  {
1034  SetModifyFlag();
1035  Modify();
1036  }
1037 
1038  SpinField::First();
1039 }
1040 
1042 {
1043  if (m_bHasMax)
1044  {
1046  SetModifyFlag();
1047  Modify();
1048  }
1049 
1050  SpinField::Last();
1051 }
1052 
1054 {
1056 }
1057 
1059  : FormattedField(pParent, nStyle)
1060 {
1062 }
1063 
1065 
1067 {
1070 }
1071 
1072 bool DoubleNumericField::CheckText(const OUString& sText) const
1073 {
1074  // We'd like to implement this using the NumberFormatter::IsNumberFormat, but unfortunately, this doesn't
1075  // recognize fragments of numbers (like, for instance "1e", which happens during entering e.g. "1e10")
1076  // Thus, the roundabout way via a regular expression
1077  return m_pNumberValidator->isValidNumericFragment( sText );
1078 }
1079 
1081 {
1082  // the thousands and the decimal separator are language dependent
1083  const SvNumberformat* pFormatEntry = ImplGetFormatter()->GetEntry(m_nFormatKey);
1084 
1085  sal_Unicode cSeparatorThousand = ',';
1086  sal_Unicode cSeparatorDecimal = '.';
1087  if (pFormatEntry)
1088  {
1089  LocaleDataWrapper aLocaleInfo( LanguageTag( pFormatEntry->GetLanguage()) );
1090 
1091  OUString sSeparator = aLocaleInfo.getNumThousandSep();
1092  if (!sSeparator.isEmpty())
1093  cSeparatorThousand = sSeparator[0];
1094 
1095  sSeparator = aLocaleInfo.getNumDecimalSep();
1096  if (!sSeparator.isEmpty())
1097  cSeparatorDecimal = sSeparator[0];
1098  }
1099 
1100  m_pNumberValidator.reset(new validation::NumberValidator( cSeparatorThousand, cSeparatorDecimal ));
1101 }
1102 
1104  :FormattedField(pParent, nStyle)
1105  ,m_bChangingFormat(false)
1106 {
1107  m_bPrependCurrSym = false;
1108 
1109  // initialize with a system currency format
1112 }
1113 
1115 {
1116  if (m_bChangingFormat)
1117  {
1119  return;
1120  }
1121 
1122  switch (nWhat)
1123  {
1127  // the aspects which changed don't take our currency settings into account (in fact, they most probably
1128  // destroyed them)
1130  break;
1132  OSL_FAIL("DoubleCurrencyField::FormatChanged : somebody modified my key !");
1133  // We always build our own format from the settings we get via special methods (setCurrencySymbol etc.).
1134  // Nobody but ourself should modify the format key directly!
1135  break;
1136  default: break;
1137  }
1138 
1140 }
1141 
1142 void DoubleCurrencyField::setCurrencySymbol(const OUString& rSymbol)
1143 {
1144  if (m_sCurrencySymbol == rSymbol)
1145  return;
1146 
1147  m_sCurrencySymbol = rSymbol;
1150 }
1151 
1153 {
1154  if (m_bPrependCurrSym == _bPrepend)
1155  return;
1156 
1157  m_bPrependCurrSym = _bPrepend;
1160 }
1161 
1163 {
1164  // the old settings
1165  LanguageType eLanguage;
1166  GetFormat(eLanguage);
1167  bool bThSep = GetThousandsSep();
1168  sal_uInt16 nDigits = GetDecimalDigits();
1169 
1170  // build a new format string with the base class' and my own settings
1171 
1172  /* Strangely with gcc 4.6.3 this needs a temporary LanguageTag, otherwise
1173  * there's
1174  * error: request for member 'getNumThousandSep' in 'aLocaleInfo', which is
1175  * of non-class type 'LocaleDataWrapper(LanguageTag)' */
1176  LanguageTag aLanguageTag( eLanguage);
1177  LocaleDataWrapper aLocaleInfo( aLanguageTag );
1178 
1179  OUStringBuffer sNewFormat;
1180  if (bThSep)
1181  {
1182  sNewFormat.append('#');
1183  sNewFormat.append(aLocaleInfo.getNumThousandSep());
1184  sNewFormat.append("##0");
1185  }
1186  else
1187  sNewFormat.append('0');
1188 
1189  if (nDigits)
1190  {
1191  sNewFormat.append(aLocaleInfo.getNumDecimalSep());
1192 
1193  OUStringBuffer sTemp;
1194  comphelper::string::padToLength(sTemp, nDigits, '0');
1195  sNewFormat.append(sTemp);
1196  }
1197 
1198  if (getPrependCurrSym())
1199  {
1200  OUString sSymbol = getCurrencySymbol();
1201  sSymbol = comphelper::string::stripStart(sSymbol, ' ');
1202  sSymbol = comphelper::string::stripEnd(sSymbol, ' ');
1203 
1204  OUStringBuffer sTemp("[$");
1205  sTemp.append(sSymbol);
1206  sTemp.append("] ");
1207  sTemp.append(sNewFormat);
1208 
1209  // for negative values : $ -0.00, not -$ 0.00...
1210  // (the real solution would be a possibility to choose a "positive currency format" and a "negative currency format"...
1211  // But not now... (and hey, you could take a formatted field for this...))
1212  // FS - 31.03.00 74642
1213  sTemp.append(";[$");
1214  sTemp.append(sSymbol);
1215  sTemp.append("] -");
1216  sTemp.append(sNewFormat);
1217 
1218  sNewFormat = sTemp;
1219  }
1220  else
1221  {
1222  OUString sTemp = getCurrencySymbol();
1223  sTemp = comphelper::string::stripStart(sTemp, ' ');
1224  sTemp = comphelper::string::stripEnd(sTemp, ' ');
1225 
1226  sNewFormat.append(" [$");
1227  sNewFormat.append(sTemp);
1228  sNewFormat.append(']');
1229  }
1230 
1231  // set this new basic format
1232  m_bChangingFormat = true;
1233  SetFormat(sNewFormat.makeStringAndClear(), eLanguage);
1234  m_bChangingFormat = false;
1235 }
1236 
1237 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool SetFormat(const OUString &rFormatString, LanguageType eLang)
Definition: fmtfield.cxx:591
virtual bool set_property(const OString &rKey, const OUString &rValue) override
Definition: fmtfield.cxx:980
bool m_bEnableNaN
Definition: fmtfield.hxx:72
OString stripEnd(const OString &rIn, sal_Char c)
bool isValidNumericFragment(const OUString &_rText)
Definition: fmtfield.cxx:247
bool m_bStrictFormat
Definition: fmtfield.hxx:68
bool IsEmptyFieldEnabled() const
Definition: fmtfield.hxx:121
virtual ~DoubleNumericField() override
virtual void FormatChanged(FORMAT_CHANGE_TYPE nWhat) override
Definition: fmtfield.cxx:1066
static void lcl_insertStopTransition(StateTransitions &_rRow)
Definition: fmtfield.cxx:86
static void lcl_insertStartExponentTransition(StateTransitions &_rRow)
Definition: fmtfield.cxx:91
#define KEY_PAGEDOWN
Definition: keycodes.hxx:117
SvNumberFormatter * ImplGetFormatter() const
Definition: fmtfield.hxx:255
const CommandEvent * GetCommandEvent() const
Definition: event.hxx:318
void SetFormatter(SvNumberFormatter *pFormatter, bool bResetFormat=true)
Definition: fmtfield.cxx:539
#define KEY_PAGEUP
Definition: keycodes.hxx:116
LanguageType getLanguageType(bool bResolveSystem=true) const
SelectionOptions GetSelectionOptions() const
SelectionOptions
Definition: settings.hxx:201
void GetOutputString(const double &fOutNumber, sal_uInt32 nFIndex, OUString &sOutString, Color **ppColor, bool bUseStarFormat=false)
FORMAT_CHANGE_TYPE
Definition: fmtfield.hxx:30
sal_uIntPtr sal_uLong
#define SAL_INFO_IF(condition, area, stream)
const StyleSettings & GetStyleSettings() const
static VCL_DLLPUBLIC SvNumberFormatter * GetFormatter()
Definition: fmtfield.cxx:265
Link< sal_Int64 *, TriState > m_aInputHdl
Definition: fmtfield.hxx:262
virtual void Last() override
Definition: fmtfield.cxx:1041
SvNumFormatType GetType(sal_uInt32 nFIndex) const
OUString m_sDefaultText
Definition: fmtfield.hxx:92
::std::map< sal_Unicode, State > StateTransitions
Definition: fmtfield.cxx:63
sal_uInt16 GetCode() const
Definition: keycod.hxx:53
void ReFormat()
Definition: fmtfield.cxx:720
virtual void SetText(const OUString &rStr) override
Definition: fmtfield.cxx:319
const KeyEvent * GetKeyEvent() const
Definition: event.hxx:302
sal_uInt32 TestNewString(const OUString &sFormatString, LanguageType eLnge=LANGUAGE_DONTKNOW)
virtual bool set_property(const OString &rKey, const OUString &rValue) override
Definition: edit.cxx:176
virtual void First() override
Definition: fmtfield.cxx:1029
OUString m_sCurrencySymbol
Definition: fmtfield.hxx:298
virtual void Up()
Definition: spinfld.cxx:359
const CommandWheelData * GetWheelData() const
TransitionTable m_aTransitions
Definition: fmtfield.cxx:75
double m_dDefaultValue
Definition: fmtfield.hxx:77
void SetMaxValue(double dMax)
Definition: fmtfield.cxx:817
TRISTATE_TRUE
static sal_uLong s_nReferences
Definition: fmtfield.hxx:48
bool IsUsingInputStringForFormatting() const
Definition: fmtfield.hxx:234
const OUString & GetFormatstring() const
bool m_bUseInputStringForFormatting
Definition: fmtfield.hxx:97
sal_Int64 WinBits
sal_uInt16 sal_Unicode
const LocaleDataWrapper & GetLocaleData() const
double m_dCurrentValue
Definition: fmtfield.hxx:76
double m_dMinValue
Definition: fmtfield.hxx:63
FUNC_TYPE const nType
StateTransitions::value_type Transition
Definition: fmtfield.cxx:66
void SetTextFormatted(const OUString &rText)
Definition: fmtfield.cxx:333
virtual bool CheckText(const OUString &sText) const override
Definition: fmtfield.cxx:1072
virtual void Up() override
Definition: fmtfield.cxx:989
double m_dSpinFirst
Definition: fmtfield.hxx:84
std::unique_ptr< validation::NumberValidator > m_pNumberValidator
Definition: fmtfield.hxx:278
static void lcl_insertSignTransitions(StateTransitions &_rRow, const State eNextState)
Definition: fmtfield.cxx:96
OUString const & GetTextValue() const
Definition: fmtfield.cxx:392
constexpr sal_uInt32 NUMBERFORMAT_ENTRY_NOT_FOUND
virtual void SetModifyFlag()
Definition: edit.cxx:2646
virtual const Selection & GetSelection() const
Definition: edit.cxx:2518
sal_uInt16 GetModifier() const
Definition: keycod.hxx:56
DoubleCurrencyField(vcl::Window *pParent, WinBits nStyle)
Definition: fmtfield.cxx:1103
void ImplSetTextImpl(const OUString &rNew, Selection const *pNewSel)
Definition: fmtfield.cxx:458
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: fmtfield.cxx:736
void GetFormatSpecialInfo(sal_uInt32 nFormat, bool &bThousand, bool &IsRed, sal_uInt16 &nPrecision, sal_uInt16 &nLeadingCnt)
void SetAutoColor(bool _bAutomatic)
Definition: fmtfield.cxx:410
virtual void Down()
Definition: spinfld.cxx:364
void SetTextValue(const OUString &rText)
Definition: fmtfield.cxx:827
static unsigned int Power10(unsigned int n)
Definition: builder.cxx:202
TRISTATE_INDET
bool PutEntry(OUString &rString, sal_Int32 &nCheckPos, SvNumFormatType &nType, sal_uInt32 &nKey, LanguageType eLnge=LANGUAGE_DONTKNOW)
void ImplSetValue(double dValue, bool bForce)
Definition: fmtfield.cxx:843
static SvNumberFormatter * s_cFormatter
Definition: fmtfield.hxx:47
void SetDecimalDigits(sal_uInt16 _nPrecision)
Definition: fmtfield.cxx:662
void EnableEmptyField(bool bEnable)
Definition: fmtfield.cxx:833
virtual void Modify() override
Definition: fmtfield.cxx:452
Color * m_pLastOutputColor
Definition: fmtfield.hxx:95
double GetValue()
Definition: fmtfield.cxx:960
Selection m_aLastSelection
Definition: fmtfield.hxx:61
const OUString & getNumDecimalSep() const
long Min() const
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: spinfld.cxx:490
void Justify()
OUString m_sCurrentTextValue
Definition: fmtfield.hxx:91
Link< Edit &, bool > m_aOutputHdl
Definition: fmtfield.hxx:261
sal_uLong m_nFormatKey
Definition: fmtfield.hxx:79
#define DBG_ASSERT(sCon, aError)
virtual void Down() override
Definition: fmtfield.cxx:1009
bool PutandConvertEntry(OUString &rString, sal_Int32 &nCheckPos, SvNumFormatType &nType, sal_uInt32 &nKey, LanguageType eLnge, LanguageType eNewLnge, bool bConvertDateOrder)
bool IsStrictFormat() const
Definition: fmtfield.hxx:156
void UseInputStringForFormatting()
When being set to true, the strings in the field are formatted using the InputLine format...
Definition: fmtfield.cxx:1053
bool ImplGetValue(double &dNewVal)
Definition: fmtfield.cxx:887
bool IsTextFormat(sal_uInt32 nFIndex) const
void SetControlForeground()
Definition: window2.cxx:457
CommandWheelMode GetMode() const
double m_dSpinSize
Definition: fmtfield.hxx:83
OStringBuffer & padToLength(OStringBuffer &rBuffer, sal_Int32 nLength, sal_Char cFill= '\0')
virtual OUString GetText() const override
Definition: edit.cxx:2614
OString stripStart(const OString &rIn, sal_Char c)
CommandEventId GetCommand() const
virtual void Modify()
Definition: edit.cxx:2320
void setPrependCurrSym(bool _bPrepend)
Definition: fmtfield.cxx:1152
void SetEvalDateFormat(NfEvalDateFormat eEDF)
#define LANGUAGE_DONTKNOW
SvNumFormatType
MouseNotifyEvent GetType() const
Definition: event.hxx:294
bool IsNumberFormat(const OUString &sString, sal_uInt32 &F_Index, double &fOutNumber)
bool m_bAutoColor
Definition: fmtfield.hxx:71
bool implValidateNormalized(const OUString &_rText)
Definition: fmtfield.cxx:208
const AllSettings & GetSettings() const
Definition: outdev.hxx:420
bool PreNotify(NotifyEvent &rNEvt) override
Definition: fmtfield.cxx:506
void SetValue(double dVal)
Definition: fmtfield.cxx:955
void GetInputLineString(const double &fOutNumber, sal_uInt32 nFIndex, OUString &rOutString)
void SetMinValue(double dMin)
Definition: fmtfield.cxx:807
bool GetThousandsSep() const
Definition: fmtfield.cxx:609
bool m_bDisableRemainderFactor
Definition: fmtfield.hxx:73
SvNumberFormatter * m_pFormatter
Definition: fmtfield.hxx:80
void ImplSetFormatKey(sal_uLong nFormatKey)
Definition: fmtfield.cxx:513
void Commit()
reformats the current text.
Definition: fmtfield.cxx:701
virtual bool CheckText(const OUString &) const
Definition: fmtfield.hxx:242
const OUString & getCurrSymbol() const
double m_dSpinLast
Definition: fmtfield.hxx:85
static void lcl_insertDigitTransitions(StateTransitions &_rRow, const State eNextState)
Definition: fmtfield.cxx:102
OUString GenerateFormat(sal_uInt32 nIndex, LanguageType eLnge=LANGUAGE_DONTKNOW, bool bThousand=false, bool IsRed=false, sal_uInt16 nPrecision=0, sal_uInt16 nLeadingCnt=1)
void UpdateCurrencyFormat()
Definition: fmtfield.cxx:1162
const vcl::KeyCode & GetKeyCode() const
Definition: event.hxx:53
virtual void First()
Definition: spinfld.cxx:369
OUString m_sLastValidText
Definition: fmtfield.hxx:58
#define KEY_DOWN
Definition: keycodes.hxx:110
void SetFormatKey(sal_uLong nFormatKey)
Definition: fmtfield.cxx:532
const SvNumberformat * GetEntry(sal_uInt32 nKey) const
void DisableRemainderFactor()
Definition: fmtfield.cxx:975
DoubleNumericField(vcl::Window *pParent, WinBits nStyle)
Definition: fmtfield.cxx:1058
sal_uInt16 GetDecimalDigits() const
Definition: fmtfield.cxx:650
NumberValidator(const sal_Unicode _cThSep, const sal_Unicode _cDecSep)
Definition: fmtfield.cxx:120
const OUString & getCurrencySymbol() const
Definition: fmtfield.hxx:287
sal_uInt32 GetStandardFormat(SvNumFormatType eType, LanguageType eLnge=LANGUAGE_DONTKNOW)
bool m_bTreatAsNumber
Definition: fmtfield.hxx:89
void ResetConformanceTester()
Definition: fmtfield.cxx:1080
virtual void Last()
Definition: spinfld.cxx:374
virtual void FormatChanged(FORMAT_CHANGE_TYPE nWhat) override
Definition: fmtfield.cxx:1114
Reference< XComponentContext > getProcessComponentContext()
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: spinfld.cxx:835
const OUString & getNumThousandSep() const
WindowType GetType() const
Definition: window2.cxx:968
bool getPrependCurrSym() const
Definition: fmtfield.hxx:290
double m_dMaxValue
Definition: fmtfield.hxx:64
virtual void FormatChanged(FORMAT_CHANGE_TYPE nWhat)
Definition: fmtfield.cxx:691
const LanguageTag & GetLanguageTag() const
valueState m_ValueState
Definition: fmtfield.hxx:75
long Max() const
virtual bool IsReadOnly() const
Definition: edit.hxx:190
virtual void SetText(const OUString &rStr) override
Definition: edit.cxx:2595
NF_EVALDATEFORMAT_FORMAT_INTL
void setCurrencySymbol(const OUString &rSymbol)
Definition: fmtfield.cxx:1142
bool TreatingAsNumber() const
Definition: fmtfield.hxx:179
FormattedField(vcl::Window *pParent, WinBits nStyle)
Definition: fmtfield.cxx:293
void impl_Modify(bool makeValueDirty=true)
Definition: fmtfield.cxx:425
void SetThousandsSep(bool _bUseSeparator)
Definition: fmtfield.cxx:621
bool m_bEnableEmptyField
Definition: fmtfield.hxx:70
void EnableNotANumber(bool _bEnable)
enables handling of not-a-number value.
Definition: fmtfield.cxx:402
::std::map< State, StateTransitions > TransitionTable
Definition: fmtfield.cxx:69
LanguageType GetLanguage() const
OUString GetFormat(LanguageType &eLang) const
Definition: fmtfield.cxx:581
#define KEY_UP
Definition: keycodes.hxx:111
static void lcl_insertCommonPreCommaTransitions(StateTransitions &_rRow, const sal_Unicode _cThSep, const sal_Unicode _cDecSep)
Definition: fmtfield.cxx:108