Time prefs: rework time zone view

* Add country flags back to the time zone view.
* Use Appearance color constants.
This commit is contained in:
John Scipione
2013-12-13 00:42:10 -05:00
parent 553211b499
commit 5b013eab68
3 changed files with 173 additions and 92 deletions
+99 -59
View File
@@ -1,12 +1,13 @@
/* /*
* Copyright 2010, Haiku Inc. All rights reserved. * Copyright 2010-2013 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Adrien Destugues <[email protected]> * Stephan Aßmus, [email protected]
* Stephan Aßmus <[email protected]> * Adrien Destugues, [email protected]
* Axel Dörfler, [email protected] * Axel Dörfler, [email protected]
* Oliver Tappe <[email protected]> * John Scipione, [email protected]
* Oliver Tappe, [email protected]
*/ */
@@ -16,6 +17,7 @@
#include <Bitmap.h> #include <Bitmap.h>
#include <Country.h> #include <Country.h>
#include <ControlLook.h>
#include <String.h> #include <String.h>
#include <TimeZone.h> #include <TimeZone.h>
#include <Window.h> #include <Window.h>
@@ -28,90 +30,85 @@ TimeZoneListItem::TimeZoneListItem(const char* text, BCountry* country,
BTimeZone* timeZone) BTimeZone* timeZone)
: :
BStringItem(text, 0, false), BStringItem(text, 0, false),
fIcon(NULL), fCountry(country),
fTimeZone(timeZone) 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() TimeZoneListItem::~TimeZoneListItem()
{ {
delete fIcon; delete fCountry;
delete fTimeZone; delete fTimeZone;
delete fIcon;
} }
void void
TimeZoneListItem::DrawItem(BView* owner, BRect frame, bool complete) 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()) { 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->SetDrawingMode(B_OP_OVER);
owner->DrawBitmap(fIcon, iconFrame); owner->DrawBitmap(fIcon, iconFrame);
owner->SetDrawingMode(B_OP_COPY); owner->SetDrawingMode(B_OP_COPY);
} } else
_DrawItemWithTextOffset(owner, frame, complete, 0);
} }
bool void
TimeZoneListItem::HasTimeZone() const TimeZoneListItem::Update(BView* owner, const BFont* font)
{ {
return fTimeZone != NULL; 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;
}
} }
const BTimeZone& void
TimeZoneListItem::TimeZone() const TimeZoneListItem::SetCountry(BCountry* country)
{ {
return *fTimeZone; delete fCountry;
fCountry = country;
}
void
TimeZoneListItem::SetTimeZone(BTimeZone* timeZone)
{
delete fTimeZone;
fTimeZone = timeZone;
} }
const BString& const BString&
TimeZoneListItem::ID() const TimeZoneListItem::ID() const
{ {
if (fTimeZone == NULL) if (!HasTimeZone())
return skDefaultString; return skDefaultString;
return fTimeZone->ID(); return fTimeZone->ID();
@@ -121,7 +118,7 @@ TimeZoneListItem::ID() const
const BString& const BString&
TimeZoneListItem::Name() const TimeZoneListItem::Name() const
{ {
if (fTimeZone == NULL) if (!HasTimeZone())
return skDefaultString; return skDefaultString;
return fTimeZone->Name(); return fTimeZone->Name();
@@ -131,8 +128,51 @@ TimeZoneListItem::Name() const
int int
TimeZoneListItem::OffsetFromGMT() const TimeZoneListItem::OffsetFromGMT() const
{ {
if (fTimeZone == NULL) if (!HasTimeZone())
return 0; return 0;
return fTimeZone->OffsetFromGMT(); 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);
}
+21 -5
View File
@@ -21,20 +21,36 @@ class TimeZoneListItem : public BStringItem {
public: public:
TimeZoneListItem(const char* text, TimeZoneListItem(const char* text,
BCountry* country, BTimeZone* timeZone); BCountry* country, BTimeZone* timeZone);
~TimeZoneListItem(); virtual ~TimeZoneListItem();
void DrawItem(BView* owner, BRect frame, virtual void DrawItem(BView* owner, BRect frame,
bool complete = false); bool complete = false);
bool HasTimeZone() const; virtual void Update(BView* owner, const BFont* font);
const BTimeZone& TimeZone() const;
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& ID() const;
const BString& Name() const; const BString& Name() const;
int OffsetFromGMT() const; int OffsetFromGMT() const;
private: private:
BBitmap* fIcon; void _DrawItemWithTextOffset(BView* owner,
BRect frame, bool complete,
float textOffset);
BCountry* fCountry;
BTimeZone* fTimeZone; BTimeZone* fTimeZone;
BBitmap* fIcon;
}; };
+53 -28
View File
@@ -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. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Mike Berg <[email protected]> * Mike Berg, [email protected]
* Julun <[email protected]> * Adrien Destugues, [email protected]
* Philippe Saint-Pierre <[email protected]> * Julun, [email protected]
* Adrien Destugues <[email protected]> * Hamish Morrison, [email protected]
* Oliver Tappe <[email protected]> * Philippe Saint-Pierre, [email protected]
* Hamish Morrison <hamish@lavabit.com> * John Scipione, jscipione@gmail.com
* Oliver Tappe, [email protected]
*/ */
@@ -316,15 +317,19 @@ TimeZoneView::_BuildZoneMenu()
ZonesByCountyMap::const_iterator countryIter = zonesByCountryMap.begin(); ZonesByCountyMap::const_iterator countryIter = zonesByCountryMap.begin();
for (; countryIter != zonesByCountryMap.end(); ++countryIter) { for (; countryIter != zonesByCountryMap.end(); ++countryIter) {
BCountry country(countryIter->first.String()); const char* countryCode = countryIter->first.String();
BString countryName; if (countryCode == NULL)
country.GetName(countryName); continue;
size_t zoneCountInCountry = countryIter->second.size(); size_t zoneCountInCountry = countryIter->second.size();
for (size_t tz = 0; tz < zoneCountInCountry; tz++) { for (size_t tz = 0; tz < zoneCountInCountry; tz++) {
BString zoneID(countryIter->second[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); BString region(zoneID, slashPos);
if (region == "Etc") if (region == "Etc")
region = kOtherRegion; region = kOtherRegion;
@@ -336,29 +341,35 @@ TimeZoneView::_BuildZoneMenu()
continue; continue;
BString fullCountryID = regionIter->second; 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 bool countryIsRegion = countryName == regionIter->second
|| region == kOtherRegion; || region == kOtherRegion;
if (!countryIsRegion) if (!countryIsRegion)
fullCountryID << "/" << countryName; fullCountryID << "/" << countryName;
BTimeZone* timeZone = new BTimeZone(zoneID, &language); BString timeZoneName;
BString tzName;
BString fullZoneID = fullCountryID; BString fullZoneID = fullCountryID;
if (zoneCountInCountry > 1) { if (zoneCountInCountry > 1) {
// we can't use the country name as timezone name, since there // we can't use the country name as timezone name, since there
// are more than one timezones in this country - fetch the // are more than one timezones in this country - fetch the
// localized name of the timezone and use that // localized name of the timezone and use that
tzName = timeZone->Name(); timeZoneName = timeZone->Name();
int32 openParenthesisPos = tzName.FindFirst('('); int32 openParenthesisPos = timeZoneName.FindFirst('(');
if (openParenthesisPos >= 0) { if (openParenthesisPos >= 0) {
tzName.Remove(0, openParenthesisPos + 1); timeZoneName.Remove(0, openParenthesisPos + 1);
int32 closeParenthesisPos = tzName.FindLast(')'); int32 closeParenthesisPos = timeZoneName.FindLast(')');
if (closeParenthesisPos >= 0) if (closeParenthesisPos >= 0)
tzName.Truncate(closeParenthesisPos); timeZoneName.Truncate(closeParenthesisPos);
} }
fullZoneID << "/" << tzName; fullZoneID << "/" << timeZoneName;
} else { } else {
tzName = countryName; timeZoneName = countryName;
fullZoneID << "/" << zoneID; fullZoneID << "/" << zoneID;
} }
@@ -375,17 +386,22 @@ TimeZoneView::_BuildZoneMenu()
ZoneItemMap::iterator countryIter ZoneItemMap::iterator countryIter
= zoneItemMap.find(fullCountryID); = zoneItemMap.find(fullCountryID);
if (countryIter == zoneItemMap.end()) { if (countryIter == zoneItemMap.end()) {
countryItem = new TimeZoneListItem(countryName, NULL, NULL); countryItem = new TimeZoneListItem(countryName.String(),
country, NULL);
countryItem->SetOutlineLevel(1); countryItem->SetOutlineLevel(1);
zoneItemMap[fullCountryID] = countryItem; zoneItemMap[fullCountryID] = countryItem;
hasUsedCountry = true;
} else } else
countryItem = countryIter->second; countryItem = countryIter->second;
zoneItem = new TimeZoneListItem(tzName, NULL, timeZone); zoneItem = new TimeZoneListItem(timeZoneName.String(),
NULL, timeZone);
zoneItem->SetOutlineLevel(countryIsRegion ? 1 : 2); zoneItem->SetOutlineLevel(countryIsRegion ? 1 : 2);
} else { } else {
zoneItem = new TimeZoneListItem(tzName, NULL, timeZone); zoneItem = new TimeZoneListItem(timeZoneName.String(),
country, timeZone);
zoneItem->SetOutlineLevel(1); zoneItem->SetOutlineLevel(1);
hasUsedCountry = true;
} }
zoneItemMap[fullZoneID] = zoneItem; zoneItemMap[fullZoneID] = zoneItem;
@@ -399,6 +415,9 @@ TimeZoneView::_BuildZoneMenu()
if (regionItemIter != zoneItemMap.end()) if (regionItemIter != zoneItemMap.end())
regionItemIter->second->SetExpanded(true); regionItemIter->second->SetExpanded(true);
} }
if (!hasUsedCountry)
delete country;
} }
} }
@@ -406,7 +425,7 @@ TimeZoneView::_BuildZoneMenu()
ZoneItemMap::iterator zoneIter; ZoneItemMap::iterator zoneIter;
bool lastWasCountryItem = false; bool lastWasCountryItem = false;
TimeZoneListItem* currentCountryItem = NULL; TimeZoneListItem* currentItem = NULL;
for (zoneIter = zoneItemMap.begin(); zoneIter != zoneItemMap.end(); for (zoneIter = zoneItemMap.begin(); zoneIter != zoneItemMap.end();
++zoneIter) { ++zoneIter) {
if (zoneIter->second->OutlineLevel() == 2 && lastWasCountryItem) { if (zoneIter->second->OutlineLevel() == 2 && lastWasCountryItem) {
@@ -418,17 +437,23 @@ TimeZoneView::_BuildZoneMenu()
++next; ++next;
if (next != zoneItemMap.end() if (next != zoneItemMap.end()
&& next->second->OutlineLevel() != 2) { && next->second->OutlineLevel() != 2) {
fZoneList->RemoveItem(currentCountryItem); fZoneList->RemoveItem(currentItem);
zoneIter->second->SetText(currentCountryItem->Text()); 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); zoneIter->second->SetOutlineLevel(1);
delete currentCountryItem; delete currentItem;
} }
} }
fZoneList->AddItem(zoneIter->second); fZoneList->AddItem(zoneIter->second);
if (zoneIter->second->OutlineLevel() == 1) { if (zoneIter->second->OutlineLevel() == 1) {
lastWasCountryItem = true; lastWasCountryItem = true;
currentCountryItem = zoneIter->second; currentItem = zoneIter->second;
} else } else
lastWasCountryItem = false; lastWasCountryItem = false;
} }