diff --git a/src/preferences/time/TimeZoneListItem.cpp b/src/preferences/time/TimeZoneListItem.cpp index a7058f8434..4bcd7fdf28 100644 --- a/src/preferences/time/TimeZoneListItem.cpp +++ b/src/preferences/time/TimeZoneListItem.cpp @@ -1,13 +1,14 @@ /* - * Copyright 2010, Haiku Inc. All rights reserved. + * Copyright 2010-2013 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: - * Adrien Destugues - * Stephan Aßmus + * Stephan Aßmus, superstippi@gmx.de + * Adrien Destugues, pulkomandy@pulkomandy.ath.cx * Axel Dörfler, axeld@pinc-software.de - * Oliver Tappe -*/ + * John Scipione, jscipione@gmail.com + * Oliver Tappe, zooey@hirschkaefer.de + */ #include "TimeZoneListItem.h" @@ -16,6 +17,7 @@ #include #include +#include #include #include #include @@ -28,90 +30,85 @@ TimeZoneListItem::TimeZoneListItem(const char* text, BCountry* country, BTimeZone* timeZone) : BStringItem(text, 0, false), - fIcon(NULL), - fTimeZone(timeZone) + fCountry(country), + fTimeZone(timeZone), + fIcon(NULL) { - if (country != NULL) { - fIcon = new(std::nothrow) BBitmap(BRect(0, 0, 15, 15), B_RGBA32); - if (fIcon != NULL && country->GetIcon(fIcon) != B_OK) { - delete fIcon; - fIcon = NULL; - } - } } TimeZoneListItem::~TimeZoneListItem() { - delete fIcon; + delete fCountry; delete fTimeZone; + delete fIcon; } void TimeZoneListItem::DrawItem(BView* owner, BRect frame, bool complete) { - rgb_color kHighlight = {140, 140, 140, 0}; - rgb_color kBlack = {0, 0, 0, 0}; - - if (IsSelected() || complete) { - rgb_color color; - if (IsSelected()) - color = kHighlight; - else - color = owner->ViewColor(); - owner->SetHighColor(color); - owner->SetLowColor(color); - owner->FillRect(frame); - owner->SetHighColor(kBlack); - } else - owner->SetLowColor(owner->ViewColor()); - - // Draw the text - BString text = Text(); - - BFont font = be_plain_font; - font_height finfo; - font.GetHeight(&finfo); - owner->SetFont(&font); - // TODO: the position is unnecessarily complicated, and not correct either - owner->MovePenTo(frame.left + 8, frame.top - + (frame.Height() - (finfo.ascent + finfo.descent + finfo.leading)) / 2 - + (finfo.ascent + finfo.descent) - 1); - owner->DrawString(text.String()); - - // Draw the icon - frame.left = frame.right - 16; - BRect iconFrame(frame); - iconFrame.Set(iconFrame.left, iconFrame.top + 1, iconFrame.left + 15, - iconFrame.top + 16); - if (fIcon != NULL && fIcon->IsValid()) { + float iconSize = fIcon->Bounds().Width(); + _DrawItemWithTextOffset(owner, frame, complete, + iconSize + be_control_look->DefaultLabelSpacing()); + + BRect iconFrame(frame.left + be_control_look->DefaultLabelSpacing(), + frame.top, + frame.left + iconSize - 1 + be_control_look->DefaultLabelSpacing(), + frame.top + iconSize - 1); owner->SetDrawingMode(B_OP_OVER); owner->DrawBitmap(fIcon, iconFrame); owner->SetDrawingMode(B_OP_COPY); + } else + _DrawItemWithTextOffset(owner, frame, complete, 0); +} + + +void +TimeZoneListItem::Update(BView* owner, const BFont* font) +{ + float oldIconSize = Height(); + BStringItem::Update(owner, font); + if (!HasCountry()) + return; + + float iconSize = Height(); + if (iconSize == oldIconSize && fIcon != NULL) + return; + + SetWidth(Width() + iconSize + be_control_look->DefaultLabelSpacing()); + + delete fIcon; + fIcon = new(std::nothrow) BBitmap(BRect(0, 0, iconSize - 1, iconSize - 1), + B_RGBA32); + if (fIcon != NULL && fCountry->GetIcon(fIcon) != B_OK) { + delete fIcon; + fIcon = NULL; } } -bool -TimeZoneListItem::HasTimeZone() const +void +TimeZoneListItem::SetCountry(BCountry* country) { - return fTimeZone != NULL; + delete fCountry; + fCountry = country; } -const BTimeZone& -TimeZoneListItem::TimeZone() const +void +TimeZoneListItem::SetTimeZone(BTimeZone* timeZone) { - return *fTimeZone; + delete fTimeZone; + fTimeZone = timeZone; } const BString& TimeZoneListItem::ID() const { - if (fTimeZone == NULL) + if (!HasTimeZone()) return skDefaultString; return fTimeZone->ID(); @@ -121,7 +118,7 @@ TimeZoneListItem::ID() const const BString& TimeZoneListItem::Name() const { - if (fTimeZone == NULL) + if (!HasTimeZone()) return skDefaultString; return fTimeZone->Name(); @@ -131,8 +128,51 @@ TimeZoneListItem::Name() const int TimeZoneListItem::OffsetFromGMT() const { - if (fTimeZone == NULL) + if (!HasTimeZone()) return 0; return fTimeZone->OffsetFromGMT(); } + + +void +TimeZoneListItem::_DrawItemWithTextOffset(BView* owner, BRect frame, + bool complete, float textOffset) +{ + rgb_color highColor = owner->HighColor(); + rgb_color lowColor = owner->LowColor(); + + if (IsSelected() || complete) { + rgb_color color; + if (IsSelected()) + color = ui_color(B_LIST_SELECTED_BACKGROUND_COLOR); + else + color = owner->ViewColor(); + + owner->SetHighColor(color); + owner->SetLowColor(color); + owner->FillRect(frame); + } else + owner->SetLowColor(owner->ViewColor()); + + if (!IsEnabled()) { + rgb_color textColor = ui_color(B_LIST_ITEM_TEXT_COLOR); + if (textColor.red + textColor.green + textColor.blue > 128 * 3) + owner->SetHighColor(tint_color(textColor, B_DARKEN_2_TINT)); + else + owner->SetHighColor(tint_color(textColor, B_LIGHTEN_2_TINT)); + } else { + if (IsSelected()) + owner->SetHighColor(ui_color(B_LIST_SELECTED_ITEM_TEXT_COLOR)); + else + owner->SetHighColor(ui_color(B_LIST_ITEM_TEXT_COLOR)); + } + + owner->MovePenTo( + frame.left + be_control_look->DefaultLabelSpacing() + textOffset, + frame.top + BaselineOffset()); + owner->DrawString(Text()); + + owner->SetHighColor(highColor); + owner->SetLowColor(lowColor); +} diff --git a/src/preferences/time/TimeZoneListItem.h b/src/preferences/time/TimeZoneListItem.h index 1071d9da2e..81a553f986 100644 --- a/src/preferences/time/TimeZoneListItem.h +++ b/src/preferences/time/TimeZoneListItem.h @@ -21,20 +21,36 @@ class TimeZoneListItem : public BStringItem { public: TimeZoneListItem(const char* text, BCountry* country, BTimeZone* timeZone); - ~TimeZoneListItem(); + virtual ~TimeZoneListItem(); - void DrawItem(BView* owner, BRect frame, + virtual void DrawItem(BView* owner, BRect frame, bool complete = false); - bool HasTimeZone() const; - const BTimeZone& TimeZone() const; + virtual void Update(BView* owner, const BFont* font); + + bool HasCountry() const + { return fCountry != NULL; }; + const BCountry& Country() const { return *fCountry; }; + void SetCountry(BCountry* country); + + bool HasTimeZone() const + { return fTimeZone != NULL; }; + const BTimeZone& TimeZoneListItem::TimeZone() const + { return *fTimeZone; }; + void SetTimeZone(BTimeZone* timeZone); + const BString& ID() const; const BString& Name() const; int OffsetFromGMT() const; private: - BBitmap* fIcon; + void _DrawItemWithTextOffset(BView* owner, + BRect frame, bool complete, + float textOffset); + + BCountry* fCountry; BTimeZone* fTimeZone; + BBitmap* fIcon; }; diff --git a/src/preferences/time/ZoneView.cpp b/src/preferences/time/ZoneView.cpp index 2356bba518..8d3e4414c8 100644 --- a/src/preferences/time/ZoneView.cpp +++ b/src/preferences/time/ZoneView.cpp @@ -1,14 +1,15 @@ /* - * Copyright 2004-2012, Haiku, Inc. All Rights Reserved. + * Copyright 2004-2013 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: - * Mike Berg - * Julun - * Philippe Saint-Pierre - * Adrien Destugues - * Oliver Tappe - * Hamish Morrison + * Mike Berg, mike@berg-net.us + * Adrien Destugues, pulkomandy@pulkomandy.ath.cx + * Julun, host.haiku@gmx.de + * Hamish Morrison, hamish@lavabit.com + * Philippe Saint-Pierre, stpere@gmail.com + * John Scipione, jscipione@gmail.com + * Oliver Tappe, zooey@hirschkaefer.de */ @@ -316,15 +317,19 @@ TimeZoneView::_BuildZoneMenu() ZonesByCountyMap::const_iterator countryIter = zonesByCountryMap.begin(); for (; countryIter != zonesByCountryMap.end(); ++countryIter) { - BCountry country(countryIter->first.String()); - BString countryName; - country.GetName(countryName); + const char* countryCode = countryIter->first.String(); + if (countryCode == NULL) + continue; size_t zoneCountInCountry = countryIter->second.size(); for (size_t tz = 0; tz < zoneCountInCountry; tz++) { BString zoneID(countryIter->second[tz]); - int32 slashPos = zoneID.FindFirst('/'); + BTimeZone* timeZone + = new(std::nothrow) BTimeZone(zoneID, &language); + if (timeZone == NULL) + continue; + int32 slashPos = zoneID.FindFirst('/'); BString region(zoneID, slashPos); if (region == "Etc") region = kOtherRegion; @@ -336,29 +341,35 @@ TimeZoneView::_BuildZoneMenu() continue; BString fullCountryID = regionIter->second; + BCountry* country = new(std::nothrow) BCountry(countryCode); + if (country == NULL) + continue; + + BString countryName; + country->GetName(countryName); + bool hasUsedCountry = false; bool countryIsRegion = countryName == regionIter->second || region == kOtherRegion; if (!countryIsRegion) fullCountryID << "/" << countryName; - BTimeZone* timeZone = new BTimeZone(zoneID, &language); - BString tzName; + BString timeZoneName; BString fullZoneID = fullCountryID; if (zoneCountInCountry > 1) { // we can't use the country name as timezone name, since there // are more than one timezones in this country - fetch the // localized name of the timezone and use that - tzName = timeZone->Name(); - int32 openParenthesisPos = tzName.FindFirst('('); + timeZoneName = timeZone->Name(); + int32 openParenthesisPos = timeZoneName.FindFirst('('); if (openParenthesisPos >= 0) { - tzName.Remove(0, openParenthesisPos + 1); - int32 closeParenthesisPos = tzName.FindLast(')'); + timeZoneName.Remove(0, openParenthesisPos + 1); + int32 closeParenthesisPos = timeZoneName.FindLast(')'); if (closeParenthesisPos >= 0) - tzName.Truncate(closeParenthesisPos); + timeZoneName.Truncate(closeParenthesisPos); } - fullZoneID << "/" << tzName; + fullZoneID << "/" << timeZoneName; } else { - tzName = countryName; + timeZoneName = countryName; fullZoneID << "/" << zoneID; } @@ -375,17 +386,22 @@ TimeZoneView::_BuildZoneMenu() ZoneItemMap::iterator countryIter = zoneItemMap.find(fullCountryID); if (countryIter == zoneItemMap.end()) { - countryItem = new TimeZoneListItem(countryName, NULL, NULL); + countryItem = new TimeZoneListItem(countryName.String(), + country, NULL); countryItem->SetOutlineLevel(1); zoneItemMap[fullCountryID] = countryItem; + hasUsedCountry = true; } else countryItem = countryIter->second; - zoneItem = new TimeZoneListItem(tzName, NULL, timeZone); + zoneItem = new TimeZoneListItem(timeZoneName.String(), + NULL, timeZone); zoneItem->SetOutlineLevel(countryIsRegion ? 1 : 2); } else { - zoneItem = new TimeZoneListItem(tzName, NULL, timeZone); + zoneItem = new TimeZoneListItem(timeZoneName.String(), + country, timeZone); zoneItem->SetOutlineLevel(1); + hasUsedCountry = true; } zoneItemMap[fullZoneID] = zoneItem; @@ -399,6 +415,9 @@ TimeZoneView::_BuildZoneMenu() if (regionItemIter != zoneItemMap.end()) regionItemIter->second->SetExpanded(true); } + + if (!hasUsedCountry) + delete country; } } @@ -406,7 +425,7 @@ TimeZoneView::_BuildZoneMenu() ZoneItemMap::iterator zoneIter; bool lastWasCountryItem = false; - TimeZoneListItem* currentCountryItem = NULL; + TimeZoneListItem* currentItem = NULL; for (zoneIter = zoneItemMap.begin(); zoneIter != zoneItemMap.end(); ++zoneIter) { if (zoneIter->second->OutlineLevel() == 2 && lastWasCountryItem) { @@ -418,17 +437,23 @@ TimeZoneView::_BuildZoneMenu() ++next; if (next != zoneItemMap.end() && next->second->OutlineLevel() != 2) { - fZoneList->RemoveItem(currentCountryItem); - zoneIter->second->SetText(currentCountryItem->Text()); + fZoneList->RemoveItem(currentItem); + zoneIter->second->SetText(currentItem->Text()); + zoneIter->second->SetCountry(currentItem->HasCountry() + ? new(std::nothrow) BCountry(currentItem->Country()) + : NULL); + zoneIter->second->SetTimeZone(currentItem->HasTimeZone() + ? new(std::nothrow) BTimeZone(currentItem->TimeZone()) + : NULL); zoneIter->second->SetOutlineLevel(1); - delete currentCountryItem; + delete currentItem; } } fZoneList->AddItem(zoneIter->second); if (zoneIter->second->OutlineLevel() == 1) { lastWasCountryItem = true; - currentCountryItem = zoneIter->second; + currentItem = zoneIter->second; } else lastWasCountryItem = false; }