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