diff --git a/headers/os/locale/TimeZone.h b/headers/os/locale/TimeZone.h index 9c5bc43980..4b1cf124b0 100644 --- a/headers/os/locale/TimeZone.h +++ b/headers/os/locale/TimeZone.h @@ -9,12 +9,20 @@ #include +namespace icu_44 { + class TimeZone; +} + + class BTimeZone { public: - BTimeZone(const char* zoneCode = NULL); + BTimeZone(const char* zoneID = NULL); + BTimeZone(const BTimeZone& other); ~BTimeZone(); - const BString& Code() const; + BTimeZone& operator=(const BTimeZone& source); + + const BString& ID() const; const BString& Name() const; const BString& DaylightSavingName() const; const BString& ShortName() const; @@ -24,20 +32,22 @@ public: status_t InitCheck() const; - status_t SetTo(const char* zoneCode); + status_t SetTo(const char* zoneID); static const char* kNameOfGmtZone; private: - BString fCode; - BString fName; - BString fDaylightSavingName; - BString fShortName; - BString fShortDaylightSavingName; - int fOffsetFromGMT; - bool fSupportsDaylightSaving; - + icu_44::TimeZone* fIcuTimeZone; status_t fInitStatus; + + mutable uint32 fInitializedFields; + mutable BString fZoneID; + mutable BString fName; + mutable BString fDaylightSavingName; + mutable BString fShortName; + mutable BString fShortDaylightSavingName; + mutable int fOffsetFromGMT; + mutable bool fSupportsDaylightSaving; }; diff --git a/src/kits/locale/Locale.cpp b/src/kits/locale/Locale.cpp index 6158209a3e..b5a5bfe3f1 100644 --- a/src/kits/locale/Locale.cpp +++ b/src/kits/locale/Locale.cpp @@ -405,7 +405,7 @@ BLocale::FormatTime(BString* string, time_t time, bool longFormat, if (timeZone != NULL) { ObjectDeleter icuTimeZone - = TimeZone::createTimeZone(timeZone->Code().String()); + = TimeZone::createTimeZone(timeZone->ID().String()); if (icuTimeZone.Get() == NULL) return B_NO_MEMORY; timeFormatter->setTimeZone(*icuTimeZone.Get()); diff --git a/src/kits/locale/MutableLocaleRoster.cpp b/src/kits/locale/MutableLocaleRoster.cpp index db45942117..de53afc3a2 100644 --- a/src/kits/locale/MutableLocaleRoster.cpp +++ b/src/kits/locale/MutableLocaleRoster.cpp @@ -434,8 +434,6 @@ RosterData::_LoadLocaleSettings() BMessage settings; if (status == B_OK) status = settings.Unflatten(&file); - if (status == B_OK) - status = _SetPreferredLanguages(&settings); if (status == B_OK) { BString codeName; @@ -454,6 +452,9 @@ RosterData::_LoadLocaleSettings() return B_OK; } + if (status == B_OK) + status = _SetPreferredLanguages(&settings); + // Something went wrong (no settings file or invalid BMessage), so we // set everything to default values @@ -481,9 +482,9 @@ RosterData::_LoadTimeSettings() if (status == B_OK) status = settings.Unflatten(&file); if (status == B_OK) { - BString timeZoneCode; - if (settings.FindString("timezone", &timeZoneCode) == B_OK) - _SetDefaultTimeZone(BTimeZone(timeZoneCode.String())); + BString timeZoneID; + if (settings.FindString("timezone", &timeZoneID) == B_OK) + _SetDefaultTimeZone(BTimeZone(timeZoneID.String())); else _SetDefaultTimeZone(BTimeZone(BTimeZone::kNameOfGmtZone)); @@ -564,6 +565,15 @@ RosterData::_SetDefaultLocale(const BLocale& newLocale) { fDefaultLocale = newLocale; + UErrorCode icuError = U_ZERO_ERROR; + Locale icuLocale = Locale::createCanonical(newLocale.Code()); + if (icuLocale.isBogus()) + return B_ERROR; + + Locale::setDefault(icuLocale, icuError); + if (!U_SUCCESS(icuError)) + return B_ERROR; + return B_OK; } @@ -573,7 +583,7 @@ RosterData::_SetDefaultTimeZone(const BTimeZone& newZone) { fDefaultTimeZone = newZone; - TimeZone* timeZone = TimeZone::createTimeZone(newZone.Code().String()); + TimeZone* timeZone = TimeZone::createTimeZone(newZone.ID().String()); if (timeZone == NULL) return B_ERROR; TimeZone::adoptDefault(timeZone); @@ -588,15 +598,6 @@ RosterData::_SetPreferredLanguages(const BMessage* languages) BString langName; if (languages != NULL && languages->FindString("language", &langName) == B_OK) { - UErrorCode icuError = U_ZERO_ERROR; - Locale icuLocale = Locale::createCanonical(langName.String()); - if (icuLocale.isBogus()) - return B_ERROR; - - Locale::setDefault(icuLocale, icuError); - if (!U_SUCCESS(icuError)) - return B_ERROR; - fDefaultLocale.SetCollator(BCollator(langName.String())); fDefaultLanguage.SetTo(langName.String()); @@ -637,7 +638,7 @@ RosterData::_AddDefaultCountryToMessage(BMessage* message) const status_t RosterData::_AddDefaultTimeZoneToMessage(BMessage* message) const { - status_t status = message->AddString("timezone", fDefaultTimeZone.Code()); + status_t status = message->AddString("timezone", fDefaultTimeZone.ID()); // add the offset, too, since that is used by clockconfig when setting // up timezone state during boot diff --git a/src/kits/locale/TimeZone.cpp b/src/kits/locale/TimeZone.cpp index be54a148ac..16a9227e43 100644 --- a/src/kits/locale/TimeZone.cpp +++ b/src/kits/locale/TimeZone.cpp @@ -10,6 +10,8 @@ #include +#include + #include #include @@ -17,20 +19,93 @@ const char* BTimeZone::kNameOfGmtZone = "GMT"; -BTimeZone::BTimeZone(const char* zoneCode) +static const BString skEmptyString; + + +static const uint32 skNameField = 1U << 0; +static const uint32 skDaylightSavingNameField = 1U << 1; +static const uint32 skShortNameField = 1U << 2; +static const uint32 skShortDaylightSavingNameField = 1U << 3; +static const uint32 skLongGenericNameField = 1U << 4; +static const uint32 skGenericLocationNameField = 1U << 5; +static const uint32 skShortCommonlyUsedNameField = 1U << 6; +static const uint32 skSupportsDaylightSavingField = 1U << 7; +static const uint32 skOffsetFromGMTField = 1U << 8; + + +BTimeZone::BTimeZone(const char* zoneID) + : + fIcuTimeZone(NULL), + fInitStatus(B_NO_INIT), + fInitializedFields(0) +{ + SetTo(zoneID); +} + + +BTimeZone::BTimeZone(const BTimeZone& other) + : + fIcuTimeZone(other.fIcuTimeZone == NULL + ? NULL + : other.fIcuTimeZone->clone()), + fInitStatus(other.fInitStatus), + fInitializedFields(other.fInitializedFields), + fZoneID(other.fZoneID), + fName(other.fName), + fDaylightSavingName(other.fDaylightSavingName), + fShortName(other.fShortName), + fShortDaylightSavingName(other.fShortDaylightSavingName), + fOffsetFromGMT(other.fOffsetFromGMT), + fSupportsDaylightSaving(other.fSupportsDaylightSaving) { - SetTo(zoneCode); } BTimeZone::~BTimeZone() { + delete fIcuTimeZone; +} + + +BTimeZone& BTimeZone::operator=(const BTimeZone& source) +{ + delete fIcuTimeZone; + fIcuTimeZone = source.fIcuTimeZone == NULL + ? NULL + : source.fIcuTimeZone->clone(); + fInitStatus = source.fInitStatus; + fInitializedFields = source.fInitializedFields; + fZoneID = source.fZoneID; + fName = source.fName; + fDaylightSavingName = source.fDaylightSavingName; + fShortName = source.fShortName; + fShortDaylightSavingName = source.fShortDaylightSavingName; + fOffsetFromGMT = source.fOffsetFromGMT; + fSupportsDaylightSaving = source.fSupportsDaylightSaving; + + return *this; +} + + +const BString& +BTimeZone::ID() const +{ + return fZoneID; } const BString& BTimeZone::Name() const { + if ((fInitializedFields & skNameField) == 0) { + UnicodeString unicodeString; + fIcuTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION, + unicodeString); + BStringByteSink sink(&fName); + unicodeString.toUTF8(sink); + fInitializedFields |= skNameField; + } + return fName; } @@ -38,6 +113,15 @@ BTimeZone::Name() const const BString& BTimeZone::DaylightSavingName() const { + if ((fInitializedFields & skDaylightSavingNameField) == 0) { + UnicodeString unicodeString; + fIcuTimeZone->getDisplayName(true, TimeZone::GENERIC_LOCATION, + unicodeString); + BStringByteSink sink(&fDaylightSavingName); + unicodeString.toUTF8(sink); + fInitializedFields |= skDaylightSavingNameField; + } + return fDaylightSavingName; } @@ -45,6 +129,15 @@ BTimeZone::DaylightSavingName() const const BString& BTimeZone::ShortName() const { + if ((fInitializedFields & skShortNameField) == 0) { + UnicodeString unicodeString; + fIcuTimeZone->getDisplayName(false, TimeZone::SHORT_COMMONLY_USED, + unicodeString); + BStringByteSink sink(&fShortName); + unicodeString.toUTF8(sink); + fInitializedFields |= skShortNameField; + } + return fShortName; } @@ -52,20 +145,38 @@ BTimeZone::ShortName() const const BString& BTimeZone::ShortDaylightSavingName() const { + if ((fInitializedFields & skShortDaylightSavingNameField) == 0) { + UnicodeString unicodeString; + fIcuTimeZone->getDisplayName(true, TimeZone::SHORT_COMMONLY_USED, + unicodeString); + BStringByteSink sink(&fShortDaylightSavingName); + unicodeString.toUTF8(sink); + fInitializedFields |= skShortDaylightSavingNameField; + } + return fShortDaylightSavingName; } -const BString& -BTimeZone::Code() const -{ - return fCode; -} - - int BTimeZone::OffsetFromGMT() const { + if ((fInitializedFields & skOffsetFromGMTField) == 0) { + int32_t rawOffset; + int32_t dstOffset; + UDate nowMillis = 1000 * (double)time(NULL); + + UErrorCode error = U_ZERO_ERROR; + fIcuTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, error); + if (!U_SUCCESS(error)) + fOffsetFromGMT = 0; + else { + fOffsetFromGMT = (rawOffset + dstOffset) / 1000; + // we want seconds, not ms (which ICU gives us) + } + fInitializedFields |= skOffsetFromGMTField; + } + return fOffsetFromGMT; } @@ -73,6 +184,11 @@ BTimeZone::OffsetFromGMT() const bool BTimeZone::SupportsDaylightSaving() const { + if ((fInitializedFields & skSupportsDaylightSavingField) == 0) { + fSupportsDaylightSaving = fIcuTimeZone->useDaylightTime(); + fInitializedFields |= skSupportsDaylightSavingField; + } + return fSupportsDaylightSaving; } @@ -85,57 +201,27 @@ BTimeZone::InitCheck() const status_t -BTimeZone::SetTo(const char* zoneCode) +BTimeZone::SetTo(const char* zoneID) { - TimeZone* icuTimeZone; - if (zoneCode == NULL || zoneCode[0] == '\0') - icuTimeZone = TimeZone::createDefault(); + delete fIcuTimeZone; + fInitializedFields = 0; + + if (zoneID == NULL || zoneID[0] == '\0') + fIcuTimeZone = TimeZone::createDefault(); else - icuTimeZone = TimeZone::createTimeZone(zoneCode); + fIcuTimeZone = TimeZone::createTimeZone(zoneID); - UnicodeString unicodeString; - icuTimeZone->getID(unicodeString); - BStringByteSink converter(&fCode); - unicodeString.toUTF8(converter); - - unicodeString.remove(); - icuTimeZone->getDisplayName(false, TimeZone::LONG, unicodeString); - converter.SetTo(&fName); - unicodeString.toUTF8(converter); - - unicodeString.remove(); - icuTimeZone->getDisplayName(true, TimeZone::LONG, unicodeString); - converter.SetTo(&fDaylightSavingName); - unicodeString.toUTF8(converter); - - unicodeString.remove(); - icuTimeZone->getDisplayName(false, TimeZone::SHORT, unicodeString); - converter.SetTo(&fShortName); - unicodeString.toUTF8(converter); - - unicodeString.remove(); - icuTimeZone->getDisplayName(true, TimeZone::SHORT, unicodeString); - converter.SetTo(&fShortDaylightSavingName); - unicodeString.toUTF8(converter); - - fSupportsDaylightSaving = icuTimeZone->useDaylightTime(); - - int32_t rawOffset; - int32_t dstOffset; - UDate nowMillis = 1000 * (double)time(NULL); - - UErrorCode error = U_ZERO_ERROR; - icuTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, error); - if (!U_SUCCESS(error)) { - fOffsetFromGMT = 0; - fInitStatus = B_ERROR; - } else { - fOffsetFromGMT = (rawOffset + dstOffset) / 1000; - // we want seconds, not ms (which ICU gives us) - fInitStatus = B_OK; + if (fIcuTimeZone == NULL) { + fInitStatus = B_NAME_NOT_FOUND; + return fInitStatus; } - delete icuTimeZone; + UnicodeString unicodeString; + fIcuTimeZone->getID(unicodeString); + BStringByteSink sink(&fZoneID); + unicodeString.toUTF8(sink); + + fInitStatus = B_OK; return fInitStatus; } diff --git a/src/preferences/time/Jamfile b/src/preferences/time/Jamfile index a87a1a39cf..eeea76fb1c 100644 --- a/src/preferences/time/Jamfile +++ b/src/preferences/time/Jamfile @@ -2,7 +2,7 @@ SubDir HAIKU_TOP src preferences time ; SetSubDirSupportedPlatformsBeOSCompatible ; -UsePrivateHeaders locale shared [ FDirName libroot time ] ; +UsePrivateHeaders interface locale shared [ FDirName libroot time ] ; UsePrivateSystemHeaders ; local sources = @@ -28,7 +28,7 @@ Includes [ FGristFiles $(sources) ] : $(HAIKU_ICU_HEADERS_DEPENDENCY) ; Preference Time : $(sources) - : be libshared.a $(TARGET_LIBSUPC++) $(HAIKU_LOCALE_LIBS) + : be libshared.a $(TARGET_LIBSTDC++) $(HAIKU_LOCALE_LIBS) : Time.rdef ; diff --git a/src/preferences/time/TimeZoneListItem.cpp b/src/preferences/time/TimeZoneListItem.cpp index f76721c50f..dad5a587fd 100644 --- a/src/preferences/time/TimeZoneListItem.cpp +++ b/src/preferences/time/TimeZoneListItem.cpp @@ -109,12 +109,12 @@ TimeZoneListItem::TimeZone() const const BString& -TimeZoneListItem::Code() const +TimeZoneListItem::ID() const { if (fTimeZone == NULL) return skDefaultString; - return fTimeZone->Code(); + return fTimeZone->ID(); } diff --git a/src/preferences/time/TimeZoneListItem.h b/src/preferences/time/TimeZoneListItem.h index d387aebe78..f36fd4379c 100644 --- a/src/preferences/time/TimeZoneListItem.h +++ b/src/preferences/time/TimeZoneListItem.h @@ -29,7 +29,7 @@ public: bool HasTimeZone() const; const BTimeZone& TimeZone() const; - const BString& Code() const; + const BString& ID() const; const BString& Name() const; int OffsetFromGMT() const; diff --git a/src/preferences/time/ZoneView.cpp b/src/preferences/time/ZoneView.cpp index fbeb39fcc2..e7b05abecd 100644 --- a/src/preferences/time/ZoneView.cpp +++ b/src/preferences/time/ZoneView.cpp @@ -15,6 +15,7 @@ #include +#include #include #include @@ -37,6 +38,7 @@ #include #include +#include #include #include @@ -52,9 +54,21 @@ using BPrivate::gMutableLocaleRoster; using BPrivate::ObjectDeleter; +struct TimeZoneItemLess { + bool operator()(const BString& first, const BString& second) + { + return fCollator.Compare(first.String(), second.String()) < 0; + } +private: + BCollator fCollator; +}; + + + TimeZoneView::TimeZoneView(BRect frame) : BView(frame, "timeZoneView", B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE_JUMP), + fToolTip(NULL), fCurrentZoneItem(NULL), fOldZoneItem(NULL), fInitialized(false) @@ -70,26 +84,9 @@ TimeZoneView::CheckCanRevert() } -void -TimeZoneView::_Revert() -{ - fCurrentZoneItem = fOldZoneItem; - - if (fCurrentZoneItem != NULL) { - int32 currentZoneIndex = fZoneList->IndexOf(fCurrentZoneItem); - fZoneList->Select(currentZoneIndex); - } else - fZoneList->DeselectAll(); - fZoneList->ScrollToSelection(); - - _SetSystemTimeZone(); - _UpdatePreview(); - _UpdateCurrent(); -} - - TimeZoneView::~TimeZoneView() { + delete fToolTip; } @@ -165,6 +162,29 @@ TimeZoneView::MessageReceived(BMessage* message) } +bool +TimeZoneView::GetToolTipAt(BPoint point, BToolTip** _tip) +{ + TimeZoneListItem* item = static_cast( + fZoneList->ItemAt(fZoneList->IndexOf(point))); + if (item == NULL || !item->HasTimeZone()) + return false; + + BString toolTip = item->Text(); + toolTip << '\n' << item->TimeZone().ShortName() << " / " + << item->TimeZone().ShortDaylightSavingName(); + + delete fToolTip; + fToolTip = new (std::nothrow) BTextToolTip(toolTip.String()); + if (fToolTip == NULL) + return false; + + *_tip = fToolTip; + + return true; +} + + void TimeZoneView::_UpdateDateTime(BMessage* message) { @@ -195,7 +215,7 @@ TimeZoneView::_InitView() fZoneList->SetSelectionMessage(new BMessage(H_CITY_CHANGED)); fZoneList->SetInvocationMessage(new BMessage(H_SET_TIME_ZONE)); - _BuildRegionMenu(); + _BuildZoneMenu(); BScrollView* scrollList = new BScrollView("scrollList", fZoneList, B_FOLLOW_ALL, 0, false, true); @@ -230,7 +250,7 @@ TimeZoneView::_InitView() void -TimeZoneView::_BuildRegionMenu() +TimeZoneView::_BuildZoneMenu() { BTimeZone defaultTimeZone = NULL; be_locale_roster->GetDefaultTimeZone(&defaultTimeZone); @@ -239,75 +259,119 @@ TimeZoneView::_BuildRegionMenu() // AddUnder() them (only if there are multiple ones). // Finally expand the current country and highlight the active TZ. - BMessage countryList; - be_locale_roster->GetAvailableCountries(&countryList); + BMessage zoneList; + be_locale_roster->GetAvailableTimeZones(&zoneList); - BString countryCode; - for (int i = 0; countryList.FindString("countries", i, &countryCode) - == B_OK; i++) { - BCountry country("", countryCode); - BString fullName; - country.GetName(fullName); + typedef std::map ZoneItemMap; + ZoneItemMap zoneMap; + const char* supportedRegions[] = { + "Africa", "America", "Antarctica", "Arctic", "Asia", "Atlantic", + "Australia", "Etc", "Europe", "Indian", "Pacific", NULL + }; + for (const char** region = supportedRegions; *region != NULL; ++region) + zoneMap[*region] = NULL; - // Now list the timezones for this country - BList tzList; + BString zoneID; + for (int i = 0; zoneList.FindString("timeZone", i, &zoneID) == B_OK; i++) { + int32 slashPos = zoneID.FindFirst('/'); - BTimeZone* timeZone; - TimeZoneListItem* countryItem; - switch (country.GetTimeZones(tzList)) - { - case 0: - // No TZ info for this country. Sorry guys! - break; - case 1: - // Only one Timezone, no need to add it to the list - timeZone = (BTimeZone*)tzList.ItemAt(0); - countryItem - = new TimeZoneListItem(fullName, &country, timeZone); - fZoneList->AddItem(countryItem); - if (timeZone->Code() == defaultTimeZone.Code()) - fCurrentZoneItem = countryItem; - break; - default: - countryItem = new TimeZoneListItem(fullName, &country, NULL); + // ignore any "global" timezones, as those are just aliases of regional + // ones + if (slashPos <= 0) + continue; + + BString region(zoneID, slashPos); + + // just accept timezones from "known" regions, as all others are aliases + ZoneItemMap::iterator regionIter = zoneMap.find(region); + if (regionIter == zoneMap.end()) + continue; + + TimeZoneListItem* regionItem = regionIter->second; + if (regionItem == NULL) { + regionItem = new TimeZoneListItem(region, NULL, NULL); + regionItem->SetOutlineLevel(0); + regionItem->SetExpanded(false); + zoneMap[region] = regionItem; + } + + BTimeZone* timeZone = new BTimeZone(zoneID); + BString tzName = timeZone->Name(); + if (tzName == "GMT+00:00") + tzName = "GMT"; + int32 openParenthesisPos = tzName.FindFirst('('); + BString country; + if (openParenthesisPos >= 0) { + if (openParenthesisPos > 0) + country.SetTo(tzName, openParenthesisPos - 1); + tzName.Remove(0, openParenthesisPos + 1); + int32 closeParenthesisPos = tzName.FindLast(')'); + if (closeParenthesisPos >= 0) + tzName.Truncate(closeParenthesisPos); + } + BString fullCountryID = region; + if (country.Length() > 0 && country != region) + fullCountryID << "/" << country; + BString fullZoneID = fullCountryID; + fullZoneID << "/" << tzName; + + // skip duplicates + ZoneItemMap::iterator zoneIter = zoneMap.find(fullZoneID); + if (zoneIter != zoneMap.end()) { + delete timeZone; + continue; + } + + TimeZoneListItem* countryItem = NULL; + if (country.Length() > 0) { + ZoneItemMap::iterator countryIter = zoneMap.find(fullCountryID); + if (countryIter == zoneMap.end()) { + countryItem = new TimeZoneListItem(country, NULL, NULL); + countryItem->SetOutlineLevel(1); countryItem->SetExpanded(false); - fZoneList->AddItem(countryItem); + zoneMap[fullCountryID] = countryItem; + } else + countryItem = countryIter->second; + } - for (int j = 0; - (timeZone = (BTimeZone*)tzList.ItemAt(j)) != NULL; - j++) { - TimeZoneListItem* tzItem = new TimeZoneListItem( - timeZone->Name(), NULL, timeZone); - fZoneList->AddUnder(tzItem, countryItem); - if (timeZone->Code() == defaultTimeZone.Code()) - { - fCurrentZoneItem = tzItem; - countryItem->SetExpanded(true); - } - } - break; + TimeZoneListItem* zoneItem + = new TimeZoneListItem(tzName, NULL, timeZone); + zoneItem->SetOutlineLevel(countryItem == NULL ? 1 : 2); + zoneMap[fullZoneID] = zoneItem; + + if (timeZone->ID() == defaultTimeZone.ID()) { + fCurrentZoneItem = zoneItem; + if (countryItem != NULL) + countryItem->SetExpanded(true); + regionItem->SetExpanded(true); } } - // add an artifical (i.e. belongs to no country) entry for GMT/UTC - BTimeZone* gmtZone = new(std::nothrow) BTimeZone(BTimeZone::kNameOfGmtZone); - TimeZoneListItem* gmtItem - = new TimeZoneListItem("- GMT/UTC (Universal Time) -", NULL, gmtZone); - fZoneList->AddItem(gmtItem); - if (gmtZone->Code() == defaultTimeZone.Code()) - fCurrentZoneItem = gmtItem; - fOldZoneItem = fCurrentZoneItem; - struct ListSorter { - static int compare(const BListItem* first, const BListItem* second) - { - static BCollator collator; - return collator.Compare(((BStringItem*)first)->Text(), - ((BStringItem*)second)->Text()); - } - }; - fZoneList->SortItemsUnder(NULL, false, ListSorter::compare); + ZoneItemMap::iterator zoneIter; + for (zoneIter = zoneMap.begin(); zoneIter != zoneMap.end(); ++zoneIter) + fZoneList->AddItem(zoneIter->second); + + fZoneList->Select(fZoneList->IndexOf(fCurrentZoneItem)); +} + + +void +TimeZoneView::_Revert() +{ + fCurrentZoneItem = fOldZoneItem; + + if (fCurrentZoneItem != NULL) { + int32 currentZoneIndex = fZoneList->IndexOf(fCurrentZoneItem); + fZoneList->Select(currentZoneIndex); + } else + fZoneList->DeselectAll(); + fZoneList->ScrollToSelection(); + + _SetSystemTimeZone(); + _UpdatePreview(); + _UpdateCurrent(); } @@ -315,12 +379,16 @@ void TimeZoneView::_UpdatePreview() { int32 selection = fZoneList->CurrentSelection(); - if (selection < 0) - return; + TimeZoneListItem* item + = selection < 0 + ? NULL + : (TimeZoneListItem*)fZoneList->ItemAt(selection); - TimeZoneListItem* item = (TimeZoneListItem*)fZoneList->ItemAt(selection); - if (!item->HasTimeZone()) + if (item == NULL || !item->HasTimeZone()) { + fPreview->SetText(""); + fPreview->SetTime(""); return; + } BString timeString = _FormatTime(item); fPreview->SetText(item->Text()); @@ -360,8 +428,8 @@ TimeZoneView::_SetSystemTimeZone() gMutableLocaleRoster->SetDefaultTimeZone(timeZone); - _kern_set_timezone(timeZone.OffsetFromGMT(), timeZone.Code().String(), - timeZone.Code().Length()); + _kern_set_timezone(timeZone.OffsetFromGMT(), timeZone.ID().String(), + timeZone.ID().Length()); fSetZone->SetEnabled(false); fLastUpdateMinute = -1; diff --git a/src/preferences/time/ZoneView.h b/src/preferences/time/ZoneView.h index b29c1abdb8..e4d656b0d8 100644 --- a/src/preferences/time/ZoneView.h +++ b/src/preferences/time/ZoneView.h @@ -18,6 +18,7 @@ class BMessage; class BPopUpMenu; class BOutlineListView; class BButton; +class BTextToolTip; class TTZDisplay; class TimeZoneListItem; @@ -31,6 +32,9 @@ public: virtual void MessageReceived(BMessage* message); bool CheckCanRevert(); +protected: + virtual bool GetToolTipAt(BPoint point, BToolTip** _tip); + private: void _UpdateDateTime(BMessage* message); @@ -41,7 +45,7 @@ private: BString _FormatTime(TimeZoneListItem* zoneItem); void _InitView(); - void _BuildRegionMenu(); + void _BuildZoneMenu(); void _Revert(); @@ -51,6 +55,8 @@ private: TTZDisplay* fCurrent; TTZDisplay* fPreview; + BTextToolTip* fToolTip; + int32 fLastUpdateMinute; TimeZoneListItem* fCurrentZoneItem;