21#include <boost/property_tree/json_parser.hpp>
38#include <rtl/math.hxx>
39#include <rtl/ustrbuf.hxx>
42#include <osl/diagnose.h>
71 for (
sal_Unicode aChar =
'0'; aChar <=
'9'; ++aChar )
72 _rRow.insert(
Transition( aChar, eNextState ) );
180 while (
END != eCurrentState )
183 TransitionTable::const_iterator aRow =
m_aTransitions.find( eCurrentState );
185 "NumberValidator::implValidateNormalized: invalid transition table (row not found)!" );
190 StateTransitions::const_iterator aTransition = aRow->second.find( *pCheckPos );
191 if ( aRow->second.end() != aTransition )
194 eCurrentState = aTransition->second;
205 "NumberValidator::implValidateNormalized: inconsistency!" );
211 return (
END == eCurrentState );
216 if ( _rText.empty() )
221 OUString sNormalized = OUString::Concat(
"_") + _rText +
"_";
237 ::comphelper::getProcessComponentContext(),
250 if (--s_nReferences == 0)
253 s_cFormatter =
nullptr;
297 "FormattedField::SetTextFormatted : valid only with text formats !");
302 double dNumber = 0.0;
304 sal_uInt32 nTempFormatKey =
static_cast< sal_uInt32
>(
m_nFormatKey );
322 sal_Int32 nNewLen = sFormatted.getLength();
324 if ((nNewLen > nCurrentLen) && (aNewSel.
Max() == nCurrentLen))
326 if (aNewSel.
Min() == 0)
328 aNewSel.
Max() = nNewLen;
334 aNewSel.
Min() = aNewSel.
Max();
339 else if (aNewSel.
Max() == aNewSel.
Min())
341 aNewSel.
Max() = nNewLen;
342 aNewSel.
Min() = nNewLen;
345 else if (aNewSel.
Max() > nNewLen)
346 aNewSel.
Max() = nNewLen;
422 sal_Int32 nNewLen = rNew.getLength();
425 if ((nNewLen > nCurrentLen) && (aSel.
Max() == nCurrentLen))
435 aSel.
Max() = nNewLen;
438 else if (aSel.
Max() == aSel.
Min())
440 aSel.
Max() = nNewLen;
441 aSel.
Min() = nNewLen;
444 else if (aSel.
Max() > nNewLen)
445 aSel.
Max() = nNewLen;
455 bool bNeedFormatter = (
m_pFormatter ==
nullptr) && (nFormatKey != 0);
498 OUString sOldFormat =
GetFormat(aOldLang);
522 DBG_ASSERT(pFormatEntry !=
nullptr,
"FormattedField::GetFormat: no number format for the given format key.");
523 OUString sFormatString = pFormatEntry ? pFormatEntry->
GetFormatstring() : OUString();
526 return sFormatString;
536 OUString rFormat(rFormatString);
550 "FormattedField::GetThousandsSep : Are you sure what you are doing when setting the precision of a text format?");
552 bool bThousand, IsRed;
553 sal_uInt16 nPrecision, nLeadingCnt;
562 "FormattedField::SetThousandsSep : Are you sure what you are doing when setting the precision of a text format?");
565 bool bThousand, IsRed;
566 sal_uInt16 nPrecision, nLeadingCnt;
568 if (bThousand == _bUseSeparator)
578 sal_Int32 nCheckPos = 0;
591 "FormattedField::GetDecimalDigits : Are you sure what you are doing when setting the precision of a text format?");
593 bool bThousand, IsRed;
594 sal_uInt16 nPrecision, nLeadingCnt;
603 "FormattedField::SetDecimalDigits : Are you sure what you are doing when setting the precision of a text format?");
606 bool bThousand, IsRed;
607 sal_uInt16 nPrecision, nLeadingCnt;
609 if (nPrecision == _nPrecision)
619 sal_Int32 nCheckPos = 0;
752 if (!bForce && (dVal ==
GetValue()))
783 DBG_ASSERT(
CheckText(sNewText),
"FormattedField::ImplSetValue : formatted string doesn't match the criteria !");
804 bool bUseExternalFormatterValue =
false;
810 if (bUseExternalFormatterValue)
822 if (!bUseExternalFormatterValue)
840 sal_uInt32 nTempFormat = nStandardNumericFormat;
893 : m_rSpinButton(rSpinButton)
905 return m_rSpinButton.
GetText();
910 m_rSpinButton.SpinField::SetText(rText, rSel);
928 m_rSpinButton.SpinField::Modify();
934 m_rSpinButton.
SetUpperEnabled(!m_bHasMax || dCurrentValue < m_dMaxValue);
935 m_rSpinButton.
SetLowerEnabled(!m_bHasMin || dCurrentValue > m_dMinValue);
939 class DoubleNumericFormatter :
public FieldFormatter
942 DoubleNumericField& m_rNumericSpinButton;
944 DoubleNumericFormatter(DoubleNumericField& rNumericSpinButton)
945 : FieldFormatter(rNumericSpinButton)
946 , m_rNumericSpinButton(rNumericSpinButton)
950 virtual bool CheckText(
const OUString& sText)
const override
955 return m_rNumericSpinButton.GetNumberValidator().isValidNumericFragment(sText);
960 m_rNumericSpinButton.ResetConformanceTester();
961 FieldFormatter::FormatChanged(nWhat);
965 class DoubleCurrencyFormatter :
public FieldFormatter
968 DoubleCurrencyField& m_rCurrencySpinButton;
969 bool m_bChangingFormat;
971 DoubleCurrencyFormatter(DoubleCurrencyField& rNumericSpinButton)
972 : FieldFormatter(rNumericSpinButton)
973 , m_rCurrencySpinButton(rNumericSpinButton)
974 , m_bChangingFormat(false)
980 if (m_bChangingFormat)
982 FieldFormatter::FormatChanged(nWhat);
993 m_rCurrencySpinButton.UpdateCurrencyFormat();
996 OSL_FAIL(
"DoubleCurrencyField::FormatChanged : somebody modified my key !");
1003 FieldFormatter::FormatChanged(nWhat);
1006 void GuardSetFormat(
const OUString& rString,
LanguageType eLanguage)
1009 m_bChangingFormat =
true;
1011 m_bChangingFormat =
false;
1020 m_xOwnFormatter.reset(
new DoubleNumericFormatter(*
this));
1022 ResetConformanceTester();
1025DoubleNumericField::~DoubleNumericField() =
default;
1027void DoubleNumericField::ResetConformanceTester()
1039 OUString sSeparator = aLocaleInfo.getNumThousandSep();
1040 if (!sSeparator.isEmpty())
1041 cSeparatorThousand = sSeparator[0];
1043 sSeparator = aLocaleInfo.getNumDecimalSep();
1044 if (!sSeparator.isEmpty())
1045 cSeparatorDecimal = sSeparator[0];
1055 m_xOwnFormatter.reset(
new DoubleCurrencyFormatter(*
this));
1058 m_bPrependCurrSym =
false;
1062 UpdateCurrencyFormat();
1065void DoubleCurrencyField::setCurrencySymbol(
const OUString& rSymbol)
1067 if (m_sCurrencySymbol == rSymbol)
1070 m_sCurrencySymbol = rSymbol;
1071 UpdateCurrencyFormat();
1075void DoubleCurrencyField::setPrependCurrSym(
bool _bPrepend)
1077 if (m_bPrependCurrSym == _bPrepend)
1080 m_bPrependCurrSym = _bPrepend;
1081 UpdateCurrencyFormat();
1085void DoubleCurrencyField::UpdateCurrencyFormat()
1089 m_pFormatter->GetFormat(eLanguage);
1090 bool bThSep = m_pFormatter->GetThousandsSep();
1091 sal_uInt16 nDigits = m_pFormatter->GetDecimalDigits();
1101 OUStringBuffer sNewFormat;
1104 sNewFormat.append(
"#" + aLocaleInfo.getNumThousandSep() +
"##0");
1107 sNewFormat.append(
'0');
1111 sNewFormat.append(aLocaleInfo.getNumDecimalSep());
1115 if (getPrependCurrSym())
1117 OUString sSymbol = getCurrencySymbol();
1121 "[$" + sSymbol +
"] "
1136 OUString sTemp = getCurrencySymbol();
1139 sNewFormat.append(
" [$" + sTemp +
"]");
1143 static_cast<DoubleCurrencyFormatter*
>(m_pFormatter)->GuardSetFormat(sNewFormat.makeStringAndClear(), eLanguage);
1148 , m_pFormatter(nullptr)
1172 if (rKey ==
"digits")
1174 else if (rKey ==
"wrap")
1187 sal_Int64 nSpinSize = std::round(rFormatter.
GetSpinSize() * nScale);
1188 assert(nSpinSize != 0);
1209 sal_Int64 nSpinSize = std::round(rFormatter.
GetSpinSize() * nScale);
1210 assert(nSpinSize != 0);
1331 rtl_math_ConversionStatus eStatus;
1333 double fValue = ::rtl::math::stringToDouble(rStr,
'.', rFormatter.
GetDecimalDigits(), &eStatus, &nEnd );
1335 if (eStatus == rtl_math_ConversionStatus_Ok &&
1336 nEnd == rStr.getLength())
1347 SAL_WARN(
"vcl",
"fail to convert the value: " << rStr);
static bool toBool(std::string_view rValue)
const StyleSettings & GetStyleSettings() const
CommandEventId GetCommand() const
const CommandWheelData * GetWheelData() const
virtual bool set_property(const OUString &rKey, const OUString &rValue) override
virtual const Selection & GetSelection() const
virtual void DumpAsPropertyTree(tools::JsonWriter &rJsonWriter) override
Dumps itself and potentially its children to a property tree, to be written easily to JSON.
virtual void SetSelection(const Selection &rSelection)
virtual bool IsReadOnly() const
virtual void SetModifyFlag()
virtual OUString GetText() const override
const vcl::KeyCode & GetKeyCode() const
LanguageType getLanguageType(bool bResolveSystem=true) const
const OUString & getCurrSymbol() const
const KeyEvent * GetKeyEvent() const
const CommandEvent * GetCommandEvent() const
NotifyEventType GetType() const
virtual bool EventNotify(NotifyEvent &rNEvt) override
SAL_DLLPRIVATE void SetLowerEnabled(bool bEnabled)
virtual bool PreNotify(NotifyEvent &rNEvt) override
SAL_DLLPRIVATE void SetUpperEnabled(bool bEnabled)
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects.
SelectionOptions GetSelectionOptions() const
const LanguageTag & GetLanguageTag() const
const LocaleDataWrapper & GetLocaleData() const
bool implValidateNormalized(const OUString &_rText)
TransitionTable m_aTransitions
bool isValidNumericFragment(std::u16string_view _rText)
NumberValidator(const sal_Unicode _cThSep, const sal_Unicode _cDecSep)
sal_uInt16 GetCode() const
sal_uInt16 GetModifier() const
void SetControlForeground()
const AllSettings & GetSettings() const
#define DBG_ASSERT(sCon, aError)
std::function< std::unique_ptr< UIObject >(vcl::Window *)> FactoryFunction
constexpr sal_uInt16 KEY_PAGEDOWN
constexpr sal_uInt16 KEY_UP
constexpr sal_uInt16 KEY_DOWN
constexpr sal_uInt16 KEY_PAGEUP
#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)
StateTransitions::value_type Transition
static void lcl_insertStartExponentTransition(StateTransitions &_rRow)
static void lcl_insertDigitTransitions(StateTransitions &_rRow, const State eNextState)
static void lcl_insertSignTransitions(StateTransitions &_rRow, const State eNextState)
static void lcl_insertStopTransition(StateTransitions &_rRow)
::std::map< sal_Unicode, State > StateTransitions
NF_EVALDATEFORMAT_FORMAT_INTL
constexpr sal_uInt32 NUMBERFORMAT_ENTRY_NOT_FOUND