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