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-11-26 05:10:48 -05:00
parent 553211b499
commit 5b013eab68
3 changed files with 173 additions and 92 deletions

View File

@ -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 <pulkomandy@pulkomandy.ath.cx>
* Stephan Aßmus <superstippi@gmx.de>
* Stephan Aßmus, superstippi@gmx.de
* Adrien Destugues, pulkomandy@pulkomandy.ath.cx
* Axel Dörfler, axeld@pinc-software.de
* Oliver Tappe <zooey@hirschkaefer.de>
*/
* John Scipione, jscipione@gmail.com
* Oliver Tappe, zooey@hirschkaefer.de
*/
#include "TimeZoneListItem.h"
@ -16,6 +17,7 @@
#include <Bitmap.h>
#include <Country.h>
#include <ControlLook.h>
#include <String.h>
#include <TimeZone.h>
#include <Window.h>
@ -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);
}

View File

@ -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;
};

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.
*
* Authors:
* Mike Berg <mike@berg-net.us>
* Julun <host.haiku@gmx.de>
* Philippe Saint-Pierre <stpere@gmail.com>
* Adrien Destugues <pulkomandy@pulkomandy.ath.cx>
* Oliver Tappe <zooey@hirschkaefer.de>
* Hamish Morrison <hamish@lavabit.com>
* 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;
}