From 6fd2f4a0d14b45a316defe994e9790de062ff3ff Mon Sep 17 00:00:00 2001 From: Oliver Tappe Date: Sun, 24 Oct 2010 12:57:55 +0000 Subject: [PATCH] One more monster commit (sorry ...) concerning the Locale Kit: * extracted new class BFormattingConventions from BCountry, which manages the formatting conventions from a given locale and allows to get/set the four different date/time formats supported by ICU-locales as well as number and monetary formats * overhauled the Locale preflet: + drop editing features for all formats, since I don't think they do not make much sense to have in a prefs GUI - being able to select from the existing locales should be good enough. Please note that you can still change the formats programmatically in an application. + renamed the 'Countries' tab to 'Formatting' + the locale formatting conventions list in the 'Formatting' tab is now hierarchical for easier access (less scrolling) + fixed functionality of 'Revert' and 'Defaults' buttons + added support for using the month/day-names of your preferred language during date formatting * adjusted BLocale to ask BFormattingConventions for the current formats when formatting dates and times and to offer 4 different format styles (full, long, medium and short). * adjust all classes formatting dates/times to pick the appropriate format style * BLocaleRoster no longer directly archives/unarchives the individual formatting conventions but delegates that to BFormattingConventions git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39123 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/LocaleKit.h | 1 + headers/os/locale/Country.h | 16 +- headers/os/locale/FormattingConventions.h | 129 +++ headers/os/locale/Locale.h | 91 +- headers/os/locale/LocaleRoster.h | 4 +- headers/private/locale/CountryPrivate.h | 37 - .../locale/FormattingConventionsPrivate.h | 37 + headers/private/locale/MutableLocaleRoster.h | 18 +- src/apps/deskbar/TimeView.cpp | 9 +- .../readonlybootprompt/BootPromptWindow.cpp | 7 +- src/bin/dstcheck.cpp | 2 +- src/kits/locale/Country.cpp | 28 +- src/kits/locale/FormattingConventions.cpp | 596 ++++++++++++ src/kits/locale/Jamfile | 1 + src/kits/locale/Locale.cpp | 614 ++++-------- src/kits/locale/LocaleRoster.cpp | 6 +- src/kits/locale/MutableLocaleRoster.cpp | 161 +--- src/kits/tracker/WidgetAttributeText.cpp | 6 +- src/preferences/locale/FormatSettingsView.cpp | 891 +++++------------- src/preferences/locale/FormatSettingsView.h | 74 +- src/preferences/locale/Jamfile | 1 - src/preferences/locale/LanguageListView.cpp | 11 +- src/preferences/locale/LanguageListView.h | 3 +- src/preferences/locale/LocalePreflet.cpp | 44 +- src/preferences/locale/LocaleSettings.cpp | 108 --- src/preferences/locale/LocaleSettings.h | 50 - src/preferences/locale/LocaleWindow.cpp | 275 +++--- src/preferences/locale/LocaleWindow.h | 24 +- src/preferences/time/DateTimeEdit.cpp | 10 +- src/preferences/time/ZoneView.cpp | 10 +- 30 files changed, 1532 insertions(+), 1732 deletions(-) create mode 100644 headers/os/locale/FormattingConventions.h delete mode 100644 headers/private/locale/CountryPrivate.h create mode 100644 headers/private/locale/FormattingConventionsPrivate.h create mode 100644 src/kits/locale/FormattingConventions.cpp delete mode 100644 src/preferences/locale/LocaleSettings.cpp delete mode 100644 src/preferences/locale/LocaleSettings.h diff --git a/headers/os/LocaleKit.h b/headers/os/LocaleKit.h index 8bc4e34739..b94c2e5659 100644 --- a/headers/os/LocaleKit.h +++ b/headers/os/LocaleKit.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/headers/os/locale/Country.h b/headers/os/locale/Country.h index 02ecaa7070..6488a1a973 100644 --- a/headers/os/locale/Country.h +++ b/headers/os/locale/Country.h @@ -22,18 +22,9 @@ namespace icu_44 { } -enum { - B_METRIC = 0, - B_US -}; - - class BCountry { public: - BCountry(const char* languageCode, - const char* countryCode); - BCountry(const char* languageAndCountryCode - = "en_US"); + BCountry(const char* countryCode = NULL); BCountry(const BCountry& other); BCountry& operator=(const BCountry& other); ~BCountry(); @@ -44,15 +35,12 @@ public: ) const; const char* Code() const; + // ISO-3166 status_t GetIcon(BBitmap* result) const; - const char* GetLocalizedString(uint32 id) const; - status_t GetAvailableTimeZones( BMessage* timeZones) const; - int8 Measurement() const; - class Private; private: friend class Private; diff --git a/headers/os/locale/FormattingConventions.h b/headers/os/locale/FormattingConventions.h new file mode 100644 index 0000000000..035442993e --- /dev/null +++ b/headers/os/locale/FormattingConventions.h @@ -0,0 +1,129 @@ +/* + * Copyright 2003-2010, Haiku, Inc. + * Distributed under the terms of the MIT Licence. + */ +#ifndef _FORMATTING_CONVENTIONS_H_ +#define _FORMATTING_CONVENTIONS_H_ + + +#include +#include +#include +#include +#include + + +class BBitmap; +class BLanguage; +class BMessage; + +namespace icu_44 { + class DateFormat; + class Locale; +} + + +enum BMeasurementKind { + B_METRIC = 0, + B_US +}; + + +enum BDateFormatStyle { + B_FULL_DATE_FORMAT = 0, + B_LONG_DATE_FORMAT, + B_MEDIUM_DATE_FORMAT, + B_SHORT_DATE_FORMAT, + + B_DATE_FORMAT_STYLE_COUNT +}; + + +enum BTimeFormatStyle { + B_FULL_TIME_FORMAT = 0, + B_LONG_TIME_FORMAT, + B_MEDIUM_TIME_FORMAT, + B_SHORT_TIME_FORMAT, + + B_TIME_FORMAT_STYLE_COUNT +}; + + +class BFormattingConventions : public BArchivable { +public: + BFormattingConventions(const char* id = NULL); + BFormattingConventions( + const BFormattingConventions& other); + BFormattingConventions(const BMessage* archive); + + BFormattingConventions& operator=( + const BFormattingConventions& other); + + ~BFormattingConventions(); + + bool operator==( + const BFormattingConventions& other) const; + bool operator!=( + const BFormattingConventions& other) const; + + const char* ID() const; + const char* LanguageCode() const; + const char* CountryCode() const; + + status_t GetNativeName(BString& name) const; + status_t GetName(BString& name, + const BLanguage* displayLanguage = NULL + ) const; + + const char* GetString(uint32 id) const; + + status_t GetDateFormat(BDateFormatStyle style, + BString& outFormat) const; + status_t GetTimeFormat(BTimeFormatStyle style, + BString& outFormat) const; + status_t GetNumericFormat(BString& outFormat) const; + status_t GetMonetaryFormat(BString& outFormat) const; + + void SetExplicitDateFormat(BDateFormatStyle style, + const BString& format); + void SetExplicitTimeFormat(BTimeFormatStyle style, + const BString& format); + void SetExplicitNumericFormat(const BString& format); + void SetExplicitMonetaryFormat( + const BString& format); + + BMeasurementKind MeasurementKind() const; + + bool UseStringsFromPreferredLanguage() const; + void SetUseStringsFromPreferredLanguage(bool value); + + bool Use24HourClock() const; + void SetExplicitUse24HourClock(bool value); + void UnsetExplicitUse24HourClock(); + + virtual status_t Archive(BMessage* archive, + bool deep = true) const; + + class Private; +private: + friend class Private; + + mutable BString fCachedDateFormats[B_DATE_FORMAT_STYLE_COUNT]; + mutable BString fCachedTimeFormats[B_TIME_FORMAT_STYLE_COUNT]; + mutable BString fCachedNumericFormat; + mutable BString fCachedMonetaryFormat; + mutable int8 fCachedUse24HourClock; + + BString fExplicitDateFormats[B_DATE_FORMAT_STYLE_COUNT]; + BString fExplicitTimeFormats[B_TIME_FORMAT_STYLE_COUNT]; + BString fExplicitNumericFormat; + BString fExplicitMonetaryFormat; + int8 fExplicitUse24HourClock; + + bool fUseStringsFromPreferredLanguage; + + icu_44::Locale* fICULocale; +}; + + +#endif /* _FORMATTING_CONVENTIONS_H_ */ diff --git a/headers/os/locale/Locale.h b/headers/os/locale/Locale.h index e389e06b59..22d8307828 100644 --- a/headers/os/locale/Locale.h +++ b/headers/os/locale/Locale.h @@ -7,11 +7,16 @@ #include -#include +#include #include #include +namespace icu_44 { + class DateFormat; +} + + class BCatalog; class BString; class BTimeZone; @@ -39,7 +44,8 @@ typedef enum { class BLocale { public: BLocale(const BLanguage* language = NULL, - const BCountry* country = NULL); + const BFormattingConventions* conventions + = NULL); BLocale(const BLocale& other); ~BLocale(); @@ -47,14 +53,14 @@ public: status_t GetCollator(BCollator* collator) const; status_t GetLanguage(BLanguage* language) const; - status_t GetCountry(BCountry* country) const; + status_t GetFormattingConventions( + BFormattingConventions* conventions) const; - void SetCountry(const BCountry& newCountry); + void SetFormattingConventions( + const BFormattingConventions& conventions); void SetCollator(const BCollator& newCollator); void SetLanguage(const BLanguage& newLanguage); - bool GetName(BString& name) const; - // see definitions in LocaleStrings.h const char* GetString(uint32 id) const; @@ -62,29 +68,34 @@ public: char* fmt, ...) const; void FormatString(BString* buffer, char* fmt, ...) const; - status_t FormatDateTime(char* target, size_t maxSize, - time_t time, bool longFormat) const; + + // DateTime + + // TODO: drop some of these once BDateTimeFormat + // has been implemented! + ssize_t FormatDateTime(char* target, size_t maxSize, + time_t time, BDateFormatStyle dateStyle, + BTimeFormatStyle timeStyle) const; status_t FormatDateTime(BString* buffer, time_t time, - bool longFormat, + BDateFormatStyle dateStyle, + BTimeFormatStyle timeStyle, const BTimeZone* timeZone = NULL) const; // Date // TODO: drop some of these once BDateFormat // has been implemented! - status_t FormatDate(char* string, size_t maxSize, - time_t time, bool longFormat) const; + ssize_t FormatDate(char* string, size_t maxSize, + time_t time, BDateFormatStyle style) const; status_t FormatDate(BString* string, time_t time, - bool longFormat, + BDateFormatStyle style, const BTimeZone* timeZone = NULL) const; status_t FormatDate(BString* string, int*& fieldPositions, int& fieldCount, - time_t time, bool longFormat) const; + time_t time, BDateFormatStyle style) const; status_t GetDateFields(BDateElement*& fields, - int& fieldCount, bool longFormat) const; - status_t GetDateFormat(BString&, bool longFormat) const; - status_t SetDateFormat(const char* formatString, - bool longFormat = true); + int& fieldCount, BDateFormatStyle style + ) const; int StartOfWeek() const; @@ -92,29 +103,25 @@ public: // TODO: drop some of these once BTimeFormat // has been implemented! - status_t FormatTime(char* string, size_t maxSize, - time_t time, bool longFormat) const; + ssize_t FormatTime(char* string, size_t maxSize, + time_t time, BTimeFormatStyle style) const; status_t FormatTime(BString* string, time_t time, - bool longFormat, + BTimeFormatStyle style, const BTimeZone* timeZone = NULL) const; status_t FormatTime(BString* string, int*& fieldPositions, int& fieldCount, - time_t time, bool longFormat) const; + time_t time, BTimeFormatStyle style) const; status_t GetTimeFields(BDateElement*& fields, - int& fieldCount, bool longFormat) const; - - status_t SetTimeFormat(const char* formatString, - bool longFormat = true); - status_t GetTimeFormat(BString& out, - bool longFormat) const; + int& fieldCount, BTimeFormatStyle style + ) const; // numbers - status_t FormatNumber(char* string, size_t maxSize, + ssize_t FormatNumber(char* string, size_t maxSize, double value) const; status_t FormatNumber(BString* string, double value) const; - status_t FormatNumber(char* string, size_t maxSize, + ssize_t FormatNumber(char* string, size_t maxSize, int32 value) const; status_t FormatNumber(BString* string, int32 value) const; @@ -123,13 +130,8 @@ public: ssize_t FormatMonetary(char* string, size_t maxSize, double value) const; - ssize_t FormatMonetary(BString* string, - double value) const; status_t FormatMonetary(BString* string, - int*& fieldPositions, - BNumberElement*& fieldTypes, - int& fieldCount, double value) const; - status_t GetCurrencySymbol(BString& result) const; + double value) const; // Collator short-hands int StringCompare(const char* s1, @@ -138,21 +140,18 @@ public: const BString* s2) const; void GetSortKey(const char* string, - BString* key) const; + BString* sortKey) const; private: - void _UpdateFormats(); + icu_44::DateFormat* _CreateDateFormatter( + const BString& format) const; + icu_44::DateFormat* _CreateTimeFormatter( + const BString& format) const; mutable BLocker fLock; BCollator fCollator; - BCountry fCountry; + BFormattingConventions fConventions; BLanguage fLanguage; - - BString fLongDateFormat; - BString fShortDateFormat; - BString fLongTimeFormat; - BString fShortTimeFormat; - }; @@ -178,9 +177,9 @@ BLocale::StringCompare(const BString* s1, const BString* s2) const inline void -BLocale::GetSortKey(const char* string, BString* key) const +BLocale::GetSortKey(const char* string, BString* sortKey) const { - fCollator.GetSortKey(string, key); + fCollator.GetSortKey(string, sortKey); } diff --git a/headers/os/locale/LocaleRoster.h b/headers/os/locale/LocaleRoster.h index 9a1e625ccf..25edc1d69b 100644 --- a/headers/os/locale/LocaleRoster.h +++ b/headers/os/locale/LocaleRoster.h @@ -13,6 +13,7 @@ class BBitmap; class BCatalog; class BCollator; class BCountry; +class BFormattingConventions; class BLanguage; class BLocale; class BMessage; @@ -37,7 +38,6 @@ public: status_t GetPreferredLanguages(BMessage* message) const; status_t GetAvailableLanguages(BMessage* message) const; - status_t GetAvailableCountries( BMessage* timeZones) const; status_t GetAvailableTimeZones( @@ -49,7 +49,7 @@ public: status_t GetFlagIconForCountry(BBitmap* flagIcon, const char* countryCode); - status_t GetInstalledCatalogs(BMessage* message, + status_t GetAvailableCatalogs(BMessage* message, const char* sigPattern = NULL, const char* langPattern = NULL, int32 fingerprint = 0) const; diff --git a/headers/private/locale/CountryPrivate.h b/headers/private/locale/CountryPrivate.h deleted file mode 100644 index 51b87dc3c9..0000000000 --- a/headers/private/locale/CountryPrivate.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2010, Oliver Tappe - * Distributed under the terms of the MIT License. - */ -#ifndef _COUNTRY_PRIVATE_H -#define _COUNTRY_PRIVATE_H - - -#include - - -class BCountry::Private { -public: - Private(const BCountry* country = NULL) - : - fCountry(country) - { - } - - void - SetTo(const BCountry* country) - { - fCountry = country; - } - - icu_44::Locale* - ICULocale() - { - return fCountry->fICULocale; - } - -private: - const BCountry* fCountry; -}; - - -#endif // _COUNTRY_PRIVATE_H diff --git a/headers/private/locale/FormattingConventionsPrivate.h b/headers/private/locale/FormattingConventionsPrivate.h new file mode 100644 index 0000000000..881ac43031 --- /dev/null +++ b/headers/private/locale/FormattingConventionsPrivate.h @@ -0,0 +1,37 @@ +/* + * Copyright 2010, Oliver Tappe + * Distributed under the terms of the MIT License. + */ +#ifndef _FORMATTING_CONVENTIONS_PRIVATE_H +#define _FORMATTING_CONVENTIONS_PRIVATE_H + + +#include + + +class BFormattingConventions::Private { +public: + Private(const BFormattingConventions* conventions = NULL) + : + fFormattingConventions(conventions) + { + } + + void + SetTo(const BFormattingConventions* conventions) + { + fFormattingConventions = conventions; + } + + icu_44::Locale* + ICULocale() + { + return fFormattingConventions->fICULocale; + } + +private: + const BFormattingConventions* fFormattingConventions; +}; + + +#endif // _FORMATTING_CONVENTIONS_PRIVATE_H diff --git a/headers/private/locale/MutableLocaleRoster.h b/headers/private/locale/MutableLocaleRoster.h index bad15aadc1..1c1606c2ef 100644 --- a/headers/private/locale/MutableLocaleRoster.h +++ b/headers/private/locale/MutableLocaleRoster.h @@ -7,7 +7,7 @@ #include -#include +#include #include #include #include @@ -34,10 +34,8 @@ public: MutableLocaleRoster(); ~MutableLocaleRoster(); - status_t GetDefaultLocale(BLocale* locale) const; - - status_t SetDefaultCountry(const BCountry& country); - status_t SetDefaultLocale(const BLocale& locale); + status_t SetDefaultFormattingConventions( + const BFormattingConventions& conventions); status_t SetDefaultTimeZone(const BTimeZone& zone); status_t SetPreferredLanguages(const BMessage* message); @@ -127,8 +125,8 @@ struct RosterData { static int CompareInfos(const void* left, const void* right); - status_t SetDefaultCountry(const BCountry& country); - status_t SetDefaultLocale(const BLocale& locale); + status_t SetDefaultFormattingConventions( + const BFormattingConventions& convetions); status_t SetDefaultTimeZone(const BTimeZone& zone); status_t SetPreferredLanguages(const BMessage* msg); private: @@ -138,12 +136,12 @@ private: status_t _LoadTimeSettings(); status_t _SaveTimeSettings(); - status_t _SetDefaultCountry(const BCountry& country); - status_t _SetDefaultLocale(const BLocale& locale); + status_t _SetDefaultFormattingConventions( + const BFormattingConventions& conventions); status_t _SetDefaultTimeZone(const BTimeZone& zone); status_t _SetPreferredLanguages(const BMessage* msg); - status_t _AddDefaultCountryToMessage( + status_t _AddDefaultFormattingConventionsToMessage( BMessage* message) const; status_t _AddDefaultTimeZoneToMessage( BMessage* message) const; diff --git a/src/apps/deskbar/TimeView.cpp b/src/apps/deskbar/TimeView.cpp index d1bfcc6b41..cebb65738f 100644 --- a/src/apps/deskbar/TimeView.cpp +++ b/src/apps/deskbar/TimeView.cpp @@ -38,7 +38,6 @@ All rights reserved. #include #include -#include #include #include #include @@ -251,7 +250,8 @@ TTimeView::ShowCalendar(BPoint where) void TTimeView::GetCurrentTime() { - fLocale.FormatTime(fTimeStr, 64, fTime, fShowSeconds); + fLocale.FormatTime(fTimeStr, 64, fTime, + fShowSeconds ? B_MEDIUM_TIME_FORMAT : B_SHORT_TIME_FORMAT); } @@ -260,7 +260,7 @@ TTimeView::GetCurrentDate() { char tmp[64]; - fLocale.FormatDate(tmp, 64, fTime, true); + fLocale.FormatDate(tmp, 64, fTime, B_FULL_DATE_FORMAT); // remove leading 0 from date when month is less than 10 (MM/DD/YY) // or remove leading 0 from date when day is less than 10 (DD/MM/YY) @@ -297,7 +297,7 @@ TTimeView::MouseDown(BPoint point) if (buttons == B_SECONDARY_MOUSE_BUTTON) { ShowClockOptions(ConvertToScreen(point)); return; - } else if (buttons == B_PRIMARY_MOUSE_BUTTON) + } else if (buttons == B_PRIMARY_MOUSE_BUTTON) ShowCalendar(point); // invalidate last time/date strings and call the pulse @@ -361,6 +361,7 @@ TTimeView::Update() GetCurrentTime(); GetCurrentDate(); + SetToolTip(fDateStr); ResizeToPreferred(); diff --git a/src/apps/readonlybootprompt/BootPromptWindow.cpp b/src/apps/readonlybootprompt/BootPromptWindow.cpp index efd5e7d19b..b04f8857f5 100644 --- a/src/apps/readonlybootprompt/BootPromptWindow.cpp +++ b/src/apps/readonlybootprompt/BootPromptWindow.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -212,8 +213,8 @@ BootPromptWindow::_InitCatalog(bool saveSettings) gMutableLocaleRoster->SetPreferredLanguages(&settings); - BCountry country(language.String(), language.ToUpper()); - gMutableLocaleRoster->SetDefaultCountry(country); + BFormattingConventions conventions(language.String()); + gMutableLocaleRoster->SetDefaultFormattingConventions(conventions); } @@ -269,7 +270,7 @@ BootPromptWindow::_PopulateLanguages() } BMessage installedCatalogs; - be_locale_roster->GetInstalledCatalogs(&installedCatalogs, + be_locale_roster->GetAvailableCatalogs(&installedCatalogs, "x-vnd.Haiku-ReadOnlyBootPrompt"); BFont font; diff --git a/src/bin/dstcheck.cpp b/src/bin/dstcheck.cpp index d2f0ead194..4f3cb0060b 100644 --- a/src/bin/dstcheck.cpp +++ b/src/bin/dstcheck.cpp @@ -83,7 +83,7 @@ TimedAlert::GetLabel(BString &string) time(&t); localtime_r(&t, &tm); - be_locale->FormatTime(timestring, 15, t, false); + be_locale->FormatTime(timestring, 15, t, B_SHORT_TIME_FORMAT); string += " "; string += timestring; diff --git a/src/kits/locale/Country.cpp b/src/kits/locale/Country.cpp index 57f19ec846..e9e620607e 100644 --- a/src/kits/locale/Country.cpp +++ b/src/kits/locale/Country.cpp @@ -30,16 +30,9 @@ #define ICU_VERSION icu_44 -BCountry::BCountry(const char* languageCode, const char* countryCode) +BCountry::BCountry(const char* countryCode) : - fICULocale(new ICU_VERSION::Locale(languageCode, countryCode)) -{ -} - - -BCountry::BCountry(const char* languageAndCountryCode) - : - fICULocale(new ICU_VERSION::Locale(languageAndCountryCode)) + fICULocale(new ICU_VERSION::Locale("", countryCode)) { } @@ -98,6 +91,7 @@ BCountry::GetName(BString& name, const BLanguage* displayLanguage) const UnicodeString uString; fICULocale->getDisplayName(Locale(appLanguage), uString); + name.Truncate(0); BStringByteSink stringConverter(&name); uString.toUTF8(stringConverter); @@ -108,7 +102,7 @@ BCountry::GetName(BString& name, const BLanguage* displayLanguage) const const char* BCountry::Code() const { - return fICULocale->getName(); + return fICULocale->getCountry(); } @@ -128,17 +122,3 @@ BCountry::GetAvailableTimeZones(BMessage* timeZones) const return be_locale_roster->GetAvailableTimeZonesForCountry(timeZones, Code()); } - -// TODO does ICU even support this ? Is it in the keywords ? -int8 -BCountry::Measurement() const -{ - UErrorCode error = U_ZERO_ERROR; - switch (ulocdata_getMeasurementSystem(Code(), &error)) { - case UMS_US: - return B_US; - case UMS_SI: - default: - return B_METRIC; - } -} diff --git a/src/kits/locale/FormattingConventions.cpp b/src/kits/locale/FormattingConventions.cpp new file mode 100644 index 0000000000..9a86223ad7 --- /dev/null +++ b/src/kits/locale/FormattingConventions.cpp @@ -0,0 +1,596 @@ +/* + * Copyright 2003-2009, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2009-2010, Adrien Destugues, pulkomandy@gmail.com. + * Copyright 2010, Oliver Tappe . + * Distributed under the terms of the MIT License. + */ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#define ICU_VERSION icu_44 + + +// #pragma mark - helpers + + +static bool +FormatUsesAmPm(const BString& format) +{ + if (format.Length() == 0) + return false; + + bool inQuote = false; + for (const char* s = format.String(); *s != '\0'; ++s) { + switch (*s) { + case '\'': + inQuote = !inQuote; + break; + case 'a': + if (!inQuote) + return true; + break; + } + } + + return false; +} + + +static void +CoerceFormatTo12HourClock(BString& format) +{ + char* s = format.LockBuffer(format.Length()); + if (s == NULL) + return; + + // change format to use h instead of H, k instead of K, and append an + // am/pm marker + bool inQuote = false; + for (; *s != '\0'; ++s) { + switch (*s) { + case '\'': + inQuote = !inQuote; + break; + case 'H': + if (!inQuote) + *s = 'h'; + break; + case 'K': + if (!inQuote) + *s = 'k'; + break; + } + } + format.UnlockBuffer(format.Length()); + + format.Append(" a"); +} + + +static void +CoerceFormatTo24HourClock(BString& format) +{ + char* buffer = format.LockBuffer(format.Length()); + char* currentPos = buffer; + if (currentPos == NULL) + return; + + // change the format to use H instead of h, K instead of k, and determine + // and remove the am/pm marker (including leading whitespace) + bool inQuote = false; + bool lastWasWhitespace = false; + uint32 ch; + const char* amPmStartPos = NULL; + const char* amPmEndPos = NULL; + const char* lastWhitespaceStart = NULL; + for (char* previousPos = currentPos; (ch = BUnicodeChar::FromUTF8( + (const char**)¤tPos)) != 0; previousPos = currentPos) { + switch (ch) { + case '\'': + inQuote = !inQuote; + break; + case 'h': + if (!inQuote) + *previousPos = 'H'; + break; + case 'k': + if (!inQuote) + *previousPos = 'K'; + break; + case 'a': + if (!inQuote) { + if (lastWasWhitespace) + amPmStartPos = lastWhitespaceStart; + else + amPmStartPos = previousPos; + amPmEndPos = currentPos; + } + break; + default: + if (!inQuote && BUnicodeChar::IsWhitespace(ch)) { + if (!lastWasWhitespace) { + lastWhitespaceStart = previousPos; + lastWasWhitespace = true; + } + continue; + } + } + lastWasWhitespace = false; + } + + format.UnlockBuffer(format.Length()); + if (amPmStartPos != NULL && amPmEndPos > amPmStartPos) + format.Remove(amPmStartPos - buffer, amPmEndPos - amPmStartPos); +} + + +static void +CoerceFormatToAbbreviatedTimezone(BString& format) +{ + char* s = format.LockBuffer(format.Length()); + if (s == NULL) + return; + + // replace a single 'z' with 'V' + bool inQuote = false; + bool lastWasZ = false; + for (; *s != '\0'; ++s) { + switch (*s) { + case '\'': + inQuote = !inQuote; + break; + case 'z': + if (!inQuote && !lastWasZ && *(s+1) != 'z') + *s = 'V'; + lastWasZ = true; + continue; + } + lastWasZ = false; + } + format.UnlockBuffer(format.Length()); +} + + +// #pragma mark - BFormattingConventions + + +enum ClockHoursState { + CLOCK_HOURS_UNSET = 0, + CLOCK_HOURS_24, + CLOCK_HOURS_12 +}; + + +BFormattingConventions::BFormattingConventions(const char* id) + : + fCachedUse24HourClock(CLOCK_HOURS_UNSET), + fExplicitUse24HourClock(CLOCK_HOURS_UNSET), + fUseStringsFromPreferredLanguage(false), + fICULocale(new ICU_VERSION::Locale(id)) +{ +} + + +BFormattingConventions::BFormattingConventions( + const BFormattingConventions& other) + : + fCachedDateFormats(other.fCachedDateFormats), + fCachedTimeFormats(other.fCachedTimeFormats), + fCachedNumericFormat(other.fCachedNumericFormat), + fCachedMonetaryFormat(other.fCachedMonetaryFormat), + fCachedUse24HourClock(other.fCachedUse24HourClock), + fExplicitDateFormats(other.fExplicitDateFormats), + fExplicitTimeFormats(other.fExplicitTimeFormats), + fExplicitNumericFormat(other.fExplicitNumericFormat), + fExplicitMonetaryFormat(other.fExplicitMonetaryFormat), + fExplicitUse24HourClock(other.fExplicitUse24HourClock), + fUseStringsFromPreferredLanguage(other.fUseStringsFromPreferredLanguage), + fICULocale(new ICU_VERSION::Locale(*other.fICULocale)) +{ +} + + +BFormattingConventions::BFormattingConventions(const BMessage* archive) +{ + BString conventionsID; + status_t status = archive->FindString("conventions", &conventionsID); + fICULocale = new ICU_VERSION::Locale(conventionsID); + + for (int s = 0; s < B_DATE_FORMAT_STYLE_COUNT && status == B_OK; ++s) { + BString format; + status = archive->FindString("dateFormat", s, &format); + if (status == B_OK) + fExplicitDateFormats[s] = format; + + status = archive->FindString("timeFormat", s, &format); + if (status == B_OK) + fExplicitTimeFormats[s] = format; + } + + if (status == B_OK) { + int8 use24HourClock; + status = archive->FindInt8("use24HourClock", &use24HourClock); + if (status == B_OK) + fExplicitUse24HourClock = use24HourClock; + } + if (status == B_OK) { + bool useStringsFromPreferredLanguage; + status = archive->FindBool("useStringsFromPreferredLanguage", + &useStringsFromPreferredLanguage); + if (status == B_OK) + fUseStringsFromPreferredLanguage = useStringsFromPreferredLanguage; + } +} + + +BFormattingConventions& +BFormattingConventions::operator=(const BFormattingConventions& other) +{ + if (this == &other) + return *this; + + for (int s = 0; s < B_DATE_FORMAT_STYLE_COUNT; ++s) + fCachedDateFormats[s] = other.fCachedDateFormats[s]; + for (int s = 0; s < B_TIME_FORMAT_STYLE_COUNT; ++s) + fCachedTimeFormats[s] = other.fCachedTimeFormats[s]; + fCachedNumericFormat = other.fCachedNumericFormat; + fCachedMonetaryFormat = other.fCachedMonetaryFormat; + fCachedUse24HourClock = other.fCachedUse24HourClock; + + for (int s = 0; s < B_DATE_FORMAT_STYLE_COUNT; ++s) + fExplicitDateFormats[s] = other.fExplicitDateFormats[s]; + for (int s = 0; s < B_TIME_FORMAT_STYLE_COUNT; ++s) + fExplicitTimeFormats[s] = other.fExplicitTimeFormats[s]; + fExplicitNumericFormat = other.fExplicitNumericFormat; + fExplicitMonetaryFormat = other.fExplicitMonetaryFormat; + fExplicitUse24HourClock = other.fExplicitUse24HourClock; + + fUseStringsFromPreferredLanguage = other.fUseStringsFromPreferredLanguage; + + *fICULocale = *other.fICULocale; + + return *this; +} + + +BFormattingConventions::~BFormattingConventions() +{ + delete fICULocale; +} + + +bool +BFormattingConventions::operator==(const BFormattingConventions& other) const +{ + if (this == &other) + return true; + + for (int s = 0; s < B_DATE_FORMAT_STYLE_COUNT; ++s) { + if (fExplicitDateFormats[s] != other.fExplicitDateFormats[s]) + return false; + } + for (int s = 0; s < B_TIME_FORMAT_STYLE_COUNT; ++s) { + if (fExplicitTimeFormats[s] != other.fExplicitTimeFormats[s]) + return false; + } + + return fExplicitNumericFormat == other.fExplicitNumericFormat + && fExplicitMonetaryFormat == other.fExplicitMonetaryFormat + && fExplicitUse24HourClock == other.fExplicitUse24HourClock + && fUseStringsFromPreferredLanguage + == other.fUseStringsFromPreferredLanguage + && *fICULocale == *other.fICULocale; +} + + +bool +BFormattingConventions::operator!=(const BFormattingConventions& other) const +{ + return !(*this == other); +} + + +const char* +BFormattingConventions::ID() const +{ + return fICULocale->getName(); +} + + +const char* +BFormattingConventions::LanguageCode() const +{ + return fICULocale->getLanguage(); +} + + +const char* +BFormattingConventions::CountryCode() const +{ + const char* country = fICULocale->getCountry(); + if (country == NULL || country[0] == '\0') + return NULL; + + return country; +} + + +status_t +BFormattingConventions::GetNativeName(BString& name) const +{ + UnicodeString string; + fICULocale->getDisplayName(*fICULocale, string); + string.toTitle(NULL, *fICULocale); + + name.Truncate(0); + BStringByteSink converter(&name); + string.toUTF8(converter); + + return B_OK; +} + + +status_t +BFormattingConventions::GetName(BString& name, + const BLanguage* displayLanguage) const +{ + BString displayLanguageID; + if (displayLanguage == NULL) { + BLanguage defaultLanguage; + be_locale->GetLanguage(&defaultLanguage); + displayLanguageID = defaultLanguage.Code(); + } else { + displayLanguageID = displayLanguage->Code(); + } + + UnicodeString uString; + fICULocale->getDisplayName(Locale(displayLanguageID.String()), uString); + name.Truncate(0); + BStringByteSink stringConverter(&name); + uString.toUTF8(stringConverter); + + return B_OK; +} + + +BMeasurementKind +BFormattingConventions::MeasurementKind() const +{ + UErrorCode error = U_ZERO_ERROR; + switch (ulocdata_getMeasurementSystem(ID(), &error)) { + case UMS_US: + return B_US; + case UMS_SI: + default: + return B_METRIC; + } +} + + +status_t +BFormattingConventions::GetDateFormat(BDateFormatStyle style, + BString& outFormat) const +{ + if (style < 0 || style >= B_DATE_FORMAT_STYLE_COUNT) + return B_BAD_VALUE; + + outFormat = fExplicitDateFormats[style].Length() + ? fExplicitDateFormats[style] + : fCachedDateFormats[style]; + + if (outFormat.Length() > 0) + return B_OK; + + ObjectDeleter dateFormatter( + DateFormat::createDateInstance((DateFormat::EStyle)style, *fICULocale)); + if (dateFormatter.Get() == NULL) + return B_NO_MEMORY; + + SimpleDateFormat* dateFormatterImpl + = static_cast(dateFormatter.Get()); + + UnicodeString icuString; + dateFormatterImpl->toPattern(icuString); + BStringByteSink stringConverter(&outFormat); + icuString.toUTF8(stringConverter); + + fCachedDateFormats[style] = outFormat; + + return B_OK; +} + + +status_t +BFormattingConventions::GetTimeFormat(BTimeFormatStyle style, + BString& outFormat) const +{ + if (style < 0 || style >= B_TIME_FORMAT_STYLE_COUNT) + return B_BAD_VALUE; + + outFormat = fExplicitTimeFormats[style].Length() + ? fExplicitTimeFormats[style] + : fCachedTimeFormats[style]; + + if (outFormat.Length() > 0) + return B_OK; + + ObjectDeleter timeFormatter( + DateFormat::createTimeInstance((DateFormat::EStyle)style, *fICULocale)); + if (timeFormatter.Get() == NULL) + return B_NO_MEMORY; + + SimpleDateFormat* timeFormatterImpl + = static_cast(timeFormatter.Get()); + + UnicodeString icuString; + timeFormatterImpl->toPattern(icuString); + BStringByteSink stringConverter(&outFormat); + icuString.toUTF8(stringConverter); + + int8 use24HourClock = fExplicitUse24HourClock != CLOCK_HOURS_UNSET + ? fExplicitUse24HourClock : fCachedUse24HourClock; + if (use24HourClock != CLOCK_HOURS_UNSET) { + // adjust to 12/24-hour clock as requested + bool localeUses24HourClock = !FormatUsesAmPm(outFormat); + if (localeUses24HourClock) { + if (use24HourClock == CLOCK_HOURS_12) + CoerceFormatTo12HourClock(outFormat); + } else { + if (use24HourClock == CLOCK_HOURS_24) + CoerceFormatTo24HourClock(outFormat); + } + } + + // use abbreviated timezone in short timezone format + CoerceFormatToAbbreviatedTimezone(outFormat); + + fCachedTimeFormats[style] = outFormat; + + return B_OK; +} + + +status_t +BFormattingConventions::GetNumericFormat(BString& outFormat) const +{ + // TODO! + return B_UNSUPPORTED; +} + + +status_t +BFormattingConventions::GetMonetaryFormat(BString& outFormat) const +{ + // TODO! + return B_UNSUPPORTED; +} + + +void +BFormattingConventions::SetExplicitDateFormat(BDateFormatStyle style, + const BString& format) +{ + fExplicitDateFormats[style] = format; +} + + +void +BFormattingConventions::SetExplicitTimeFormat(BTimeFormatStyle style, + const BString& format) +{ + fExplicitTimeFormats[style] = format; +} + + +void +BFormattingConventions::SetExplicitNumericFormat(const BString& format) +{ + fExplicitNumericFormat = format; +} + + +void +BFormattingConventions::SetExplicitMonetaryFormat(const BString& format) +{ + fExplicitMonetaryFormat = format; +} + + +bool +BFormattingConventions::UseStringsFromPreferredLanguage() const +{ + return fUseStringsFromPreferredLanguage; +} + + +void +BFormattingConventions::SetUseStringsFromPreferredLanguage(bool value) +{ + fUseStringsFromPreferredLanguage = value; +} + + +bool +BFormattingConventions::Use24HourClock() const +{ + int8 use24HourClock = fExplicitUse24HourClock != CLOCK_HOURS_UNSET + ? fExplicitUse24HourClock : fCachedUse24HourClock; + + if (use24HourClock == CLOCK_HOURS_UNSET) { + BString format; + GetTimeFormat(B_MEDIUM_TIME_FORMAT, format); + fCachedUse24HourClock + = FormatUsesAmPm(format) ? CLOCK_HOURS_12 : CLOCK_HOURS_24; + } + + return fCachedUse24HourClock == CLOCK_HOURS_24; +} + + +void +BFormattingConventions::SetExplicitUse24HourClock(bool value) +{ + int8 newUse24HourClock = value ? CLOCK_HOURS_24 : CLOCK_HOURS_12; + if (fExplicitUse24HourClock == newUse24HourClock) + return; + + fExplicitUse24HourClock = newUse24HourClock; + + for (int s = 0; s < B_TIME_FORMAT_STYLE_COUNT; ++s) + fCachedTimeFormats[s].Truncate(0); +} + + +void +BFormattingConventions::UnsetExplicitUse24HourClock() +{ + fExplicitUse24HourClock = CLOCK_HOURS_UNSET; + + for (int s = 0; s < B_TIME_FORMAT_STYLE_COUNT; ++s) + fCachedTimeFormats[s].Truncate(0); +} + + +status_t +BFormattingConventions::Archive(BMessage* archive, bool deep) const +{ + status_t status = archive->AddString("conventions", fICULocale->getName()); + for (int s = 0; s < B_DATE_FORMAT_STYLE_COUNT && status == B_OK; ++s) { + status = archive->AddString("dateFormat", fExplicitDateFormats[s]); + if (status == B_OK) + status = archive->AddString("timeFormat", fExplicitTimeFormats[s]); + } + if (status == B_OK) + status = archive->AddInt8("use24HourClock", fExplicitUse24HourClock); + if (status == B_OK) { + status = archive->AddBool("useStringsFromPreferredLanguage", + fUseStringsFromPreferredLanguage); + } + + return status; +} diff --git a/src/kits/locale/Jamfile b/src/kits/locale/Jamfile index 2197235ec1..ba39d87689 100644 --- a/src/kits/locale/Jamfile +++ b/src/kits/locale/Jamfile @@ -12,6 +12,7 @@ local sources = Collator.cpp Country.cpp DefaultCatalog.cpp + FormattingConventions.cpp HashMapCatalog.cpp Language.cpp LibbeLocaleBackend.cpp diff --git a/src/kits/locale/Locale.cpp b/src/kits/locale/Locale.cpp index 425c694acf..563e8b3058 100644 --- a/src/kits/locale/Locale.cpp +++ b/src/kits/locale/Locale.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include @@ -36,40 +36,25 @@ using BPrivate::B_WEEK_START_MONDAY; using BPrivate::B_WEEK_START_SUNDAY; -static DateFormat* CreateDateFormat(bool longFormat, const Locale& locale, - const BString& format); -static DateFormat* CreateTimeFormat(bool longFormat, const Locale& locale, - const BString& format); -static void FetchDateFormat(bool longFormat, const Locale& locale, - BString& format); -static void FetchTimeFormat(bool longFormat, const Locale& locale, - BString& format); - - -BLocale::BLocale(const BLanguage* language, const BCountry* country) +BLocale::BLocale(const BLanguage* language, + const BFormattingConventions* conventions) { - if (country != NULL) - fCountry = *country; + if (conventions != NULL) + fConventions = *conventions; else - be_locale->GetCountry(&fCountry); + be_locale->GetFormattingConventions(&fConventions); if (language != NULL) fLanguage = *language; else be_locale->GetLanguage(&fLanguage); - - _UpdateFormats(); } BLocale::BLocale(const BLocale& other) : - fCountry(other.fCountry), - fLanguage(other.fLanguage), - fLongDateFormat(other.fLongDateFormat), - fShortDateFormat(other.fShortDateFormat), - fLongTimeFormat(other.fLongTimeFormat), - fShortTimeFormat(other.fShortTimeFormat) + fConventions(other.fConventions), + fLanguage(other.fLanguage) { } @@ -80,12 +65,12 @@ BLocale::operator=(const BLocale& other) if (this == &other) return *this; - fLongDateFormat = other.fLongDateFormat; - fShortDateFormat = other.fShortDateFormat; - fLongTimeFormat = other.fLongTimeFormat; - fShortTimeFormat = other.fShortTimeFormat; + BAutolock lock(fLock); + BAutolock otherLock(other.fLock); + if (!lock.IsLocked() || !otherLock.IsLocked()) + return *this; - fCountry = other.fCountry; + fConventions = other.fConventions; fLanguage = other.fLanguage; return *this; @@ -130,16 +115,16 @@ BLocale::GetLanguage(BLanguage* language) const status_t -BLocale::GetCountry(BCountry* country) const +BLocale::GetFormattingConventions(BFormattingConventions* conventions) const { - if (!country) + if (!conventions) return B_BAD_VALUE; BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; - *country = fCountry; + *conventions = fConventions; return B_OK; } @@ -165,15 +150,13 @@ BLocale::GetString(uint32 id) const void -BLocale::SetCountry(const BCountry& newCountry) +BLocale::SetFormattingConventions(const BFormattingConventions& conventions) { BAutolock lock(fLock); if (!lock.IsLocked()) return; - fCountry = newCountry; - - _UpdateFormats(); + fConventions = conventions; } @@ -199,80 +182,64 @@ BLocale::SetLanguage(const BLanguage& newLanguage) } -bool -BLocale::GetName(BString& name) const -{ - Locale icuLocale = Locale::createCanonical(fCountry.Code()); - if (icuLocale.isBogus()) - return false; - - UnicodeString uString; - const Locale* countryLocale = BCountry::Private(&fCountry).ICULocale(); - countryLocale->getDisplayName(icuLocale, uString); - BStringByteSink stringConverter(&name); - uString.toUTF8(stringConverter); - return true; -} - - // #pragma mark - Date -status_t +ssize_t BLocale::FormatDate(char* string, size_t maxSize, time_t time, - bool longFormat) const + BDateFormatStyle style) const { BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; - ObjectDeleter dateFormatter = CreateDateFormat(longFormat, - *BLanguage::Private(&fLanguage).ICULocale(), - longFormat ? fLongDateFormat : fShortDateFormat); + BString format; + fConventions.GetDateFormat(style, format); + ObjectDeleter dateFormatter(_CreateDateFormatter(format)); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; - UnicodeString ICUString; - ICUString = dateFormatter->format((UDate)time * 1000, ICUString); + UnicodeString icuString; + dateFormatter->format((UDate)time * 1000, icuString); CheckedArrayByteSink stringConverter(string, maxSize); - ICUString.toUTF8(stringConverter); + icuString.toUTF8(stringConverter); if (stringConverter.Overflowed()) return B_BAD_VALUE; - return B_OK; + return stringConverter.NumberOfBytesWritten(); } status_t -BLocale::FormatDate(BString *string, time_t time, bool longFormat, +BLocale::FormatDate(BString *string, time_t time, BDateFormatStyle style, const BTimeZone* timeZone) const { BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; - ObjectDeleter dateFormatter = CreateDateFormat(longFormat, - *BLanguage::Private(&fLanguage).ICULocale(), - longFormat ? fLongDateFormat : fShortDateFormat); + BString format; + fConventions.GetDateFormat(style, format); + ObjectDeleter dateFormatter(_CreateDateFormatter(format)); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; if (timeZone != NULL) { - ObjectDeleter icuTimeZone - = TimeZone::createTimeZone(timeZone->ID().String()); + ObjectDeleter icuTimeZone( + TimeZone::createTimeZone(timeZone->ID().String())); if (icuTimeZone.Get() == NULL) return B_NO_MEMORY; dateFormatter->setTimeZone(*icuTimeZone.Get()); } - UnicodeString ICUString; - ICUString = dateFormatter->format((UDate)time * 1000, ICUString); + UnicodeString icuString; + dateFormatter->format((UDate)time * 1000, icuString); string->Truncate(0); BStringByteSink stringConverter(string); - ICUString.toUTF8(stringConverter); + icuString.toUTF8(stringConverter); return B_OK; } @@ -280,24 +247,24 @@ BLocale::FormatDate(BString *string, time_t time, bool longFormat, status_t BLocale::FormatDate(BString* string, int*& fieldPositions, int& fieldCount, - time_t time, bool longFormat) const + time_t time, BDateFormatStyle style) const { BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; - ObjectDeleter dateFormatter = CreateDateFormat(longFormat, - *BLanguage::Private(&fLanguage).ICULocale(), - longFormat ? fLongDateFormat : fShortDateFormat); + BString format; + fConventions.GetDateFormat(style, format); + ObjectDeleter dateFormatter(_CreateDateFormatter(format)); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; fieldPositions = NULL; UErrorCode error = U_ZERO_ERROR; ICU_VERSION::FieldPositionIterator positionIterator; - UnicodeString ICUString; - ICUString = dateFormatter->format((UDate)time * 1000, ICUString, - &positionIterator, error); + UnicodeString icuString; + dateFormatter->format((UDate)time * 1000, icuString, &positionIterator, + error); if (error != U_ZERO_ERROR) return B_ERROR; @@ -319,57 +286,7 @@ BLocale::FormatDate(BString* string, int*& fieldPositions, int& fieldCount, string->Truncate(0); BStringByteSink stringConverter(string); - ICUString.toUTF8(stringConverter); - - return B_OK; -} - - -status_t -BLocale::GetDateFormat(BString& format, bool longFormat) const -{ - BAutolock lock(fLock); - if (!lock.IsLocked()) - return B_ERROR; - - if (longFormat && fLongDateFormat.Length() > 0) - format = fLongDateFormat; - else if (!longFormat && fShortDateFormat.Length() > 0) - format = fShortDateFormat; - else { - format.Truncate(0); - - ObjectDeleter dateFormatter = CreateDateFormat(longFormat, - *BCountry::Private(&fCountry).ICULocale(), format); - if (dateFormatter.Get() == NULL) - return B_NO_MEMORY; - - SimpleDateFormat* dateFormatterImpl - = static_cast(dateFormatter.Get()); - - UnicodeString ICUString; - ICUString = dateFormatterImpl->toPattern(ICUString); - - BStringByteSink stringConverter(&format); - - ICUString.toUTF8(stringConverter); - } - - return B_OK; -} - - -status_t -BLocale::SetDateFormat(const char* formatString, bool longFormat) -{ - BAutolock lock(fLock); - if (!lock.IsLocked()) - return B_ERROR; - - if (longFormat) - fLongDateFormat = formatString; - else - fShortDateFormat = formatString; + icuString.toUTF8(stringConverter); return B_OK; } @@ -377,24 +294,24 @@ BLocale::SetDateFormat(const char* formatString, bool longFormat) status_t BLocale::GetDateFields(BDateElement*& fields, int& fieldCount, - bool longFormat) const + BDateFormatStyle style) const { BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; - ObjectDeleter dateFormatter = CreateDateFormat(longFormat, - *BCountry::Private(&fCountry).ICULocale(), - longFormat ? fLongDateFormat : fShortDateFormat); + BString format; + fConventions.GetDateFormat(style, format); + ObjectDeleter dateFormatter(_CreateDateFormatter(format)); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; fields = NULL; UErrorCode error = U_ZERO_ERROR; ICU_VERSION::FieldPositionIterator positionIterator; - UnicodeString ICUString; + UnicodeString icuString; time_t now; - ICUString = dateFormatter->format((UDate)time(&now) * 1000, ICUString, + dateFormatter->format((UDate)time(&now) * 1000, icuString, &positionIterator, error); if (U_FAILURE(error)) @@ -439,9 +356,9 @@ BLocale::StartOfWeek() const return B_ERROR; UErrorCode err = U_ZERO_ERROR; - Calendar* c - = Calendar::createInstance(*BCountry::Private(&fCountry).ICULocale(), - err); + Calendar* c = Calendar::createInstance( + *BFormattingConventions::Private(&fConventions).ICULocale(), + err); if (err == U_ZERO_ERROR && c->getFirstDayOfWeek(err) == UCAL_SUNDAY) { delete c; @@ -454,81 +371,78 @@ BLocale::StartOfWeek() const } -status_t +ssize_t BLocale::FormatDateTime(char* target, size_t maxSize, time_t time, - bool longFormat) const + BDateFormatStyle dateStyle, BTimeFormatStyle timeStyle) const { BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; - ObjectDeleter dateFormatter = CreateDateFormat(longFormat, - *BLanguage::Private(&fLanguage).ICULocale(), - longFormat ? fLongDateFormat : fShortDateFormat); + BString format; + fConventions.GetDateFormat(dateStyle, format); + ObjectDeleter dateFormatter(_CreateDateFormatter(format)); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; - ObjectDeleter timeFormatter = CreateTimeFormat(longFormat, - *BLanguage::Private(&fLanguage).ICULocale(), - longFormat ? fLongTimeFormat : fShortTimeFormat); + fConventions.GetTimeFormat(timeStyle, format); + ObjectDeleter timeFormatter(_CreateTimeFormatter(format)); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; - UnicodeString ICUString; - ICUString = dateFormatter->format((UDate)time * 1000, ICUString); + UnicodeString icuString; + dateFormatter->format((UDate)time * 1000, icuString); - ICUString.append(UnicodeString::fromUTF8(", ")); + icuString.append(UnicodeString::fromUTF8(", ")); - ICUString = timeFormatter->format((UDate)time * 1000, ICUString); + timeFormatter->format((UDate)time * 1000, icuString); CheckedArrayByteSink stringConverter(target, maxSize); - ICUString.toUTF8(stringConverter); + icuString.toUTF8(stringConverter); if (stringConverter.Overflowed()) return B_BAD_VALUE; - return B_OK; + return stringConverter.NumberOfBytesWritten(); } status_t -BLocale::FormatDateTime(BString* target, time_t time, bool longFormat, +BLocale::FormatDateTime(BString* target, time_t time, + BDateFormatStyle dateStyle, BTimeFormatStyle timeStyle, const BTimeZone* timeZone) const { BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; - ObjectDeleter dateFormatter = CreateDateFormat(longFormat, - *BLanguage::Private(&fLanguage).ICULocale(), - longFormat ? fLongDateFormat : fShortDateFormat); + BString format; + fConventions.GetDateFormat(dateStyle, format); + ObjectDeleter dateFormatter(_CreateDateFormatter(format)); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; - ObjectDeleter timeFormatter = CreateTimeFormat(longFormat, - *BLanguage::Private(&fLanguage).ICULocale(), - longFormat ? fLongTimeFormat : fShortTimeFormat); + fConventions.GetTimeFormat(timeStyle, format); + ObjectDeleter timeFormatter(_CreateTimeFormatter(format)); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; if (timeZone != NULL) { - ObjectDeleter icuTimeZone - = TimeZone::createTimeZone(timeZone->ID().String()); + ObjectDeleter icuTimeZone( + TimeZone::createTimeZone(timeZone->ID().String())); if (icuTimeZone.Get() == NULL) return B_NO_MEMORY; timeFormatter->setTimeZone(*icuTimeZone.Get()); } - UnicodeString ICUString; - ICUString = dateFormatter->format((UDate)time * 1000, ICUString); - - ICUString.append(UnicodeString::fromUTF8(", ")); - - ICUString = timeFormatter->format((UDate)time * 1000, ICUString); + UnicodeString icuString; + dateFormatter->format((UDate)time * 1000, icuString); + icuString.append(UnicodeString::fromUTF8(", ")); + timeFormatter->format((UDate)time * 1000, icuString); target->Truncate(0); BStringByteSink stringConverter(target); - ICUString.toUTF8(stringConverter); + icuString.toUTF8(stringConverter); return B_OK; } @@ -537,63 +451,61 @@ BLocale::FormatDateTime(BString* target, time_t time, bool longFormat, // #pragma mark - Time -status_t +ssize_t BLocale::FormatTime(char* string, size_t maxSize, time_t time, - bool longFormat) const + BTimeFormatStyle style) const { BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; - ObjectDeleter timeFormatter = CreateTimeFormat(longFormat, - *BLanguage::Private(&fLanguage).ICULocale(), - longFormat ? fLongTimeFormat : fShortTimeFormat); + BString format; + fConventions.GetTimeFormat(style, format); + ObjectDeleter timeFormatter(_CreateTimeFormatter(format)); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; - UnicodeString ICUString; - ICUString = timeFormatter->format((UDate)time * 1000, ICUString); + UnicodeString icuString; + timeFormatter->format((UDate)time * 1000, icuString); CheckedArrayByteSink stringConverter(string, maxSize); - - ICUString.toUTF8(stringConverter); + icuString.toUTF8(stringConverter); if (stringConverter.Overflowed()) return B_BAD_VALUE; - return B_OK; + return stringConverter.NumberOfBytesWritten(); } status_t -BLocale::FormatTime(BString* string, time_t time, bool longFormat, +BLocale::FormatTime(BString* string, time_t time, BTimeFormatStyle style, const BTimeZone* timeZone) const { BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; - ObjectDeleter timeFormatter = CreateTimeFormat(longFormat, - *BLanguage::Private(&fLanguage).ICULocale(), - longFormat ? fLongTimeFormat : fShortTimeFormat); + BString format; + fConventions.GetTimeFormat(style, format); + ObjectDeleter timeFormatter(_CreateTimeFormatter(format)); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; if (timeZone != NULL) { - ObjectDeleter icuTimeZone - = TimeZone::createTimeZone(timeZone->ID().String()); + ObjectDeleter icuTimeZone( + TimeZone::createTimeZone(timeZone->ID().String())); if (icuTimeZone.Get() == NULL) return B_NO_MEMORY; timeFormatter->setTimeZone(*icuTimeZone.Get()); } - UnicodeString ICUString; - ICUString = timeFormatter->format((UDate)time * 1000, ICUString); + UnicodeString icuString; + timeFormatter->format((UDate)time * 1000, icuString); string->Truncate(0); BStringByteSink stringConverter(string); - - ICUString.toUTF8(stringConverter); + icuString.toUTF8(stringConverter); return B_OK; } @@ -601,24 +513,24 @@ BLocale::FormatTime(BString* string, time_t time, bool longFormat, status_t BLocale::FormatTime(BString* string, int*& fieldPositions, int& fieldCount, - time_t time, bool longFormat) const + time_t time, BTimeFormatStyle style) const { BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; - ObjectDeleter timeFormatter = CreateTimeFormat(longFormat, - *BLanguage::Private(&fLanguage).ICULocale(), - longFormat ? fLongTimeFormat : fShortTimeFormat); + BString format; + fConventions.GetTimeFormat(style, format); + ObjectDeleter timeFormatter(_CreateTimeFormatter(format)); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; fieldPositions = NULL; UErrorCode error = U_ZERO_ERROR; ICU_VERSION::FieldPositionIterator positionIterator; - UnicodeString ICUString; - ICUString = timeFormatter->format((UDate)time * 1000, ICUString, - &positionIterator, error); + UnicodeString icuString; + timeFormatter->format((UDate)time * 1000, icuString, &positionIterator, + error); if (error != U_ZERO_ERROR) return B_ERROR; @@ -639,8 +551,7 @@ BLocale::FormatTime(BString* string, int*& fieldPositions, int& fieldCount, string->Truncate(0); BStringByteSink stringConverter(string); - - ICUString.toUTF8(stringConverter); + icuString.toUTF8(stringConverter); return B_OK; } @@ -648,24 +559,24 @@ BLocale::FormatTime(BString* string, int*& fieldPositions, int& fieldCount, status_t BLocale::GetTimeFields(BDateElement*& fields, int& fieldCount, - bool longFormat) const + BTimeFormatStyle style) const { BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; - ObjectDeleter timeFormatter = CreateTimeFormat(longFormat, - *BCountry::Private(&fCountry).ICULocale(), - longFormat ? fLongTimeFormat : fShortTimeFormat); + BString format; + fConventions.GetTimeFormat(style, format); + ObjectDeleter timeFormatter(_CreateTimeFormatter(format)); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; fields = NULL; UErrorCode error = U_ZERO_ERROR; ICU_VERSION::FieldPositionIterator positionIterator; - UnicodeString ICUString; + UnicodeString icuString; time_t now; - ICUString = timeFormatter->format((UDate)time(&now) * 1000, ICUString, + timeFormatter->format((UDate)time(&now) * 1000, icuString, &positionIterator, error); if (error != U_ZERO_ERROR) @@ -708,82 +619,18 @@ BLocale::GetTimeFields(BDateElement*& fields, int& fieldCount, } -status_t -BLocale::SetTimeFormat(const char* formatString, bool longFormat) -{ - BAutolock lock(fLock); - if (!lock.IsLocked()) - return B_ERROR; - - if (longFormat) - fLongTimeFormat = formatString; - else - fShortTimeFormat = formatString; - - return B_OK; -} - - -status_t -BLocale::GetTimeFormat(BString& format, bool longFormat) const -{ - BAutolock lock(fLock); - if (!lock.IsLocked()) - return B_ERROR; - - if (longFormat && fLongTimeFormat.Length() > 0) - format = fLongTimeFormat; - else if (!longFormat && fShortTimeFormat.Length() > 0) - format = fShortTimeFormat; - else { - format.Truncate(0); - - ObjectDeleter timeFormatter = CreateTimeFormat(longFormat, - *BCountry::Private(&fCountry).ICULocale(), - longFormat ? fLongTimeFormat : fShortTimeFormat); - if (timeFormatter.Get() == NULL) - return B_NO_MEMORY; - - SimpleDateFormat* timeFormatterImpl - = static_cast(timeFormatter.Get()); - - UnicodeString ICUString; - ICUString = timeFormatterImpl->toPattern(ICUString); - - BStringByteSink stringConverter(&format); - ICUString.toUTF8(stringConverter); - } - - return B_OK; -} - - -void -BLocale::_UpdateFormats() -{ - FetchDateFormat(true, *BCountry::Private(&fCountry).ICULocale(), - this->fLongDateFormat); - FetchDateFormat(false, *BCountry::Private(&fCountry).ICULocale(), - this->fShortDateFormat); - FetchTimeFormat(true, *BCountry::Private(&fCountry).ICULocale(), - this->fLongTimeFormat); - FetchTimeFormat(false, *BCountry::Private(&fCountry).ICULocale(), - this->fShortTimeFormat); -} - - // #pragma mark - Numbers -status_t +ssize_t BLocale::FormatNumber(char* string, size_t maxSize, double value) const { BString fullString; status_t status = FormatNumber(&fullString, value); - if (status == B_OK) - strlcpy(string, fullString.String(), maxSize); + if (status != B_OK) + return status; - return status; + return strlcpy(string, fullString.String(), maxSize); } @@ -795,35 +642,35 @@ BLocale::FormatNumber(BString* string, double value) const return B_ERROR; UErrorCode err = U_ZERO_ERROR; - ObjectDeleter numberFormatter = NumberFormat::createInstance( - *BCountry::Private(&fCountry).ICULocale(), NumberFormat::kNumberStyle, - err); + ObjectDeleter numberFormatter(NumberFormat::createInstance( + *BFormattingConventions::Private(&fConventions).ICULocale(), + NumberFormat::kNumberStyle, err)); if (numberFormatter.Get() == NULL) return B_NO_MEMORY; if (U_FAILURE(err)) return B_ERROR; - UnicodeString ICUString; - ICUString = numberFormatter->format(value, ICUString); + UnicodeString icuString; + numberFormatter->format(value, icuString); string->Truncate(0); BStringByteSink stringConverter(string); - ICUString.toUTF8(stringConverter); + icuString.toUTF8(stringConverter); return B_OK; } -status_t +ssize_t BLocale::FormatNumber(char* string, size_t maxSize, int32 value) const { BString fullString; status_t status = FormatNumber(&fullString, value); - if (status == B_OK) - strlcpy(string, fullString.String(), maxSize); + if (status != B_OK) + return status; - return status; + return strlcpy(string, fullString.String(), maxSize); } @@ -835,21 +682,21 @@ BLocale::FormatNumber(BString* string, int32 value) const return B_ERROR; UErrorCode err = U_ZERO_ERROR; - ObjectDeleter numberFormatter = NumberFormat::createInstance( - *BCountry::Private(&fCountry).ICULocale(), NumberFormat::kNumberStyle, - err); + ObjectDeleter numberFormatter(NumberFormat::createInstance( + *BFormattingConventions::Private(&fConventions).ICULocale(), + NumberFormat::kNumberStyle, err)); if (numberFormatter.Get() == NULL) return B_NO_MEMORY; if (U_FAILURE(err)) return B_ERROR; - UnicodeString ICUString; - ICUString = numberFormatter->format((int32_t)value, ICUString); + UnicodeString icuString; + numberFormatter->format((int32_t)value, icuString); string->Truncate(0); BStringByteSink stringConverter(string); - ICUString.toUTF8(stringConverter); + icuString.toUTF8(stringConverter); return B_OK; } @@ -859,15 +706,15 @@ ssize_t BLocale::FormatMonetary(char* string, size_t maxSize, double value) const { BString fullString; - ssize_t written = FormatMonetary(&fullString, value); - if (written < 0) - return written; + status_t status = FormatMonetary(&fullString, value); + if (status != B_OK) + return status; return strlcpy(string, fullString.String(), maxSize); } -ssize_t +status_t BLocale::FormatMonetary(BString* string, double value) const { if (string == NULL) @@ -877,186 +724,69 @@ BLocale::FormatMonetary(BString* string, double value) const if (!lock.IsLocked()) return B_ERROR; - UErrorCode err; - ObjectDeleter numberFormatter - = NumberFormat::createCurrencyInstance( - *BCountry::Private(&fCountry).ICULocale(), err); + UErrorCode err = U_ZERO_ERROR; + ObjectDeleter numberFormatter( + NumberFormat::createCurrencyInstance( + *BFormattingConventions::Private(&fConventions).ICULocale(), + err)); if (numberFormatter.Get() == NULL) return B_NO_MEMORY; if (U_FAILURE(err)) return B_ERROR; - UnicodeString ICUString; - ICUString = numberFormatter->format(value, ICUString); + UnicodeString icuString; + numberFormatter->format(value, icuString); string->Truncate(0); BStringByteSink stringConverter(string); - ICUString.toUTF8(stringConverter); - - return string->Length(); -} - - -status_t -BLocale::FormatMonetary(BString* string, int*& fieldPositions, - BNumberElement*& fieldTypes, int& fieldCount, double value) const -{ - BAutolock lock(fLock); - if (!lock.IsLocked()) - return B_ERROR; - - UErrorCode err = U_ZERO_ERROR; - ObjectDeleter numberFormatter - = NumberFormat::createCurrencyInstance( - *BCountry::Private(&fCountry).ICULocale(), err); - if (U_FAILURE(err)) - return B_NO_MEMORY; - - fieldPositions = NULL; - fieldTypes = NULL; - ICU_VERSION::FieldPositionIterator positionIterator; - UnicodeString ICUString; - ICUString = numberFormatter->format(value, ICUString, &positionIterator, - err); - - if (err != U_ZERO_ERROR) - return B_ERROR; - - ICU_VERSION::FieldPosition field; - std::vector fieldPosStorage; - std::vector fieldTypeStorage; - fieldCount = 0; - while (positionIterator.next(field)) { - fieldTypeStorage.push_back(field.getField()); - fieldPosStorage.push_back(field.getBeginIndex() | (field.getEndIndex() << 16)); - fieldCount ++; - - } - - fieldPositions = (int*) malloc(fieldCount * sizeof(int)); - fieldTypes = (BNumberElement*) malloc(fieldCount * sizeof(BNumberElement)); - - for (int i = 0 ; i < fieldCount ; i++ ) { - fieldPositions[i] = fieldPosStorage[i]; - switch (fieldTypeStorage[i]) { - case NumberFormat::kCurrencyField: - fieldTypes[i] = B_NUMBER_ELEMENT_CURRENCY; - break; - case NumberFormat::kIntegerField: - fieldTypes[i] = B_NUMBER_ELEMENT_INTEGER; - break; - case NumberFormat::kFractionField: - fieldTypes[i] = B_NUMBER_ELEMENT_FRACTIONAL; - break; - default: - fieldTypes[i] = B_NUMBER_ELEMENT_INVALID; - break; - } - } - - string->Truncate(0); - BStringByteSink stringConverter(string); - - ICUString.toUTF8(stringConverter); + icuString.toUTF8(stringConverter); return B_OK; } -status_t -BLocale::GetCurrencySymbol(BString& result) const +DateFormat* +BLocale::_CreateDateFormatter(const BString& format) const { - BAutolock lock(fLock); - if (!lock.IsLocked()) - return B_ERROR; + Locale* icuLocale + = fConventions.UseStringsFromPreferredLanguage() + ? BLanguage::Private(&fLanguage).ICULocale() + : BFormattingConventions::Private(&fConventions).ICULocale(); - UErrorCode error = U_ZERO_ERROR; - NumberFormat* format = NumberFormat::createCurrencyInstance( - *BCountry::Private(&fCountry).ICULocale(), error); + DateFormat* dateFormatter + = DateFormat::createDateInstance(DateFormat::kShort, *icuLocale); + if (dateFormatter == NULL) + return NULL; - if (U_FAILURE(error)) - return B_ERROR; + SimpleDateFormat* dateFormatterImpl + = static_cast(dateFormatter); - char* symbol = (char*)malloc(20); - u_strToUTF8(symbol, 20, NULL, format->getCurrency(), -1, &error); - if (U_FAILURE(error)) - return B_BAD_DATA; - result.Append(symbol); - delete format; - delete symbol; - return B_OK; -} - - -// #pragma mark - Helpers - - -static DateFormat* -CreateDateFormat(bool longFormat, const Locale& locale, const BString& format) -{ - DateFormat* dateFormatter = DateFormat::createDateInstance( - longFormat ? DateFormat::kFull : DateFormat::kShort, locale); - - if (format.Length() > 0) { - SimpleDateFormat* dateFormatterImpl - = static_cast(dateFormatter); - - UnicodeString pattern(format.String()); - dateFormatterImpl->applyPattern(pattern); - } + UnicodeString pattern(format.String()); + dateFormatterImpl->applyPattern(pattern); return dateFormatter; } -static DateFormat* -CreateTimeFormat(bool longFormat, const Locale& locale, const BString& format) +DateFormat* +BLocale::_CreateTimeFormatter(const BString& format) const { - DateFormat* timeFormatter = DateFormat::createTimeInstance( - longFormat ? DateFormat::kMedium: DateFormat::kShort, locale); + Locale* icuLocale + = fConventions.UseStringsFromPreferredLanguage() + ? BLanguage::Private(&fLanguage).ICULocale() + : BFormattingConventions::Private(&fConventions).ICULocale(); - if (format.Length() > 0) { - SimpleDateFormat* timeFormatterImpl - = static_cast(timeFormatter); - - UnicodeString pattern(format.String()); - timeFormatterImpl->applyPattern(pattern); - } - - return timeFormatter; -} - - -static void -FetchDateFormat(bool longFormat, const Locale& locale, BString& format) -{ - DateFormat* dateFormatter = DateFormat::createDateInstance( - longFormat ? DateFormat::kFull : DateFormat::kShort, locale); - - SimpleDateFormat* dateFormatterImpl - = static_cast(dateFormatter); - - UnicodeString pattern; - dateFormatterImpl->toPattern(pattern); - format.Truncate(0); - BStringByteSink stringConverter(&format); - pattern.toUTF8(stringConverter); -} - - -static void -FetchTimeFormat(bool longFormat, const Locale& locale, BString& format) -{ - DateFormat* timeFormatter = DateFormat::createTimeInstance( - longFormat ? DateFormat::kMedium : DateFormat::kShort, locale); + DateFormat* timeFormatter + = DateFormat::createTimeInstance(DateFormat::kShort, *icuLocale); + if (timeFormatter == NULL) + return NULL; SimpleDateFormat* timeFormatterImpl = static_cast(timeFormatter); - UnicodeString pattern; - timeFormatterImpl->toPattern(pattern); - format.Truncate(0); - BStringByteSink stringConverter(&format); - pattern.toUTF8(stringConverter); + UnicodeString pattern(format.String()); + timeFormatterImpl->applyPattern(pattern); + + return timeFormatter; } diff --git a/src/kits/locale/LocaleRoster.cpp b/src/kits/locale/LocaleRoster.cpp index 346ad9389f..7293d6a930 100644 --- a/src/kits/locale/LocaleRoster.cpp +++ b/src/kits/locale/LocaleRoster.cpp @@ -20,11 +20,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include @@ -261,8 +261,8 @@ BLocaleRoster::GetFlagIconForCountry(BBitmap* flagIcon, const char* countryCode) status_t -BLocaleRoster::GetInstalledCatalogs(BMessage* languageList, - const char* sigPattern, const char* langPattern, int32 fingerprint) const +BLocaleRoster::GetAvailableCatalogs(BMessage* languageList, + const char* sigPattern, const char* langPattern, int32 fingerprint) const { if (languageList == NULL) return B_BAD_VALUE; diff --git a/src/kits/locale/MutableLocaleRoster.cpp b/src/kits/locale/MutableLocaleRoster.cpp index 7d360bfad6..c39802ebc3 100644 --- a/src/kits/locale/MutableLocaleRoster.cpp +++ b/src/kits/locale/MutableLocaleRoster.cpp @@ -18,12 +18,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include #include @@ -129,6 +129,11 @@ RosterData gRosterData; static const char* kPriorityAttr = "ADDON:priority"; +static const char* kLanguageField = "language"; + +static const char* kTimezoneField = "timezone"; +static const char* kOffsetField = "offset"; + RosterData::RosterData() : @@ -322,7 +327,8 @@ RosterData::CleanupCatalogAddOns() status_t -RosterData::SetDefaultCountry(const BCountry& newCountry) +RosterData::SetDefaultFormattingConventions( + const BFormattingConventions& newFormattingConventions) { status_t status = B_OK; @@ -330,40 +336,14 @@ RosterData::SetDefaultCountry(const BCountry& newCountry) if (!lock.IsLocked()) return B_ERROR; - status = _SetDefaultCountry(newCountry); + status = _SetDefaultFormattingConventions(newFormattingConventions); if (status == B_OK) status = _SaveLocaleSettings(); if (status == B_OK) { BMessage updateMessage(B_LOCALE_CHANGED); - status = _AddDefaultCountryToMessage(&updateMessage); - if (status == B_OK) - status = be_roster->Broadcast(&updateMessage); - } - - return status; -} - - -status_t -RosterData::SetDefaultLocale(const BLocale& newLocale) -{ - status_t status = B_OK; - - BAutolock lock(fLock); - if (!lock.IsLocked()) - return B_ERROR; - - status = _SetDefaultLocale(newLocale); - - if (status == B_OK) - status = _SaveLocaleSettings(); - - if (status == B_OK) { - BMessage updateMessage(B_LOCALE_CHANGED); - status = _AddDefaultCountryToMessage(&updateMessage); - // TODO : should be differenciated from country + status = _AddDefaultFormattingConventionsToMessage(&updateMessage); if (status == B_OK) status = be_roster->Broadcast(&updateMessage); } @@ -437,21 +417,8 @@ RosterData::_LoadLocaleSettings() status = settings.Unflatten(&file); if (status == B_OK) { - BString codeName; - BLocale newDefaultLocale; - - if (settings.FindString("country", &codeName) == B_OK) { - BCountry country(codeName); - newDefaultLocale = BLocale(NULL, &country); - } - - BString timeFormat; - if (settings.FindString("shortTimeFormat", &timeFormat) == B_OK) - newDefaultLocale.SetTimeFormat(timeFormat, false); - if (settings.FindString("longTimeFormat", &timeFormat) == B_OK) - newDefaultLocale.SetTimeFormat(timeFormat, true); - - _SetDefaultLocale(newDefaultLocale); + BFormattingConventions conventions(&settings); + fDefaultLocale.SetFormattingConventions(conventions); _SetPreferredLanguages(&settings); @@ -463,9 +430,11 @@ RosterData::_LoadLocaleSettings() // set everything to default values fPreferredLanguages.MakeEmpty(); - fPreferredLanguages.AddString("language", "en"); + fPreferredLanguages.AddString(kLanguageField, "en"); BLanguage defaultLanguage("en_US"); - _SetDefaultLocale(BLocale(&defaultLanguage)); + fDefaultLocale.SetLanguage(defaultLanguage); + BFormattingConventions conventions("en_US"); + fDefaultLocale.SetFormattingConventions(conventions); return status; } @@ -486,7 +455,7 @@ RosterData::_LoadTimeSettings() status = settings.Unflatten(&file); if (status == B_OK) { BString timeZoneID; - if (settings.FindString("timezone", &timeZoneID) == B_OK) + if (settings.FindString(kTimezoneField, &timeZoneID) == B_OK) _SetDefaultTimeZone(BTimeZone(timeZoneID.String())); else _SetDefaultTimeZone(BTimeZone(BTimeZone::kNameOfGmtZone)); @@ -506,7 +475,7 @@ status_t RosterData::_SaveLocaleSettings() { BMessage settings; - status_t status = _AddDefaultCountryToMessage(&settings); + status_t status = _AddDefaultFormattingConventionsToMessage(&settings); if (status == B_OK) _AddPreferredLanguagesToMessage(&settings); @@ -555,32 +524,13 @@ RosterData::_SaveTimeSettings() status_t -RosterData::_SetDefaultCountry(const BCountry& newCountry) +RosterData::_SetDefaultFormattingConventions( + const BFormattingConventions& newFormattingConventions) { - fDefaultLocale.SetCountry(newCountry); + fDefaultLocale.SetFormattingConventions(newFormattingConventions); UErrorCode icuError = U_ZERO_ERROR; - Locale icuLocale = Locale::createCanonical(newCountry.Code()); - if (icuLocale.isBogus()) - return B_ERROR; - - Locale::setDefault(icuLocale, icuError); - if (!U_SUCCESS(icuError)) - return B_ERROR; - - return B_OK; -} - - -status_t -RosterData::_SetDefaultLocale(const BLocale& newLocale) -{ - fDefaultLocale = newLocale; - - UErrorCode icuError = U_ZERO_ERROR; - BCountry defaultCountry; - newLocale.GetCountry(&defaultCountry); - Locale icuLocale = Locale::createCanonical(defaultCountry.Code()); + Locale icuLocale = Locale::createCanonical(newFormattingConventions.ID()); if (icuLocale.isBogus()) return B_ERROR; @@ -611,18 +561,18 @@ RosterData::_SetPreferredLanguages(const BMessage* languages) { BString langName; if (languages != NULL - && languages->FindString("language", &langName) == B_OK) { + && languages->FindString(kLanguageField, &langName) == B_OK) { fDefaultLocale.SetCollator(BCollator(langName.String())); fDefaultLocale.SetLanguage(BLanguage(langName.String())); - fPreferredLanguages.RemoveName("language"); - for (int i = 0; languages->FindString("language", i, &langName) == B_OK; - i++) { - fPreferredLanguages.AddString("language", langName); + fPreferredLanguages.RemoveName(kLanguageField); + for (int i = 0; languages->FindString(kLanguageField, i, &langName) + == B_OK; i++) { + fPreferredLanguages.AddString(kLanguageField, langName); } } else { fPreferredLanguages.MakeEmpty(); - fPreferredLanguages.AddString("language", "en"); + fPreferredLanguages.AddString(kLanguageField, "en"); fDefaultLocale.SetCollator(BCollator("en")); } @@ -631,34 +581,26 @@ RosterData::_SetPreferredLanguages(const BMessage* languages) status_t -RosterData::_AddDefaultCountryToMessage(BMessage* message) const +RosterData::_AddDefaultFormattingConventionsToMessage(BMessage* message) const { - BCountry defaultCountry; - fDefaultLocale.GetCountry(&defaultCountry); - status_t status = message->AddString("country", defaultCountry.Code()); - BString timeFormat; - if (status == B_OK) - status = fDefaultLocale.GetTimeFormat(timeFormat, false); - if (status == B_OK) - status = message->AddString("shortTimeFormat", timeFormat.String()); - if (status == B_OK) - status = fDefaultLocale.GetTimeFormat(timeFormat, true); - if (status == B_OK) - status = message->AddString("longTimeFormat", timeFormat.String()); + BFormattingConventions conventions; + fDefaultLocale.GetFormattingConventions(&conventions); - return status; + return conventions.Archive(message); } status_t RosterData::_AddDefaultTimeZoneToMessage(BMessage* message) const { - status_t status = message->AddString("timezone", fDefaultTimeZone.ID()); + status_t status = message->AddString(kTimezoneField, fDefaultTimeZone.ID()); // add the offset, too, since that is used by clockconfig when setting // up timezone state during boot - if (status == B_OK) - status = message->AddInt32("offset", fDefaultTimeZone.OffsetFromGMT()); + if (status == B_OK) { + status = message->AddInt32(kOffsetField, + fDefaultTimeZone.OffsetFromGMT()); + } return status; } @@ -672,7 +614,7 @@ RosterData::_AddPreferredLanguagesToMessage(BMessage* message) const BString langName; for (int i = 0; fPreferredLanguages.FindString("language", i, &langName) == B_OK; i++) { - status = message->AddString("language", langName); + status = message->AddString(kLanguageField, langName); if (status != B_OK) break; } @@ -699,16 +641,9 @@ MutableLocaleRoster::~MutableLocaleRoster() status_t -MutableLocaleRoster::SetDefaultCountry(const BCountry& newCountry) +MutableLocaleRoster::SetDefaultFormattingConventions(const BFormattingConventions& newFormattingConventions) { - return gRosterData.SetDefaultCountry(newCountry); -} - - -status_t -MutableLocaleRoster::SetDefaultLocale(const BLocale& newLocale) -{ - return gRosterData.SetDefaultLocale(newLocale); + return gRosterData.SetDefaultFormattingConventions(newFormattingConventions); } @@ -726,22 +661,6 @@ MutableLocaleRoster::SetPreferredLanguages(const BMessage* languages) } -status_t -MutableLocaleRoster::GetDefaultLocale(BLocale* locale) const -{ - if (!locale) - return B_BAD_VALUE; - - BAutolock lock(gRosterData.fLock); - if (!lock.IsLocked()) - return B_ERROR; - - *locale = gRosterData.fDefaultLocale; - - return B_OK; -} - - status_t MutableLocaleRoster::GetSystemCatalog(BCatalogAddOn** catalog) const { diff --git a/src/kits/tracker/WidgetAttributeText.cpp b/src/kits/tracker/WidgetAttributeText.cpp index 3763998ab7..5fd0e651af 100644 --- a/src/kits/tracker/WidgetAttributeText.cpp +++ b/src/kits/tracker/WidgetAttributeText.cpp @@ -190,11 +190,13 @@ TruncTimeBase(BString* result, int64 value, const View* view, float width) time_t timeValue = (time_t)value; - if (be_locale->FormatDateTime(buffer, 256, timeValue, true) == B_OK) + if (be_locale->FormatDateTime(buffer, 256, timeValue, B_FULL_DATE_FORMAT, + B_MEDIUM_TIME_FORMAT) == B_OK) resultWidth = view->StringWidth(buffer); if (resultWidth > width - && be_locale->FormatDateTime(buffer, 256, timeValue, false) == B_OK) { + && be_locale->FormatDateTime(buffer, 256, timeValue, + B_SHORT_DATE_FORMAT, B_SHORT_TIME_FORMAT) == B_OK) { resultWidth = view->StringWidth(buffer); } diff --git a/src/preferences/locale/FormatSettingsView.cpp b/src/preferences/locale/FormatSettingsView.cpp index 586c469c2c..9fff7efc2a 100644 --- a/src/preferences/locale/FormatSettingsView.cpp +++ b/src/preferences/locale/FormatSettingsView.cpp @@ -6,7 +6,6 @@ #include "FormatSettingsView.h" -#include #include #include @@ -14,7 +13,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -44,446 +45,243 @@ using BPrivate::gMutableLocaleRoster; #define B_TRANSLATE_CONTEXT "TimeFormatSettings" -class DateMenuItem: public BMenuItem { -public: - DateMenuItem(const char* label, const char* code, BMenuField* field) - : - BMenuItem(label, _MenuMessage(code, field)) - { - fICUCode = code; - } - - const BString& ICUCode() const - { - return fICUCode; - } - -private: - static BMessage* _MenuMessage(const char* format, BMenuField* field) - { - BMessage* msg = new BMessage(kMenuMessage); - msg->AddPointer("dest", field); - msg->AddString("format", format); - - return msg; - } - -private: - BString fICUCode; -}; - - -void -CreateDateMenu(BMenuField** field, bool longFormat = true) -{ - BMenu* menu = new BMenu(""); - *field = new BMenuField("", menu); - - BPopUpMenu* dayMenu = new BPopUpMenu(B_TRANSLATE("Day")); - // Not all available ICU settings are listed here. It's possible to add some - // other things if you ever need. - menu->AddItem(dayMenu); - dayMenu->AddItem(new DateMenuItem( - B_TRANSLATE("Day in month"), "d", *field)); - dayMenu->AddItem(new DateMenuItem( - B_TRANSLATE("Day in month (2 digits)"), "dd", *field)); - /* - dayMenu->AddItem(new DateMenuItem(B_TRANSLATE("Day in year"), - "D", *field)); - dayMenu->AddItem(new DateMenuItem(B_TRANSLATE("Day in year (2 digits)"), - "DD", *field)); - dayMenu->AddItem(new DateMenuItem(B_TRANSLATE("Day in year (3 digits)"), - "DDD", *field)); - */ - dayMenu->AddItem(new DateMenuItem( - B_TRANSLATE("Day of week"), "e", *field)); - // dayMenu->AddItem(new DateMenuItem("Day of week (short text)", "eee", - // *field)); - // dayMenu->AddItem(new DateMenuItem("Day of week (full text)", "eeee", - // *field)); - dayMenu->AddItem(new DateMenuItem( - B_TRANSLATE("Day of week (short name)"), "E", *field)); - dayMenu->AddItem(new DateMenuItem( - B_TRANSLATE("Day of week (name)"), "EEEE", *field)); - dayMenu->AddItem(new DateMenuItem( - B_TRANSLATE("Day of week in month"), "F", *field)); - // dayMenu->AddItem(new DateMenuItem( - // B_TRANSLATE("julian day"), "g", *field)); - // dayMenu->AddItem(new BMenuItem("c", msg)); - BPopUpMenu* monthMenu = new BPopUpMenu(B_TRANSLATE("Month")); - menu->AddItem(monthMenu); - monthMenu->AddItem(new DateMenuItem( - B_TRANSLATE("Month number"), "M", *field)); - monthMenu->AddItem(new DateMenuItem( - B_TRANSLATE("Month number (2 digits)"), "MM", *field)); - monthMenu->AddItem(new DateMenuItem( - B_TRANSLATE("Month name"), "MMMM", *field)); - // monthMenu->AddItem(new DateMenuItem("L", "L", *field)); - BPopUpMenu* yearMenu = new BPopUpMenu(B_TRANSLATE("Year")); - menu->AddItem(yearMenu); - // And here is some ICU kludge... sorry about that. - if (longFormat) - yearMenu->AddItem(new DateMenuItem( - B_TRANSLATE("Year"), "y", *field)); - else { - yearMenu->AddItem(new DateMenuItem( - B_TRANSLATE("Year (4 digits)"), "yyyy", *field)); - } - yearMenu->AddItem(new DateMenuItem( - B_TRANSLATE("Year (2 digits)"), "yy", *field)); - // yearMenu->AddItem(new DateMenuItem("Y", "Y", *field)); - // yearMenu->AddItem(new DateMenuItem("u", "u", *field)); -} - - -bool -IsSpecialDateChar(char charToTest) -{ - static const char* specials = "dDeEFgMLyYu"; - for (int i = 0; i < 11; i++) - if (charToTest == specials[i]) - return true; - return false; -} - // #pragma mark - -FormatView::FormatView(const BLocale& locale) +FormatSettingsView::FormatSettingsView() : - BView("WindowsSettingsView", B_FRAME_EVENTS), - fLocale(locale) + BView("WindowsSettingsView", B_FRAME_EVENTS) { + fUseLanguageStringsCheckBox = new BCheckBox( + B_TRANSLATE("Use month/day-names from preferred language"), + new BMessage(kStringsLanguageChange)); + + BStringView* fullDateLabel + = new BStringView("", B_TRANSLATE("Full format:")); + fullDateLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); + BStringView* longDateLabel + = new BStringView("", B_TRANSLATE("Long format:")); + longDateLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); + BStringView* mediumDateLabel + = new BStringView("", B_TRANSLATE("Medium format:")); + mediumDateLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); + BStringView* shortDateLabel + = new BStringView("", B_TRANSLATE("Short format:")); + shortDateLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); + + fFullDateExampleView = new BStringView("", ""); + fFullDateExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); fLongDateExampleView = new BStringView("", ""); - - for (int i = 0; i < 4; i++) { - CreateDateMenu(&fLongDateMenu[i]); - fLongDateSeparator[i] = new BTextControl("", "", "", - new BMessage(kSettingsContentsModified)); - fLongDateSeparator[i]->SetModificationMessage( - new BMessage(kSettingsContentsModified)); - } - + fLongDateExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); + fMediumDateExampleView = new BStringView("", ""); + fMediumDateExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); fShortDateExampleView = new BStringView("", ""); + fShortDateExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); - for (int i = 0; i < 3; i++) { - CreateDateMenu(&fDateMenu[i], false); - } - - BPopUpMenu* menu = new BPopUpMenu(B_TRANSLATE("Separator")); - menu->AddItem(new BMenuItem(B_TRANSLATE("None"), - new BMessage(kSettingsContentsModified))); - menu->AddItem(new BMenuItem(B_TRANSLATE("Space"), - new BMessage(kSettingsContentsModified))); - menu->AddItem(new BMenuItem("-", new BMessage(kSettingsContentsModified))); - menu->AddItem(new BMenuItem("/", new BMessage(kSettingsContentsModified))); - menu->AddItem(new BMenuItem("\\", new BMessage(kSettingsContentsModified))); - menu->AddItem(new BMenuItem(".", new BMessage(kSettingsContentsModified))); - - fSeparatorMenuField = new BMenuField(B_TRANSLATE("Separator:"), menu); - - f24HrRadioButton = new BRadioButton("", B_TRANSLATE("24 hour"), + f24HourRadioButton = new BRadioButton("", B_TRANSLATE("24 hour"), new BMessage(kClockFormatChange)); - - f12HrRadioButton = new BRadioButton("", B_TRANSLATE("12 hour"), + f12HourRadioButton = new BRadioButton("", B_TRANSLATE("12 hour"), new BMessage(kClockFormatChange)); - fLocale.GetTimeFormat(fOriginalTimeFormat, false); - fLocale.GetTimeFormat(fOriginalLongTimeFormat, true); - if (fOriginalTimeFormat.FindFirst("a") != B_ERROR) { - f12HrRadioButton->SetValue(B_CONTROL_ON); - fLocaleIs24Hr = false; - } else { - f24HrRadioButton->SetValue(B_CONTROL_ON); - fLocaleIs24Hr = true; - } - float spacing = be_control_look->DefaultItemSpacing(); + BStringView* fullTimeLabel + = new BStringView("", B_TRANSLATE("Full format:")); + fullTimeLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); + BStringView* longTimeLabel + = new BStringView("", B_TRANSLATE("Long format:")); + longTimeLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); + BStringView* mediumTimeLabel + = new BStringView("", B_TRANSLATE("Medium format:")); + mediumTimeLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); + BStringView* shortTimeLabel + = new BStringView("", B_TRANSLATE("Short format:")); + shortTimeLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); + + fFullTimeExampleView = new BStringView("", ""); + fFullTimeExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); fLongTimeExampleView = new BStringView("", ""); + fLongTimeExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); + fMediumTimeExampleView = new BStringView("", ""); + fMediumTimeExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); fShortTimeExampleView = new BStringView("", ""); + fShortTimeExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); - fNumberFormatExampleView = new BStringView("", ""); + BStringView* positiveNumberLabel + = new BStringView("", B_TRANSLATE("Positive:")); + positiveNumberLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); + BStringView* negativeNumberLabel + = new BStringView("", B_TRANSLATE("Negative:")); + negativeNumberLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); - BTextControl* numberThousand = new BTextControl("", - B_TRANSLATE("Thousand separator: "), "", - new BMessage(kSettingsContentsModified)); - BTextControl* numberDecimal = new BTextControl("", - B_TRANSLATE("Decimal separator: "), "", - new BMessage(kSettingsContentsModified)); - // TODO number of decimal digits (spinbox ?) - BCheckBox* numberLeadingZero = new BCheckBox("", B_TRANSLATE("Leading 0"), - new BMessage(kSettingsContentsModified)); - BTextControl* numberList = new BTextControl("", - B_TRANSLATE("List separator: "), "", - new BMessage(kSettingsContentsModified)); - // Unit system (US/Metric) (radio) + fPositiveNumberExampleView = new BStringView("", ""); + fPositiveNumberExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, + B_ALIGN_VERTICAL_UNSET)); + fNegativeNumberExampleView = new BStringView("", ""); + fNegativeNumberExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, + B_ALIGN_VERTICAL_UNSET)); - fCurrencySymbolView = new BTextControl("", - B_TRANSLATE("Currency symbol:"), "", - new BMessage(kSettingsContentsModified)); - menu = new BPopUpMenu(B_TRANSLATE("Negative marker")); - menu->AddItem(new BMenuItem("-", new BMessage(kSettingsContentsModified))); - menu->AddItem(new BMenuItem("()", new BMessage(kSettingsContentsModified))); + BStringView* positiveMonetaryLabel + = new BStringView("", B_TRANSLATE("Positive:")); + positiveMonetaryLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); + BStringView* negativeMonetaryLabel + = new BStringView("", B_TRANSLATE("Negative:")); + negativeMonetaryLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, + B_ALIGN_VERTICAL_UNSET)); - BMenuField* currencyNegative = new BMenuField( - B_TRANSLATE("Negative marker:"), menu); + fPositiveMonetaryExampleView = new BStringView("", ""); + fPositiveMonetaryExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, + B_ALIGN_VERTICAL_UNSET)); + fNegativeMonetaryExampleView = new BStringView("", ""); + fNegativeMonetaryExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, + B_ALIGN_VERTICAL_UNSET)); - BTextControl* currencyDecimal = new BTextControl("", - B_TRANSLATE("Decimal separator: "), "", - new BMessage(kSettingsContentsModified)); - BCheckBox* currencyLeadingZero = new BCheckBox("", - B_TRANSLATE("Leading 0"), new BMessage(kSettingsContentsModified)); - - fCurrencySymbolBefore = new BRadioButton("CurrencySymbolPosition", - B_TRANSLATE("Before"), new BMessage(kSettingsContentsModified)); - - fCurrencySymbolAfter = new BRadioButton("CurrencySymbolPosition", - B_TRANSLATE("After"), new BMessage(kSettingsContentsModified)); - - fMonetaryView = new BStringView("", ""); - - _UpdateExamples(); - _ParseDateFormat(); - _ParseCurrencyFormat(); + Refresh(true); fDateBox = new BBox(B_TRANSLATE("Date")); fTimeBox = new BBox(B_TRANSLATE("Time")); - fNumbersBox = new BBox(B_TRANSLATE("Numbers")); - fCurrencyBox = new BBox(B_TRANSLATE("Currency")); + fNumberBox = new BBox(B_TRANSLATE("Numbers")); + fMonetaryBox = new BBox(B_TRANSLATE("Currency")); fDateBox->SetLabel(B_TRANSLATE("Date")); fTimeBox->SetLabel(B_TRANSLATE("Time")); - fNumbersBox->SetLabel(B_TRANSLATE("Numbers")); - fCurrencyBox->SetLabel(B_TRANSLATE("Currency")); + fNumberBox->SetLabel(B_TRANSLATE("Numbers")); + fMonetaryBox->SetLabel(B_TRANSLATE("Currency")); - fDateBox->AddChild(BLayoutBuilder::Group<>(B_VERTICAL, spacing / 2) + fDateBox->AddChild(BLayoutBuilder::Grid<>(spacing, spacing / 2) .SetInsets(spacing, spacing, spacing, spacing) - .AddGroup(B_HORIZONTAL, spacing) - .Add(new BStringView("", B_TRANSLATE("Long format:"))) - .Add(fLongDateExampleView) - .AddGlue() - .End() - .AddGroup(B_HORIZONTAL, spacing) - .Add(fLongDateMenu[0]) - .Add(fLongDateSeparator[0]) - .End() - .AddGroup(B_HORIZONTAL, spacing) - .Add(fLongDateMenu[1]) - .Add(fLongDateSeparator[1]) - .End() - .AddGroup(B_HORIZONTAL, spacing) - .Add(fLongDateMenu[2]) - .Add(fLongDateSeparator[2]) - .End() - .AddGroup(B_HORIZONTAL, spacing) - .Add(fLongDateMenu[3]) - .Add(fLongDateSeparator[3]) - .End() - .AddGroup(B_HORIZONTAL, spacing) - .Add(new BStringView("", B_TRANSLATE("Short format:"))) - .Add(fShortDateExampleView) - .AddGlue() - .End() - .Add(fDateMenu[0]) - .Add(fDateMenu[1]) - .Add(fDateMenu[2]) + .Add(fullDateLabel, 0, 0) + .Add(fFullDateExampleView, 1, 0) + .Add(BSpaceLayoutItem::CreateGlue(), 2, 0) + .Add(longDateLabel, 0, 1) + .Add(fLongDateExampleView, 1, 1) + .Add(BSpaceLayoutItem::CreateGlue(), 2, 1) + .Add(mediumDateLabel, 0, 2) + .Add(fMediumDateExampleView, 1, 2) + .Add(BSpaceLayoutItem::CreateGlue(), 2, 2) + .Add(shortDateLabel, 0, 3) + .Add(fShortDateExampleView, 1, 3) + .Add(BSpaceLayoutItem::CreateGlue(), 2, 3) .View()); - fTimeBox->AddChild(BLayoutBuilder::Group<>(B_VERTICAL, spacing / 2) + fTimeBox->AddChild(BLayoutBuilder::Grid<>(spacing, spacing / 2) .SetInsets(spacing, spacing, spacing, spacing) - .AddGroup(B_HORIZONTAL, spacing) - .Add(new BStringView("", B_TRANSLATE("Long format:"))) - .Add(fLongTimeExampleView) - .AddGlue() - .End() - .AddGroup(B_HORIZONTAL, spacing) - .Add(new BStringView("", B_TRANSLATE("Short format:"))) - .Add(fShortTimeExampleView) - .AddGlue() - .End() - .AddGroup(B_HORIZONTAL, spacing) - .Add(f24HrRadioButton) - .Add(f12HrRadioButton) + .AddGroup(B_HORIZONTAL, spacing, 0, 0, 2) + .Add(f24HourRadioButton, 0) + .Add(f12HourRadioButton, 0) .AddGlue() .End() + .Add(fullTimeLabel, 0, 1) + .Add(fFullTimeExampleView, 1, 1) + .Add(BSpaceLayoutItem::CreateGlue(), 2, 1) + .Add(longTimeLabel, 0, 2) + .Add(fLongTimeExampleView, 1, 2) + .Add(BSpaceLayoutItem::CreateGlue(), 2, 2) + .Add(mediumTimeLabel, 0, 3) + .Add(fMediumTimeExampleView, 1, 3) + .Add(BSpaceLayoutItem::CreateGlue(), 2, 3) + .Add(shortTimeLabel, 0, 4) + .Add(fShortTimeExampleView, 1, 4) + .Add(BSpaceLayoutItem::CreateGlue(), 2, 4) .View()); - fNumbersBox->AddChild(BLayoutBuilder::Group<>(B_VERTICAL, spacing / 2) + fNumberBox->AddChild(BLayoutBuilder::Grid<>(spacing, spacing / 2) .SetInsets(spacing, spacing, spacing, spacing) - .AddGroup(B_HORIZONTAL, spacing) - .Add(new BStringView("", B_TRANSLATE("Example:"))) - .Add(fNumberFormatExampleView) - .AddGlue() - .End() - .Add(numberThousand) - .Add(numberDecimal) - .Add(numberLeadingZero) - .Add(numberList) - .View()); - - fCurrencyBox->AddChild(BLayoutBuilder::Group<>(B_VERTICAL, spacing / 2) - .SetInsets(spacing, spacing, spacing, spacing) - .Add(fMonetaryView) - .Add(fCurrencySymbolView) - .AddGroup(B_HORIZONTAL, spacing) - .AddGlue() - .Add(fCurrencySymbolBefore) - .Add(fCurrencySymbolAfter) - .End() - .Add(currencyNegative) - .Add(currencyDecimal) - .Add(currencyLeadingZero) + .Add(positiveNumberLabel, 0, 0) + .Add(fPositiveNumberExampleView, 1, 0) + .Add(BSpaceLayoutItem::CreateGlue(), 2, 0) + .Add(negativeNumberLabel, 0, 1) + .Add(fNegativeNumberExampleView, 1, 1) + .Add(BSpaceLayoutItem::CreateGlue(), 2, 1) .View()); + fMonetaryBox->AddChild(BLayoutBuilder::Grid<>(spacing, spacing / 2) + .SetInsets(spacing, spacing, spacing, spacing) + .Add(positiveMonetaryLabel, 0, 0) + .Add(fPositiveMonetaryExampleView, 1, 0) + .Add(BSpaceLayoutItem::CreateGlue(), 2, 0) + .Add(negativeMonetaryLabel, 0, 1) + .Add(fNegativeMonetaryExampleView, 1, 1) + .Add(BSpaceLayoutItem::CreateGlue(), 2, 1) + .View()); - BGroupLayout* rootLayout = new BGroupLayout(B_HORIZONTAL, spacing); + BGroupLayout* rootLayout = new BGroupLayout(B_VERTICAL, spacing); SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); SetLayout(rootLayout); BLayoutBuilder::Group<>(rootLayout) - .AddGroup(B_VERTICAL, spacing) - .Add(fDateBox) - .Add(fTimeBox) + .Add(fUseLanguageStringsCheckBox) + .Add(fDateBox) + .Add(fTimeBox) + .AddGroup(B_HORIZONTAL, spacing) + .Add(fNumberBox) + .Add(fMonetaryBox) .AddGlue() .End() - .AddGroup(B_VERTICAL, spacing) - .Add(fNumbersBox) - .Add(fCurrencyBox) - .AddGlue(); + .AddGlue(); } -FormatView::~FormatView() +FormatSettingsView::~FormatSettingsView() { - gMutableLocaleRoster->SetDefaultLocale(fLocale); } void -FormatView::AttachedToWindow() +FormatSettingsView::AttachedToWindow() { - f24HrRadioButton->SetTarget(this); - f12HrRadioButton->SetTarget(this); - - for (int j = 0; j < 4; j++) { - for (int i = 0; i < fLongDateMenu[j]->Menu()->CountItems(); i++) - fLongDateMenu[j]->Menu()->SubmenuAt(i)->SetTargetForItems(this); - fLongDateSeparator[j]->SetTarget(this); - } - - for (int j = 0; j < 3; j++) { - for (int i = 0; i < fDateMenu[j]->Menu()->CountItems(); i++) - fDateMenu[j]->Menu()->SubmenuAt(i)->SetTargetForItems(this); - } - - fSeparatorMenuField->Menu()->SetTargetForItems(this); + fUseLanguageStringsCheckBox->SetTarget(this); + f24HourRadioButton->SetTarget(this); + f12HourRadioButton->SetTarget(this); } void -FormatView::MessageReceived(BMessage* message) +FormatSettingsView::MessageReceived(BMessage* message) { switch (message->what) { - case kMenuMessage: + case kClockFormatChange: { - // Update one of the dropdown menus - void* pointerFromMessage; - message->FindPointer("dest", &pointerFromMessage); - BMenuField* menuField - = static_cast(pointerFromMessage); - BString format; - message->FindString("format", &format); - - for (int i = 0; i < 4; i++) { - if (fLongDateMenu[i]==menuField) { - fLongDateString[i] = format; - break; - } - } - - for (int i = 0; i < 3; i++) { - if (fDateMenu[i]==menuField) { - fDateString[i] = format; - break; - } - } - - message->FindPointer("source", &pointerFromMessage); - BMenuItem* menuItem = static_cast(pointerFromMessage); - - menuField->MenuItem()->SetLabel(menuItem->Label()); - - _UpdateLongDateFormatString(); - // fall through - } - - case kSettingsContentsModified: - { - int32 separator = 0; - BMenuItem* item = fSeparatorMenuField->Menu()->FindMarked(); - if (item) { - separator = fSeparatorMenuField->Menu()->IndexOf(item); - if (separator >= 0) - // settings.SetTimeFormatSeparator( - // (FormatSeparator)separator); - ; - } - - // Make the notification message and send it to the tracker: - BMessage notificationMessage; - notificationMessage.AddInt32("TimeFormatSeparator", separator); - notificationMessage.AddBool("24HrClock", - f24HrRadioButton->Value() == 1); + BFormattingConventions conventions; + be_locale->GetFormattingConventions(&conventions); + conventions.SetExplicitUse24HourClock( + f24HourRadioButton->Value() ? true : false); + gMutableLocaleRoster->SetDefaultFormattingConventions(conventions); _UpdateExamples(); - - Window()->PostMessage(kSettingsContentsModified); + Window()->PostMessage(kMsgSettingsChanged); break; } - case kClockFormatChange: + case kStringsLanguageChange: { - BMessage newMessage(kMsgSettingsChanged); + BFormattingConventions conventions; + be_locale->GetFormattingConventions(&conventions); + conventions.SetUseStringsFromPreferredLanguage( + fUseLanguageStringsCheckBox->Value() ? true : false); + gMutableLocaleRoster->SetDefaultFormattingConventions(conventions); - BString timeFormat; - timeFormat = fOriginalTimeFormat; - if (f24HrRadioButton->Value() == 1) { - if (!fLocaleIs24Hr) { - timeFormat.ReplaceAll("h", "H"); - timeFormat.ReplaceAll("k", "K"); - timeFormat.RemoveAll(" a"); - timeFormat.RemoveAll("a"); - } - } else { - if (fLocaleIs24Hr && timeFormat.FindFirst("a") == B_ERROR) { - timeFormat.ReplaceAll("K", "k"); - timeFormat.ReplaceAll("H", "h"); - timeFormat.Append(" a"); - } - } - fLocale.SetTimeFormat(timeFormat.String(), false); - newMessage.AddString("shortTimeFormat", timeFormat); - - timeFormat = fOriginalLongTimeFormat; - if (f24HrRadioButton->Value() == 1) { - if (!fLocaleIs24Hr) { - timeFormat.ReplaceAll("h", "H"); - timeFormat.ReplaceAll("k", "K"); - timeFormat.RemoveAll(" a"); - timeFormat.RemoveAll("a"); - } - } else { - if (fLocaleIs24Hr && timeFormat.FindFirst("a") == B_ERROR) { - timeFormat.ReplaceAll("K", "k"); - timeFormat.ReplaceAll("H", "h"); - timeFormat.Append(" a"); - } - } - fLocale.SetTimeFormat(timeFormat.String(), true); - newMessage.AddString("longTimeFormat", timeFormat); _UpdateExamples(); - Window()->PostMessage(kSettingsContentsModified); - be_app_messenger.SendMessage(&newMessage); + + Window()->PostMessage(kMsgSettingsChanged); break; } @@ -494,306 +292,101 @@ FormatView::MessageReceived(BMessage* message) void -FormatView::Revert() +FormatSettingsView::Revert() { - /* - TrackerSettings settings; - - settings.SetTimeFormatSeparator(fSeparator); - settings.SetDateOrderFormat(fFormat); - settings.SetClockTo24Hr(f24HrClock); - */ - - // ShowCurrentSettings(); - _SendNotices(); -} - - -void -FormatView::SetLocale(const BLocale& locale) -{ - fLocale = locale; - - fLocale.GetTimeFormat(fOriginalTimeFormat, false); - fLocale.GetTimeFormat(fOriginalLongTimeFormat, true); - - if (fOriginalTimeFormat.FindFirst("a") != B_ERROR) { - f12HrRadioButton->SetValue(B_CONTROL_ON); - fLocaleIs24Hr = false; - } else { - f24HrRadioButton->SetValue(B_CONTROL_ON); - fLocaleIs24Hr = true; - } - - /* - FormatSeparator separator = settings.TimeFormatSeparator(); - - if (separator >= kNoSeparator && separator < kSeparatorsEnd) - fSeparatorMenuField->Menu()->ItemAt((int32)separator)->SetMarked(true); - */ + gMutableLocaleRoster->SetDefaultFormattingConventions(fInitialConventions); _UpdateExamples(); - _ParseDateFormat(); - _ParseCurrencyFormat(); } void -FormatView::RecordRevertSettings() +FormatSettingsView::Refresh(bool setInitial) { - /* - f24HrClock = settings.ClockIs24Hr(); - fSeparator = settings.TimeFormatSeparator(); - fFormat = settings.DateOrderFormat(); - */ + BFormattingConventions conventions; + be_locale->GetFormattingConventions(&conventions); + if (setInitial) + fInitialConventions = conventions; + + if (!conventions.Use24HourClock()) { + f12HourRadioButton->SetValue(B_CONTROL_ON); + fLocaleIs24Hour = false; + } else { + f24HourRadioButton->SetValue(B_CONTROL_ON); + fLocaleIs24Hour = true; + } + + fUseLanguageStringsCheckBox->SetValue( + conventions.UseStringsFromPreferredLanguage() + ? B_CONTROL_ON : B_CONTROL_OFF); + + _UpdateExamples(); } -// Return true if the Revert button should be enabled (ie some setting was +// Return true if the Revert button should be enabled (i.e. something has been // changed) bool -FormatView::IsRevertable() const +FormatSettingsView::IsReversible() const { - FormatSeparator separator; + BFormattingConventions conventions; + be_locale->GetFormattingConventions(&conventions); - BMenuItem* item = fSeparatorMenuField->Menu()->FindMarked(); - if (item) { - int32 index = fSeparatorMenuField->Menu()->IndexOf(item); - if (index >= 0) - separator = (FormatSeparator)index; - else - return true; - } else - return true; - - // TODO generate ICU string and compare to the initial one - BString dateFormat ; - // fYMDRadioButton->Value() ? kYMDFormat : - //(fDMYRadioButton->Value() ? kDMYFormat : kMDYFormat); - - return f24HrClock != (f24HrRadioButton->Value() > 0) - || separator != fSeparator - || dateFormat != fDateFormat; + return conventions != fInitialConventions; } void -FormatView::_UpdateExamples() +FormatSettingsView::_UpdateExamples() { time_t timeValue = (time_t)time(NULL); - BString timeFormat; + BString result; - fLocale.FormatDate(&timeFormat, timeValue, true); - fLongDateExampleView->SetText(timeFormat); + be_locale->FormatDate(&result, timeValue, B_FULL_DATE_FORMAT); + fFullDateExampleView->SetText(result); - fLocale.FormatDate(&timeFormat, timeValue, false); - fShortDateExampleView->SetText(timeFormat); + be_locale->FormatDate(&result, timeValue, B_LONG_DATE_FORMAT); + fLongDateExampleView->SetText(result); - fLocale.FormatTime(&timeFormat, timeValue, true); - fLongTimeExampleView->SetText(timeFormat); + be_locale->FormatDate(&result, timeValue, B_MEDIUM_DATE_FORMAT); + fMediumDateExampleView->SetText(result); - fLocale.FormatTime(&timeFormat, timeValue, false); - fShortTimeExampleView->SetText(timeFormat); + be_locale->FormatDate(&result, timeValue, B_SHORT_DATE_FORMAT); + fShortDateExampleView->SetText(result); - status_t Error = fLocale.FormatNumber(&timeFormat, 1234.5678); - if (Error == B_OK) - fNumberFormatExampleView->SetText(timeFormat); + be_locale->FormatTime(&result, timeValue, B_FULL_TIME_FORMAT); + fFullTimeExampleView->SetText(result); + + be_locale->FormatTime(&result, timeValue, B_LONG_TIME_FORMAT); + fLongTimeExampleView->SetText(result); + + be_locale->FormatTime(&result, timeValue, B_MEDIUM_TIME_FORMAT); + fMediumTimeExampleView->SetText(result); + + be_locale->FormatTime(&result, timeValue, B_SHORT_TIME_FORMAT); + fShortTimeExampleView->SetText(result); + + status_t status = be_locale->FormatNumber(&result, 1234.5678); + if (status == B_OK) + fPositiveNumberExampleView->SetText(result); else - fNumberFormatExampleView->SetText("ERROR"); -} - - -void -FormatView::_SendNotices() -{ - // Make the notification message and send it to the tracker: - /* - BMessage notificationMessage; - notificationMessage.AddInt32("TimeFormatSeparator", - (int32)settings.TimeFormatSeparator()); - notificationMessage.AddInt32("DateOrderFormat", - (int32)settings.DateOrderFormat()); - notificationMessage.AddBool("24HrClock", settings.ClockIs24Hr()); - tracker->SendNotices(kDateFormatChanged, ¬ificationMessage); - */ -} - - -void -FormatView::_ParseCurrencyFormat() -{ - BString currencySample; - int* fieldPos = NULL; - int fieldCount; - BNumberElement* fieldID = NULL; - if (fLocale.FormatMonetary(¤cySample, fieldPos, fieldID, fieldCount, - -1234.56) != B_OK) { - fMonetaryView->SetText("ERROR"); - return; - } - - fMonetaryView->SetText(currencySample); - - for (int i = 0; i < fieldCount; i++) { - BString currentSymbol; - currentSymbol.AppendChars(currencySample.CharAt(fieldPos[i]&0xFFFF), - (fieldPos[i]>>16) - (fieldPos[i]&0xFFFF)); - switch (fieldID[i]) { - case B_NUMBER_ELEMENT_CURRENCY: - fCurrencySymbolView->SetText(currentSymbol); - if (i > fieldCount / 2) - fCurrencySymbolAfter->SetValue(1); - else - fCurrencySymbolBefore->SetValue(1); - break; - default: - break; - } - } - - free(fieldPos); - free(fieldID); -} - - -//! Get the date format from ICU and set the date fields accordingly -void -FormatView::_ParseDateFormat() -{ - BString dateFormatString; - fLocale.GetDateFormat(dateFormatString, true); - const char* dateFormat = dateFormatString.String(); - - // Travel through the string and parse it - const char* parsePointer = dateFormat; - const char* fieldBegin = dateFormat; - - for (int i = 0; i < 4; i++) - { - fieldBegin = parsePointer; - while (*parsePointer == *(parsePointer + 1)) - parsePointer++; - parsePointer++; - BString str; - str.Append(fieldBegin, parsePointer - fieldBegin); - - fLongDateString[i] = str; - - BMenu* subMenu; - bool isFound = false; - for (int subMenuIndex = 0; subMenuIndex < 3; subMenuIndex++) { - subMenu = fLongDateMenu[i]->Menu()->SubmenuAt(subMenuIndex); - BMenuItem* item; - for (int itemIndex = 0; (item = subMenu->ItemAt(itemIndex)) != NULL; - itemIndex++) { - if (static_cast(item)->ICUCode() == str) { - item->SetMarked(true); - fLongDateMenu[i]->MenuItem()->SetLabel(item->Label()); - isFound = true; - } else - item->SetMarked(false); - } - } - - if (!isFound) - fLongDateMenu[i]->MenuItem()->SetLabel(str.Append("*")); - - fieldBegin = parsePointer; - while ((!IsSpecialDateChar(*parsePointer)) && *parsePointer != '\0') { - if (*parsePointer == '\'') { - parsePointer++; - while (*parsePointer != '\0' && *parsePointer != '\'') - parsePointer++; - if (*parsePointer == '\0') - break; - } - parsePointer++; - } - str.Truncate(0); - str.Append(fieldBegin, parsePointer - fieldBegin); - fLongDateSeparator[i]->SetText(str); - } - - // Short date is a bit more tricky, we want to extract the separator - fLocale.GetDateFormat(dateFormatString, false); - dateFormat = dateFormatString.String(); - - // Travel trough the string and parse it - parsePointer = dateFormat; - fieldBegin = dateFormat; - - for (int i = 0; i < 3; i++) { - fieldBegin = parsePointer; - while (*parsePointer == *(parsePointer + 1)) - parsePointer++; - parsePointer++; - BString str; - str.Append(fieldBegin, parsePointer - fieldBegin); - - fLongDateString[i] = str; - - BMenu* subMenu; - bool isFound = false; - for (int subMenuIndex = 0; subMenuIndex < 3; subMenuIndex++) { - subMenu = fDateMenu[i]->Menu()->SubmenuAt(subMenuIndex); - BMenuItem* item; - for (int itemIndex = 0; (item = subMenu->ItemAt(itemIndex)) != NULL; - itemIndex++) { - if (static_cast(item)->ICUCode() == str) { - item->SetMarked(true); - fDateMenu[i]->MenuItem()->SetLabel(item->Label()); - isFound = true; - } else - item->SetMarked(false); - } - } - - if (!isFound) { - fDateMenu[i]->MenuItem()->SetLabel( - str.Append(B_TRANSLATE(" (unknown format)"))); - } - - fieldBegin = parsePointer; - while ((!IsSpecialDateChar(*parsePointer)) && *parsePointer != '\0') { - if (*parsePointer == '\'') { - parsePointer++; - while (*parsePointer != '\0' && *parsePointer != '\'') - parsePointer++; - if (*parsePointer == '\0') - break; - } - parsePointer++; - } - if (parsePointer - fieldBegin > 0) { - str.Truncate(0); - str.Append(fieldBegin, parsePointer - fieldBegin); - fSeparatorMenuField->MenuItem()->SetLabel(str); - } - } -} - - -void -FormatView::_UpdateLongDateFormatString() -{ - BString newDateFormat; - - for (int i = 0; i < 4; i++) { - newDateFormat.Append(fLongDateString[i]); - newDateFormat.Append(fLongDateSeparator[i]->Text()); - } - - // TODO save this in the settings preflet and make the roster load it back - fLocale.SetDateFormat(newDateFormat.String()); - - newDateFormat.Truncate(0); - - newDateFormat.Append(fDateString[0]); - newDateFormat.Append(fSeparatorMenuField->MenuItem()->Label()); - newDateFormat.Append(fDateString[1]); - newDateFormat.Append(fSeparatorMenuField->MenuItem()->Label()); - newDateFormat.Append(fDateString[2]); - - // TODO save this in the settings preflet and make the roster load it back - fLocale.SetDateFormat(newDateFormat.String(), false); + fPositiveNumberExampleView->SetText("ERROR"); + + status = be_locale->FormatNumber(&result, -1234.5678); + if (status == B_OK) + fNegativeNumberExampleView->SetText(result); + else + fNegativeNumberExampleView->SetText("ERROR"); + + status = be_locale->FormatMonetary(&result, 1234.56); + if (status == B_OK) + fPositiveMonetaryExampleView->SetText(result); + else + fPositiveMonetaryExampleView->SetText("ERROR"); + + status = be_locale->FormatMonetary(&result, -1234.56); + if (status == B_OK) + fNegativeMonetaryExampleView->SetText(result); + else + fNegativeMonetaryExampleView->SetText("ERROR"); } diff --git a/src/preferences/locale/FormatSettingsView.h b/src/preferences/locale/FormatSettingsView.h index c0acb6b50b..c092d5c71c 100644 --- a/src/preferences/locale/FormatSettingsView.h +++ b/src/preferences/locale/FormatSettingsView.h @@ -7,11 +7,12 @@ #include -#include +#include #include #include +class BCheckBox; class BCountry; class BMenuField; class BMessage; @@ -20,79 +21,54 @@ class BStringView; class BTextControl; -enum FormatSeparator { - kNoSeparator, - kSpaceSeparator, - kMinusSeparator, - kSlashSeparator, - kBackslashSeparator, - kDotSeparator, - kSeparatorsEnd -}; - -const uint32 kSettingsContentsModified = 'Scmo'; -const uint32 kClockFormatChange = 'cfmc'; -const uint32 kMenuMessage = 'FRMT'; +static const uint32 kClockFormatChange = 'cfmc'; +static const uint32 kStringsLanguageChange = 'strc'; -class FormatView : public BView { +class FormatSettingsView : public BView { public: - FormatView(const BLocale& locale); - ~FormatView(); + FormatSettingsView(); + ~FormatSettingsView(); virtual void MessageReceived(BMessage* message); virtual void AttachedToWindow(); virtual void Revert(); - virtual void SetLocale(const BLocale& locale); - virtual void RecordRevertSettings(); - virtual bool IsRevertable() const; + virtual void Refresh(bool setInitial = false); + virtual bool IsReversible() const; private: void _UpdateExamples(); - void _SendNotices(); - void _ParseDateFormat(); - void _ParseCurrencyFormat(); - void _UpdateLongDateFormatString(); private: - BRadioButton* f24HrRadioButton; - BRadioButton* f12HrRadioButton; + BCheckBox* fUseLanguageStringsCheckBox; - BMenuField* fLongDateMenu[4]; - BString fLongDateString[4]; - BTextControl* fLongDateSeparator[4]; - BMenuField* fDateMenu[3]; - BString fDateString[3]; - - BMenuField* fSeparatorMenuField; + BRadioButton* f24HourRadioButton; + BRadioButton* f12HourRadioButton; + BStringView* fFullDateExampleView; BStringView* fLongDateExampleView; + BStringView* fMediumDateExampleView; BStringView* fShortDateExampleView; + + BStringView* fFullTimeExampleView; BStringView* fLongTimeExampleView; + BStringView* fMediumTimeExampleView; BStringView* fShortTimeExampleView; - BStringView* fNumberFormatExampleView; - BStringView* fMonetaryView; - BTextControl* fCurrencySymbolView; - BRadioButton* fCurrencySymbolBefore; - BRadioButton* fCurrencySymbolAfter; + BStringView* fPositiveNumberExampleView; + BStringView* fNegativeNumberExampleView; + BStringView* fPositiveMonetaryExampleView; + BStringView* fNegativeMonetaryExampleView; - bool f24HrClock; + bool fLocaleIs24Hour; - FormatSeparator fSeparator; - BString fDateFormat; - - BString fOriginalTimeFormat; - BString fOriginalLongTimeFormat; - bool fLocaleIs24Hr; - - BLocale fLocale; + BFormattingConventions fInitialConventions; BBox* fDateBox; BBox* fTimeBox; - BBox* fNumbersBox; - BBox* fCurrencyBox; + BBox* fNumberBox; + BBox* fMonetaryBox; }; diff --git a/src/preferences/locale/Jamfile b/src/preferences/locale/Jamfile index bb26d5d10f..3cc167bd3e 100644 --- a/src/preferences/locale/Jamfile +++ b/src/preferences/locale/Jamfile @@ -6,7 +6,6 @@ UsePrivateHeaders shared ; local sources = LanguageListView.cpp LocalePreflet.cpp - LocaleSettings.cpp LocaleWindow.cpp FormatSettingsView.cpp ; diff --git a/src/preferences/locale/LanguageListView.cpp b/src/preferences/locale/LanguageListView.cpp index 5eb13b641e..5e51d50fef 100644 --- a/src/preferences/locale/LanguageListView.cpp +++ b/src/preferences/locale/LanguageListView.cpp @@ -18,7 +18,8 @@ #include #include -#include +#include +#include #include @@ -30,17 +31,15 @@ LanguageListItem::LanguageListItem(const char* text, const char* id, - const char* code) + const char* code, const char* countryCode) : BStringItem(text), fID(id), fCode(code) { - // TODO: should probably keep the BCountry as a member of the class - BCountry country(id); - fIcon = new(std::nothrow) BBitmap(BRect(0, 0, 15, 15), B_RGBA32); - if (fIcon != NULL && country.GetIcon(fIcon) != B_OK) { + if (fIcon != NULL && be_locale_roster->GetFlagIconForCountry(fIcon, + countryCode) != B_OK) { delete fIcon; fIcon = NULL; } diff --git a/src/preferences/locale/LanguageListView.h b/src/preferences/locale/LanguageListView.h index 03fc8ee6b9..246242ac03 100644 --- a/src/preferences/locale/LanguageListView.h +++ b/src/preferences/locale/LanguageListView.h @@ -20,7 +20,8 @@ class LanguageListItem : public BStringItem { public: LanguageListItem(const char* text, - const char* id, const char* code); + const char* id, const char* langCode, + const char* countryCode = NULL); LanguageListItem(const LanguageListItem& other); virtual ~LanguageListItem(); diff --git a/src/preferences/locale/LocalePreflet.cpp b/src/preferences/locale/LocalePreflet.cpp index 253a61837c..752ae5ca6d 100644 --- a/src/preferences/locale/LocalePreflet.cpp +++ b/src/preferences/locale/LocalePreflet.cpp @@ -16,7 +16,6 @@ #include #include "LocalePreflet.h" -#include "LocaleSettings.h" #include "LocaleWindow.h" @@ -32,12 +31,9 @@ class LocalePreflet : public BApplication { LocalePreflet(); virtual ~LocalePreflet(); - virtual void MessageReceived(BMessage* message); virtual void AboutRequested(); private: - LocaleSettings fSettings; - LocaleSettings fOriginalSettings; LocaleWindow* fLocaleWindow; }; @@ -51,52 +47,24 @@ LocalePreflet::LocalePreflet() { fLocaleWindow = new LocaleWindow(); - fOriginalSettings.Load(); - fSettings = fOriginalSettings; - - /* - if (fSettings.Message().HasPoint("window_location")) { - BPoint point = fSettings.Message().FindPoint("window_location"); - fLocaleWindow->MoveTo(point); - } - */ - fLocaleWindow->Show(); } LocalePreflet::~LocalePreflet() { - fSettings.Save(); -} - - -void -LocalePreflet::MessageReceived(BMessage* message) -{ - switch (message->what) { - case kMsgSettingsChanged: - fSettings.UpdateFrom(message); - break; - - case kMsgRevert: - fSettings = fOriginalSettings; - break; - - default: - BApplication::MessageReceived(message); - break; - } } void LocalePreflet::AboutRequested() { - const char* authors[3]; - authors[0] = "Axel Dörfler"; - authors[1] = "Adrien Destugues"; - authors[2] = NULL; + const char* authors[] = { + "Axel Dörfler", + "Adrien Destugues", + "Oliver Tappe", + NULL + }; BAboutWindow about(B_TRANSLATE("Locale"), 2005, authors); about.Show(); } diff --git a/src/preferences/locale/LocaleSettings.cpp b/src/preferences/locale/LocaleSettings.cpp deleted file mode 100644 index 376619e9eb..0000000000 --- a/src/preferences/locale/LocaleSettings.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2010, Adrien Destugues . - * Distributed under the terms of the MIT License. - */ - - -#include "LocaleSettings.h" - -#include -#include -#include -#include -#include -#include - - -using BPrivate::gMutableLocaleRoster; - - -static const uint32 kMsgLocaleSettings = 'LCst'; - - -LocaleSettings::LocaleSettings() - : - fMessage(kMsgLocaleSettings) -{ - // Set default preferences - fMessage.AddString("language", "en"); - fMessage.AddString("country", "en_US"); -} - - -status_t -LocaleSettings::Load() -{ - BFile file; - status_t err; - err = _Open(&file, B_READ_ONLY); - if (err != B_OK) - return err; - return fMessage.Unflatten(&file); -} - - -status_t -LocaleSettings::Save() -{ - return B_OK; -} - - -status_t -LocaleSettings::_Open(BFile* file, int32 mode) -{ - BPath path; - if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) - return B_ERROR; - - path.Append("Locale settings"); - - return file->SetTo(path.Path(), mode); -} - - -void -LocaleSettings::UpdateFrom(BMessage* message) -{ - BString messageContent; - - BLocale locale(*be_locale); - - if (message->FindString("language", &messageContent) == B_OK) { - fMessage.RemoveName("language"); - - for (int i = 0;; i++) { - if (message->FindString("language", i, &messageContent) != B_OK) - break; - fMessage.AddString("language", messageContent); - } - gMutableLocaleRoster->SetPreferredLanguages(message); - } - - bool localeChanged = false; - if (message->FindString("country", &messageContent) == B_OK) { - fMessage.ReplaceString("country", messageContent); - fMessage.RemoveName("shortTimeFormat"); - fMessage.RemoveName("longTimeFormat"); - locale.SetCountry(messageContent.String()); - localeChanged = true; - } - - if (message->FindString("shortTimeFormat", &messageContent) == B_OK) { - fMessage.RemoveName("shortTimeFormat"); - fMessage.AddString("shortTimeFormat", messageContent); - locale.SetTimeFormat(messageContent, false); - localeChanged = true; - } - - if (message->FindString("longTimeFormat", &messageContent) == B_OK) { - fMessage.RemoveName("longTimeFormat"); - fMessage.AddString("longTimeFormat", messageContent); - locale.SetTimeFormat(messageContent, true); - localeChanged = true; - } - - if (localeChanged) - gMutableLocaleRoster->SetDefaultLocale(locale); -} diff --git a/src/preferences/locale/LocaleSettings.h b/src/preferences/locale/LocaleSettings.h deleted file mode 100644 index c456a72aab..0000000000 --- a/src/preferences/locale/LocaleSettings.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2010, Adrien Destugues . - * Distributed under the terms of the MIT License. - */ - - -#ifndef __LOCALE_SETTINGS_H__ -#define __LOCALE_SETTINGS_H__ - - -#include -#include - - -class LocaleSettings { - public: - LocaleSettings(); - - status_t Load(); - status_t Save(); - - bool operator==(const LocaleSettings& other); - - void UpdateFrom(BMessage* message); - - /* - void SetPreferredLanguages(); - void GetPreferredLanguages(); - void SetCountry(); - void GetCountry(); - - void SetDateFormat(); - void GetDateFormat(); - void SetTimeFormat(); - void GetTimeFormat(); - void SetNumberFormat(); - void GetNumberFormat(); - void SetMoneyFormat(); - void GetMoneyFormat(); - */ - - private: - status_t _Open(BFile* file, int32 mode); - - BMessage fMessage; -}; - - -#endif - diff --git a/src/preferences/locale/LocaleWindow.cpp b/src/preferences/locale/LocaleWindow.cpp index 5bf5f63718..b365fc76f7 100644 --- a/src/preferences/locale/LocaleWindow.cpp +++ b/src/preferences/locale/LocaleWindow.cpp @@ -14,10 +14,11 @@ #include #include #include +#include #include #include #include -#include +#include #include #include #include @@ -29,7 +30,7 @@ #include "LanguageListView.h" -#include +using BPrivate::gMutableLocaleRoster; #undef B_TRANSLATE_CONTEXT @@ -41,7 +42,7 @@ static const uint32 kMsgLanguageDragged = 'LaDr'; static const uint32 kMsgPreferredLanguageInvoked = 'PLIv'; static const uint32 kMsgPreferredLanguageDragged = 'PLDr'; static const uint32 kMsgPreferredLanguageDeleted = 'PLDl'; -static const uint32 kMsgCountrySelection = 'csel'; +static const uint32 kMsgConventionsSelection = 'csel'; static const uint32 kMsgDefaults = 'dflt'; static const uint32 kMsgPreferredLanguagesChanged = 'lang'; @@ -59,26 +60,15 @@ compare_typed_list_items(const BListItem* _a, const BListItem* _b) } -static int -compare_void_list_items(const void* _a, const void* _b) -{ - static BCollator collator; - - LanguageListItem* a = *(LanguageListItem**)_a; - LanguageListItem* b = *(LanguageListItem**)_b; - - return collator.Compare(a->Text(), b->Text()); -} - - // #pragma mark - - LocaleWindow::LocaleWindow() : BWindow(BRect(0, 0, 0, 0), B_TRANSLATE("Locale"), B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE | B_ASYNCHRONOUS_CONTROLS - | B_AUTO_UPDATE_SIZE_LIMITS) + | B_AUTO_UPDATE_SIZE_LIMITS), + fInitialConventionsItem(NULL), + fDefaultConventionsItem(NULL) { SetLayout(new BGroupLayout(B_HORIZONTAL)); @@ -92,7 +82,7 @@ LocaleWindow::LocaleWindow() fLanguageListView = new LanguageListView("available", B_MULTIPLE_SELECTION_LIST); BScrollView* scrollView = new BScrollView("scroller", fLanguageListView, - B_WILL_DRAW | B_FRAME_EVENTS, false, true); + B_WILL_DRAW | B_FRAME_EVENTS, true, true); fLanguageListView->SetInvocationMessage(new BMessage(kMsgLanguageInvoked)); fLanguageListView->SetDragMessage(new BMessage(kMsgLanguageDragged)); @@ -101,12 +91,12 @@ LocaleWindow::LocaleWindow() fLanguageListView->GetFont(&font); // Fill the language list from the LocaleRoster data - BMessage installedLanguages; - if (be_locale_roster->GetAvailableLanguages(&installedLanguages) == B_OK) { + BMessage availableLanguages; + if (be_locale_roster->GetAvailableLanguages(&availableLanguages) == B_OK) { BString currentID; LanguageListItem* lastAddedCountryItem = NULL; - for (int i = 0; installedLanguages.FindString("language", i, ¤tID) + for (int i = 0; availableLanguages.FindString("language", i, ¤tID) == B_OK; i++) { // Now get the human-readable, native name for each language BString name; @@ -126,7 +116,8 @@ LocaleWindow::LocaleWindow() } LanguageListItem* item = new LanguageListItem(name, - currentID.String(), currentLanguage.Code()); + currentID.String(), currentLanguage.Code(), + currentLanguage.CountryCode()); if (currentLanguage.IsCountrySpecific() && lastAddedCountryItem != NULL && lastAddedCountryItem->Code() == item->Code()) { @@ -155,7 +146,7 @@ LocaleWindow::LocaleWindow() fPreferredListView = new LanguageListView("preferred", B_MULTIPLE_SELECTION_LIST); BScrollView* scrollViewEnabled = new BScrollView("scroller", - fPreferredListView, B_WILL_DRAW | B_FRAME_EVENTS, false, true); + fPreferredListView, B_WILL_DRAW | B_FRAME_EVENTS, true, true); fPreferredListView->SetInvocationMessage( new BMessage(kMsgPreferredLanguageInvoked)); @@ -178,40 +169,60 @@ LocaleWindow::LocaleWindow() BView* countryTab = new BView(B_TRANSLATE("Formatting"), B_WILL_DRAW); countryTab->SetLayout(new BGroupLayout(B_VERTICAL, 0)); - BListView* listView = new BListView("formatting", B_SINGLE_SELECTION_LIST); - scrollView = new BScrollView("scroller", listView, - B_WILL_DRAW | B_FRAME_EVENTS, false, true); - listView->SetSelectionMessage(new BMessage(kMsgCountrySelection)); + fConventionsListView = new LanguageListView("formatting", + B_SINGLE_SELECTION_LIST); + scrollView = new BScrollView("scroller", fConventionsListView, + B_WILL_DRAW | B_FRAME_EVENTS, true, true); + fConventionsListView->SetSelectionMessage( + new BMessage(kMsgConventionsSelection)); // get all available formatting conventions (by language) - BString formattingConventionCode; - LanguageListItem* currentItem = NULL; - BCountry defaultFormattingConvention; - be_locale->GetCountry(&defaultFormattingConvention); + BFormattingConventions defaultConventions; + be_locale->GetFormattingConventions(&defaultConventions); + BString conventionID; + fInitialConventionsItem = NULL; + LanguageListItem* lastAddedConventionsItem = NULL; for (int i = 0; - installedLanguages.FindString("language", i, &formattingConventionCode) - == B_OK; i++) { - BCountry formattingConvention(formattingConventionCode); - BString formattingConventionName; - formattingConvention.GetName(formattingConventionName); + availableLanguages.FindString("language", i, &conventionID) == B_OK; + i++) { + BFormattingConventions convention(conventionID); + BString conventionName; + convention.GetName(conventionName); - LanguageListItem* item = new LanguageListItem(formattingConventionName, - formattingConventionCode, NULL); - listView->AddItem(item); - if (!strcmp(formattingConventionCode, - defaultFormattingConvention.Code())) - currentItem = item; + LanguageListItem* item = new LanguageListItem(conventionName, + conventionID, convention.LanguageCode(), convention.CountryCode()); + if (!strcmp(conventionID, "en_US")) + fDefaultConventionsItem = item; + if (conventionID.FindFirst('_') >= 0 + && lastAddedConventionsItem != NULL + && lastAddedConventionsItem->Code() == item->Code()) { + if (!strcmp(conventionID, defaultConventions.ID())) { + lastAddedConventionsItem->SetExpanded(true); + fInitialConventionsItem = item; + } + fConventionsListView->AddUnder(item, lastAddedConventionsItem); + } else { + // This conventions-item isn't country-specific, add it at top-level + fConventionsListView->AddItem(item); + if (conventionID.FindFirst('_') < 0) { + item->SetExpanded(false); + lastAddedConventionsItem = item; + } + if (!strcmp(conventionID, defaultConventions.ID())) + fInitialConventionsItem = item; + } } - listView->SortItems(compare_void_list_items); - if (currentItem != NULL) - listView->Select(listView->IndexOf(currentItem)); + fConventionsListView->FullListSortItems(compare_typed_list_items); + if (fInitialConventionsItem != NULL) { + fConventionsListView->Select(fConventionsListView->IndexOf( + fInitialConventionsItem)); + } - // TODO: find a real solution intead of this hack - listView->SetExplicitMinSize( - BSize(25 * be_plain_font->Size(), B_SIZE_UNSET)); + fConventionsListView->SetExplicitMinSize(BSize(20 * be_plain_font->Size(), + B_SIZE_UNSET)); - fFormatView = new FormatView(*be_locale); + fFormatView = new FormatSettingsView(); countryTab->AddChild(BLayoutBuilder::Group<>(B_HORIZONTAL, spacing) .AddGroup(B_VERTICAL, 3) @@ -220,16 +231,14 @@ LocaleWindow::LocaleWindow() .Add(fFormatView) .SetInsets(spacing, spacing, spacing, spacing)); - listView->ScrollToSelection(); - tabView->AddTab(languageTab); tabView->AddTab(countryTab); - BButton* button = new BButton(B_TRANSLATE("Defaults"), - new BMessage(kMsgDefaults)); + BButton* button + = new BButton(B_TRANSLATE("Defaults"), new BMessage(kMsgDefaults)); - fRevertButton = new BButton(B_TRANSLATE("Revert"), - new BMessage(kMsgRevert)); + fRevertButton + = new BButton(B_TRANSLATE("Revert"), new BMessage(kMsgRevert)); fRevertButton->SetEnabled(false); BLayoutBuilder::Group<>(this, B_VERTICAL, spacing) @@ -242,8 +251,8 @@ LocaleWindow::LocaleWindow() .SetInsets(spacing, spacing, spacing, spacing) .End(); - _UpdatePreferredFromLocaleRoster(); - SettingsReverted(); + _Refresh(true); + _SettingsReverted(); CenterOnScreen(); } @@ -262,8 +271,25 @@ LocaleWindow::MessageReceived(BMessage* message) break; case kMsgRevert: - be_app_messenger.SendMessage(message); - _UpdatePreferredFromLocaleRoster(); + { + _Revert(); + fFormatView->Revert(); + fConventionsListView->DeselectAll(); + if (fInitialConventionsItem != NULL) { + BListItem* superitem + = fConventionsListView->Superitem(fInitialConventionsItem); + if (superitem != NULL) + superitem->SetExpanded(true); + fConventionsListView->Select(fConventionsListView->IndexOf( + fInitialConventionsItem)); + fConventionsListView->ScrollToSelection(); + } + _SettingsReverted(); + break; + } + + case kMsgSettingsChanged: + _SettingsChanged(); break; case kMsgLanguageDragged: @@ -342,7 +368,7 @@ LocaleWindow::MessageReceived(BMessage* message) break; } - case kMsgCountrySelection: + case kMsgConventionsSelection: { // Country selection changed. // Get the new selected country from the ListView and send it to the @@ -351,18 +377,15 @@ LocaleWindow::MessageReceived(BMessage* message) if (message->FindPointer("source", &listView) != B_OK) break; - BListView* countryList = static_cast(listView); + BListView* conventionsList = static_cast(listView); LanguageListItem* item = static_cast - (countryList->ItemAt(countryList->CurrentSelection())); - BMessage newMessage(kMsgSettingsChanged); - newMessage.AddString("country", item->ID()); - be_app_messenger.SendMessage(&newMessage); - SettingsChanged(); + (conventionsList->ItemAt(conventionsList->CurrentSelection())); + BFormattingConventions conventions(item->ID()); + gMutableLocaleRoster->SetDefaultFormattingConventions(conventions); - BCountry country(item->ID()); - BLocale locale(NULL, &country); - fFormatView->SetLocale(locale); + _SettingsChanged(); + fFormatView->Refresh(); break; } @@ -381,35 +404,57 @@ LocaleWindow::QuitRequested() void -LocaleWindow::SettingsChanged() +LocaleWindow::Show() { - fRevertButton->SetEnabled(true); + BWindow::Show(); + + Lock(); + if (IsLocked()) { + fConventionsListView->ScrollToSelection(); + Unlock(); + } } void -LocaleWindow::SettingsReverted() +LocaleWindow::_SettingsChanged() +{ + bool haveAnythingToRevert = fFormatView->IsReversible() || _IsReversible(); + fRevertButton->SetEnabled(haveAnythingToRevert); +} + + +void +LocaleWindow::_SettingsReverted() { fRevertButton->SetEnabled(false); } +bool +LocaleWindow::_IsReversible() const +{ + BMessage preferredLanguages; + be_locale_roster->GetPreferredLanguages(&preferredLanguages); + + return !preferredLanguages.HasSameData(fInitialPreferredLanguages); +} + + void LocaleWindow::_PreferredLanguagesChanged() { - BMessage update(kMsgSettingsChanged); + BMessage preferredLanguages; int index = 0; while (index < fPreferredListView->FullListCountItems()) { - // only include subitems: we can guess the superitem - // from them anyway + // only include subitems: we can guess the superitem from them anyway LanguageListItem* item = static_cast( fPreferredListView->FullListItemAt(index)); if (item != NULL) - update.AddString("language", item->ID()); - + preferredLanguages.AddString("language", item->ID()); index++; } - be_app_messenger.SendMessage(&update); + gMutableLocaleRoster->SetPreferredLanguages(&preferredLanguages); _EnableDisableLanguages(); } @@ -437,15 +482,31 @@ LocaleWindow::_EnableDisableLanguages() } } - SettingsChanged(); - EnableUpdates(); } -//! Get the preferred languages from the settings. void -LocaleWindow::_UpdatePreferredFromLocaleRoster() +LocaleWindow::_Refresh(bool setInitial) +{ + BMessage preferredLanguages; + be_locale_roster->GetPreferredLanguages(&preferredLanguages); + if (setInitial) + fInitialPreferredLanguages = preferredLanguages; + + _SetPreferredLanguages(preferredLanguages); +} + + +void +LocaleWindow::_Revert() +{ + _SetPreferredLanguages(fInitialPreferredLanguages); +} + + +void +LocaleWindow::_SetPreferredLanguages(const BMessage& languages) { DisableUpdates(); @@ -455,17 +516,12 @@ LocaleWindow::_UpdatePreferredFromLocaleRoster() } fPreferredListView->MakeEmpty(); - // Add new ones from the locale roster - BMessage preferredLanguages; - be_locale_roster->GetPreferredLanguages(&preferredLanguages); - BString languageID; - for (int32 index = 0; preferredLanguages.FindString("language", index, - &languageID) == B_OK; index++) { + for (int32 index = 0; + languages.FindString("language", index, &languageID) == B_OK; index++) { int32 listIndex; - LanguageListItem* item - = fLanguageListView->ItemForLanguageID(languageID.String(), - &listIndex); + LanguageListItem* item = fLanguageListView->ItemForLanguageID( + languageID.String(), &listIndex); if (item != NULL) { // We found the item we were looking for, now copy it to // the other list @@ -488,22 +544,15 @@ LocaleWindow::_InsertPreferredLanguage(LanguageListItem* item, int32 atIndex) if (atIndex == -1) atIndex = fPreferredListView->CountItems(); - BLanguage* language = NULL; - be_locale_roster->GetLanguage(item->Code(), &language); - - LanguageListItem* baseItem = NULL; - if (language != NULL) { - baseItem = fPreferredListView->ItemForLanguageCode(language->Code(), - &atIndex); - delete language; - } + BLanguage language(item->Code()); + LanguageListItem* baseItem + = fPreferredListView->ItemForLanguageCode(language.Code(), &atIndex); DisableUpdates(); fPreferredListView->AddItem(new LanguageListItem(*item), atIndex); - // Replace other languages with the same base - + // Replace other languages sharing the same base if (baseItem != NULL) { fPreferredListView->RemoveItem(baseItem); delete baseItem; @@ -518,11 +567,23 @@ LocaleWindow::_InsertPreferredLanguage(LanguageListItem* item, int32 atIndex) void LocaleWindow::_Defaults() { - BMessage update(kMsgSettingsChanged); - update.AddString("language", "en"); + BMessage preferredLanguages; + preferredLanguages.AddString("language", "en"); + gMutableLocaleRoster->SetPreferredLanguages(&preferredLanguages); + _SetPreferredLanguages(preferredLanguages); - be_app_messenger.SendMessage(&update); - SettingsChanged(); - _UpdatePreferredFromLocaleRoster(); + BFormattingConventions conventions("en_US"); + gMutableLocaleRoster->SetDefaultFormattingConventions(conventions); + + fConventionsListView->DeselectAll(); + if (fDefaultConventionsItem != NULL) { + BListItem* superitem + = fConventionsListView->Superitem(fDefaultConventionsItem); + if (superitem != NULL && !superitem->IsExpanded()) + superitem->SetExpanded(true); + fConventionsListView->Select(fConventionsListView->IndexOf( + fDefaultConventionsItem)); + fConventionsListView->ScrollToSelection(); + } } diff --git a/src/preferences/locale/LocaleWindow.h b/src/preferences/locale/LocaleWindow.h index cd8861bb9f..d43281c5a3 100644 --- a/src/preferences/locale/LocaleWindow.h +++ b/src/preferences/locale/LocaleWindow.h @@ -6,6 +6,7 @@ #define LOCALE_WINDOW_H +#include #include @@ -14,7 +15,7 @@ static const uint32 kMsgRevert = 'revt'; class BButton; class BListView; -class FormatView; +class FormatSettingsView; class LanguageListItem; class LanguageListView; @@ -26,14 +27,21 @@ public: virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); - - void SettingsChanged(); - void SettingsReverted(); + virtual void Show(); private: + void _SettingsChanged(); + void _SettingsReverted(); + + bool _IsReversible() const; + + void _Refresh(bool setInitial = false); + void _Revert(); + + void _SetPreferredLanguages( + const BMessage& languages); void _PreferredLanguagesChanged(); void _EnableDisableLanguages(); - void _UpdatePreferredFromLocaleRoster(); void _InsertPreferredLanguage(LanguageListItem* item, int32 atIndex = -1); void _Defaults(); @@ -41,7 +49,11 @@ private: BButton* fRevertButton; LanguageListView* fLanguageListView; LanguageListView* fPreferredListView; - FormatView* fFormatView; + LanguageListView* fConventionsListView; + FormatSettingsView* fFormatView; + LanguageListItem* fInitialConventionsItem; + LanguageListItem* fDefaultConventionsItem; + BMessage fInitialPreferredLanguages; }; diff --git a/src/preferences/time/DateTimeEdit.cpp b/src/preferences/time/DateTimeEdit.cpp index 7e46a651fd..f6fe301a3e 100644 --- a/src/preferences/time/DateTimeEdit.cpp +++ b/src/preferences/time/DateTimeEdit.cpp @@ -277,8 +277,9 @@ void TTimeEdit::_UpdateFields() { time_t time = fTime.Time_t(); - be_locale->FormatTime(&fText, fFieldPositions, fFieldPosCount, time, true); - be_locale->GetTimeFields(fFields, fFieldCount, true); + be_locale->FormatTime(&fText, fFieldPositions, fFieldPosCount, time, + B_MEDIUM_TIME_FORMAT); + be_locale->GetTimeFields(fFields, fFieldCount, B_MEDIUM_TIME_FORMAT); } @@ -675,8 +676,9 @@ void TDateEdit::_UpdateFields() { time_t time = BDateTime(fDate, BTime()).Time_t(); - be_locale->FormatDate(&fText, fFieldPositions, fFieldPosCount, time, false); - be_locale->GetDateFields(fFields, fFieldCount, false); + be_locale->FormatDate(&fText, fFieldPositions, fFieldPosCount, time, + B_SHORT_DATE_FORMAT); + be_locale->GetDateFields(fFields, fFieldCount, B_SHORT_DATE_FORMAT); } diff --git a/src/preferences/time/ZoneView.cpp b/src/preferences/time/ZoneView.cpp index 9ddda907eb..3ba73abc7d 100644 --- a/src/preferences/time/ZoneView.cpp +++ b/src/preferences/time/ZoneView.cpp @@ -184,10 +184,12 @@ TimeZoneView::GetToolTipAt(BPoint point, BToolTip** _tip) BString nowInTimeZone; time_t now = time(NULL); - be_locale->FormatTime(&nowInTimeZone, now, false, &item->TimeZone()); + be_locale->FormatTime(&nowInTimeZone, now, B_SHORT_TIME_FORMAT, + &item->TimeZone()); BString dateInTimeZone; - be_locale->FormatDate(&dateInTimeZone, now, false, &item->TimeZone()); + be_locale->FormatDate(&dateInTimeZone, now, B_SHORT_DATE_FORMAT, + &item->TimeZone()); BString toolTip = item->Text(); toolTip << '\n' << item->TimeZone().ShortName() << " / " @@ -300,7 +302,7 @@ TimeZoneView::_BuildZoneMenu() BString countryCode; for (int c = 0; countryList.FindString("country", c, &countryCode) == B_OK; c++) { - BCountry country("", countryCode); + BCountry country(countryCode); BString countryName; country.GetName(countryName); @@ -532,7 +534,7 @@ TimeZoneView::_FormatTime(const BTimeZone& timeZone) : 0; now -= timeZone.OffsetFromGMT() - currentOffset; } - be_locale->FormatTime(&result, now, false, &timeZone); + be_locale->FormatTime(&result, now, B_SHORT_TIME_FORMAT, &timeZone); return result; }