Use wxUILocale in wxNumberFormatter
Always use the UI locale conventions for floating point numbers in wxNumberFormatter, making it different from wxString::{To,From}Double() functions that use C locale, which may, or not, correspond to the UI locale.
This commit is contained in:
@@ -8,11 +8,15 @@
|
||||
/**
|
||||
@class wxNumberFormatter
|
||||
|
||||
Helper class for formatting and parsing numbers with thousands separators.
|
||||
Formatting and parsing numbers using the current UI locale conventions,
|
||||
including support for using the correct decimal point character and
|
||||
thousands separators.
|
||||
|
||||
This class contains only static functions, so users must not create instances
|
||||
but directly call the member functions.
|
||||
|
||||
@see wxUILocale
|
||||
|
||||
@since 2.9.2
|
||||
|
||||
@library{wxbase}
|
||||
@@ -32,7 +36,7 @@ public:
|
||||
|
||||
/**
|
||||
If this flag is given, thousands separators will be inserted in the
|
||||
number string representation as defined by the current locale.
|
||||
number string representation as defined by the current UI locale.
|
||||
*/
|
||||
Style_WithThousandsSep = 0x01,
|
||||
|
||||
@@ -56,7 +60,7 @@ public:
|
||||
Returns string representation of an integer number.
|
||||
|
||||
By default, the string will use thousands separators if appropriate for
|
||||
the current locale. This can be avoided by passing Style_None as @a
|
||||
the current UI locale. This can be avoided by passing Style_None as @a
|
||||
flags in which case the call to the function has exactly the same
|
||||
effect as <code>wxString::Format("%ld", val)</code>.
|
||||
|
||||
@@ -94,7 +98,7 @@ public:
|
||||
Parse a string representation of a number possibly including thousands
|
||||
separators.
|
||||
|
||||
These functions parse number representation in the current locale. On
|
||||
These functions parse number representation in the current UI locale. On
|
||||
success they return @true and store the result at the location pointed
|
||||
to by @a val (which can't be @NULL), otherwise @false is returned.
|
||||
|
||||
@@ -114,7 +118,7 @@ public:
|
||||
//@}
|
||||
|
||||
/**
|
||||
Get the decimal separator for the current locale.
|
||||
Get the decimal separator for the current UI locale.
|
||||
|
||||
Decimal separators is always defined and we fall back to returning '.'
|
||||
in case of an error.
|
||||
@@ -123,14 +127,14 @@ public:
|
||||
|
||||
/**
|
||||
Get the thousands separator if grouping of the digits is used by the
|
||||
current locale.
|
||||
current UI locale.
|
||||
|
||||
The value returned in @a sep should be only used if the function
|
||||
returns @true, otherwise no thousands separator should be used at all.
|
||||
|
||||
@param sep
|
||||
Points to the variable receiving the thousands separator character
|
||||
if it is used by the current locale. May be @NULL if only the
|
||||
if it is used by the current UI locale. May be @NULL if only the
|
||||
function return value is needed.
|
||||
*/
|
||||
static bool GetThousandsSeparatorIfUsed(wxChar *sep);
|
||||
|
@@ -16,84 +16,7 @@
|
||||
|
||||
|
||||
#include "wx/numformatter.h"
|
||||
#include "wx/intl.h"
|
||||
|
||||
#include <locale.h> // for setlocale and LC_ALL
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// local helpers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Contains information about the locale which was used to initialize our
|
||||
// cached values of the decimal and thousands separators. Notice that it isn't
|
||||
// enough to store just wxLocale because the user code may call setlocale()
|
||||
// directly and storing just C locale string is not enough because we can use
|
||||
// the OS API directly instead of the CRT ones on some platforms. So just store
|
||||
// both.
|
||||
class LocaleId
|
||||
{
|
||||
public:
|
||||
LocaleId()
|
||||
{
|
||||
#if wxUSE_INTL
|
||||
m_wxloc = NULL;
|
||||
#endif // wxUSE_INTL
|
||||
m_cloc = NULL;
|
||||
}
|
||||
|
||||
~LocaleId()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
#if wxUSE_INTL
|
||||
// Return true if this is the first time this function is called for this
|
||||
// object or if the program locale has changed since the last time it was
|
||||
// called. Otherwise just return false indicating that updating locale-
|
||||
// dependent information is not necessary.
|
||||
bool NotInitializedOrHasChanged()
|
||||
{
|
||||
wxLocale * const wxloc = wxGetLocale();
|
||||
const char * const cloc = setlocale(LC_ALL, NULL);
|
||||
if ( m_wxloc || m_cloc )
|
||||
{
|
||||
if ( m_wxloc == wxloc && strcmp(m_cloc, cloc) == 0 )
|
||||
return false;
|
||||
|
||||
Free();
|
||||
}
|
||||
//else: Not initialized yet.
|
||||
|
||||
m_wxloc = wxloc;
|
||||
m_cloc = wxCRT_StrdupA(cloc);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // wxUSE_INTL
|
||||
|
||||
private:
|
||||
void Free()
|
||||
{
|
||||
#if wxUSE_INTL
|
||||
free(m_cloc);
|
||||
#endif // wxUSE_INTL
|
||||
}
|
||||
|
||||
#if wxUSE_INTL
|
||||
// Non-owned pointer to wxLocale which was used.
|
||||
wxLocale *m_wxloc;
|
||||
#endif // wxUSE_INTL
|
||||
|
||||
// Owned pointer to the C locale string.
|
||||
char *m_cloc;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(LocaleId);
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
#include "wx/uilocale.h"
|
||||
|
||||
// ============================================================================
|
||||
// wxNumberFormatter implementation
|
||||
@@ -111,14 +34,10 @@ wxChar wxNumberFormatter::GetDecimalSeparator()
|
||||
// concurrently from more than one thread so it's not a real problem.
|
||||
static wxChar s_decimalSeparator = 0;
|
||||
|
||||
// Remember the locale which was current when we initialized, we must redo
|
||||
// the initialization if the locale changed.
|
||||
static LocaleId s_localeUsedForInit;
|
||||
|
||||
if ( s_localeUsedForInit.NotInitializedOrHasChanged() )
|
||||
if ( !s_decimalSeparator )
|
||||
{
|
||||
const wxString
|
||||
s = wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER);
|
||||
s = wxUILocale::GetCurrent().GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER);
|
||||
if ( s.length() == 1 )
|
||||
{
|
||||
s_decimalSeparator = s[0];
|
||||
@@ -141,12 +60,14 @@ bool wxNumberFormatter::GetThousandsSeparatorIfUsed(wxChar *sep)
|
||||
{
|
||||
#if wxUSE_INTL
|
||||
static wxChar s_thousandsSeparator = 0;
|
||||
static LocaleId s_localeUsedForInit;
|
||||
static bool s_thousandsSeparatorInitialized = false;
|
||||
|
||||
if ( s_localeUsedForInit.NotInitializedOrHasChanged() )
|
||||
if ( !s_thousandsSeparatorInitialized )
|
||||
{
|
||||
s_thousandsSeparatorInitialized = true;
|
||||
|
||||
const wxString
|
||||
s = wxLocale::GetInfo(wxLOCALE_THOUSANDS_SEP, wxLOCALE_CAT_NUMBER);
|
||||
s = wxUILocale::GetCurrent().GetInfo(wxLOCALE_THOUSANDS_SEP, wxLOCALE_CAT_NUMBER);
|
||||
if ( s.length() == 1 )
|
||||
{
|
||||
s_thousandsSeparator = s[0];
|
||||
@@ -172,6 +93,21 @@ bool wxNumberFormatter::GetThousandsSeparatorIfUsed(wxChar *sep)
|
||||
// Conversion to string and helpers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void ReplaceSeparatorIfNecessary(wxString& s, wxChar sepOld, wxChar sepNew)
|
||||
{
|
||||
if ( sepNew != sepOld )
|
||||
{
|
||||
const size_t posSep = s.find(sepOld);
|
||||
if ( posSep != wxString::npos )
|
||||
s[posSep] = sepNew;
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
wxString wxNumberFormatter::PostProcessIntString(wxString s, int style)
|
||||
{
|
||||
if ( style & Style_WithThousandsSep )
|
||||
@@ -206,7 +142,9 @@ wxString wxNumberFormatter::ToString(wxULongLong_t val, int style)
|
||||
|
||||
wxString wxNumberFormatter::ToString(double val, int precision, int style)
|
||||
{
|
||||
wxString s = wxString::FromDouble(val,precision);
|
||||
wxString s = wxString::FromCDouble(val,precision);
|
||||
|
||||
ReplaceSeparatorIfNecessary(s, '.', GetDecimalSeparator());
|
||||
|
||||
if ( style & Style_WithThousandsSep )
|
||||
AddThousandsSeparators(s);
|
||||
@@ -330,5 +268,6 @@ bool wxNumberFormatter::FromString(wxString s, wxULongLong_t *val)
|
||||
bool wxNumberFormatter::FromString(wxString s, double *val)
|
||||
{
|
||||
RemoveThousandsSeparators(s);
|
||||
return s.ToDouble(val);
|
||||
ReplaceSeparatorIfNecessary(s, GetDecimalSeparator(), '.');
|
||||
return s.ToCDouble(val);
|
||||
}
|
||||
|
Reference in New Issue
Block a user