Fix drawing artefacts in Locale prefs (and IMHO improve the look):

* separate LanguageListItemWithFlag from LanguageListItem
* draw the flag in front of the text instead of at wherever the right bounds happen to
  be, fixing the drawing artefacts when scrolling
* size the flag to match the size of the list item, which looks much better when
  using a largish default font
* use StringItem::BaselineOffset() instead of manually computed (and wrong) offset
  when drawing the text


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42667 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Oliver Tappe
2011-08-21 17:24:27 +00:00
parent e267238ff1
commit ed32703038
3 changed files with 149 additions and 88 deletions
+79 -46
View File
@@ -30,47 +30,40 @@
#define B_TRANSLATE_CONTEXT "LanguageListView"
static const float kFlagWidth = 17.0;
static const float kLeftInset = 4;
LanguageListItem::LanguageListItem(const char* text, const char* id,
const char* code, const char* countryCode)
const char* languageCode)
:
BStringItem(text),
fID(id),
fCode(code)
fCode(languageCode)
{
fIcon = new(std::nothrow) BBitmap(BRect(0, 0, 15, 15), B_RGBA32);
if (fIcon != NULL && BLocaleRoster::Default()->GetFlagIconForCountry(fIcon,
countryCode) != B_OK) {
delete fIcon;
fIcon = NULL;
}
}
LanguageListItem::LanguageListItem(const LanguageListItem& other)
:
BStringItem(other.Text()),
fID(other.ID()),
fCode(other.Code()),
fIcon(NULL)
fID(other.fID),
fCode(other.fCode)
{
if (other.fIcon != NULL)
fIcon = new BBitmap(*other.fIcon);
}
LanguageListItem::~LanguageListItem()
{
delete fIcon;
}
void
LanguageListItem::DrawItem(BView* owner, BRect frame, bool complete)
{
rgb_color kHighlight = {140, 140, 140, 0};
rgb_color kBlack = {0, 0, 0, 0};
DrawItemWithTextOffset(owner, frame, complete, 0);
}
void
LanguageListItem::DrawItemWithTextOffset(BView* owner, BRect frame,
bool complete, float textOffset)
{
static rgb_color kHighlight = {140, 140, 140, 0};
static rgb_color kBlack = {0, 0, 0, 0};
if (IsSelected() || complete) {
rgb_color color;
@@ -90,41 +83,81 @@ LanguageListItem::DrawItem(BView* owner, BRect frame, bool complete)
owner->SetHighColor(kBlack);
else {
owner->SetHighColor(tint_color(owner->LowColor(), B_DARKEN_3_TINT));
text += " [";
text += B_TRANSLATE("already chosen");
text += "]";
text << " [" << B_TRANSLATE("already chosen") << "]";
}
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->MovePenTo(frame.left + kLeftInset + textOffset,
frame.top + BaselineOffset());
owner->DrawString(text.String());
}
// Draw the icon
frame.left = frame.right - kFlagWidth;
BRect iconFrame(frame);
iconFrame.Set(iconFrame.left, iconFrame.top + 1, iconFrame.left + kFlagWidth - 2,
iconFrame.top + kFlagWidth - 1);
if (fIcon != NULL && fIcon->IsValid()) {
owner->SetDrawingMode(B_OP_OVER);
owner->DrawBitmap(fIcon, iconFrame);
owner->SetDrawingMode(B_OP_COPY);
}
// #pragma mark -
LanguageListItemWithFlag::LanguageListItemWithFlag(const char* text,
const char* id, const char* languageCode, const char* countryCode)
:
LanguageListItem(text, id, languageCode),
fCountryCode(countryCode),
fIcon(NULL)
{
}
LanguageListItemWithFlag::LanguageListItemWithFlag(
const LanguageListItemWithFlag& other)
:
LanguageListItem(other),
fCountryCode(other.fCountryCode),
fIcon(other.fIcon != NULL ? new BBitmap(*other.fIcon) : NULL)
{
}
LanguageListItemWithFlag::~LanguageListItemWithFlag()
{
delete fIcon;
}
void
LanguageListItem::Update(BView* owner, const BFont* font)
LanguageListItemWithFlag::Update(BView* owner, const BFont* font)
{
BStringItem::Update(owner, font);
SetWidth(Width() + kFlagWidth);
LanguageListItem::Update(owner, font);
float iconSize = Height();
SetWidth(Width() + iconSize + 4);
if (fCountryCode.IsEmpty())
return;
fIcon = new(std::nothrow) BBitmap(BRect(0, 0, iconSize - 1, iconSize - 1),
B_RGBA32);
if (fIcon != NULL && BLocaleRoster::Default()->GetFlagIconForCountry(fIcon,
fCountryCode.String()) != B_OK) {
delete fIcon;
fIcon = NULL;
}
}
void
LanguageListItemWithFlag::DrawItem(BView* owner, BRect frame, bool complete)
{
if (fIcon == NULL || !fIcon->IsValid()) {
DrawItemWithTextOffset(owner, frame, complete, 0);
return;
}
float iconSize = fIcon->Bounds().Width();
DrawItemWithTextOffset(owner, frame, complete, iconSize + 4);
BRect iconFrame(frame.left + kLeftInset, frame.top,
frame.left + kLeftInset + iconSize - 1, frame.top + iconSize - 1);
owner->SetDrawingMode(B_OP_OVER);
owner->DrawBitmap(fIcon, iconFrame);
owner->SetDrawingMode(B_OP_COPY);
}
+26 -5
View File
@@ -20,10 +20,9 @@
class LanguageListItem : public BStringItem {
public:
LanguageListItem(const char* text,
const char* id, const char* langCode,
const char* countryCode = NULL);
LanguageListItem(const LanguageListItem& other);
virtual ~LanguageListItem();
const char* id, const char* languageCode);
LanguageListItem(
const LanguageListItem& other);
const BString& ID() const { return fID; }
const BString& Code() const { return fCode; }
@@ -31,11 +30,33 @@ public:
virtual void DrawItem(BView* owner, BRect frame,
bool complete = false);
virtual void Update(BView* owner, const BFont* font);
protected:
void DrawItemWithTextOffset(BView* owner,
BRect frame, bool complete,
float textOffset);
private:
BString fID;
BString fCode;
};
class LanguageListItemWithFlag : public LanguageListItem {
public:
LanguageListItemWithFlag(const char* text,
const char* id, const char* languageCode,
const char* countryCode = NULL);
LanguageListItemWithFlag(
const LanguageListItemWithFlag& other);
virtual ~LanguageListItemWithFlag();
virtual void Update(BView* owner, const BFont* font);
virtual void DrawItem(BView* owner, BRect frame,
bool complete = false);
private:
BString fCountryCode;
BBitmap* fIcon;
};
+44 -37
View File
@@ -98,7 +98,7 @@ LocaleWindow::LocaleWindow()
if (BLocaleRoster::Default()->GetAvailableLanguages(&availableLanguages)
== B_OK) {
BString currentID;
LanguageListItem* lastAddedCountryItem = NULL;
LanguageListItem* currentToplevelItem = NULL;
for (int i = 0; availableLanguages.FindString("language", i, &currentID)
== B_OK; i++) {
@@ -119,20 +119,23 @@ LocaleWindow::LocaleWindow()
}
}
LanguageListItem* item = new LanguageListItem(name,
currentID.String(), currentLanguage.Code(),
currentLanguage.CountryCode());
if (currentLanguage.IsCountrySpecific()
&& lastAddedCountryItem != NULL
&& lastAddedCountryItem->Code() == item->Code()) {
fLanguageListView->AddUnder(item, lastAddedCountryItem);
LanguageListItem* item;
if (currentLanguage.IsCountrySpecific()) {
item = new LanguageListItemWithFlag(name, currentID.String(),
currentLanguage.Code(), currentLanguage.CountryCode());
} else {
// This is a language variant, add it at top-level
item = new LanguageListItem(name, currentID.String(),
currentLanguage.Code());
}
if (currentLanguage.IsCountrySpecific()
&& currentToplevelItem != NULL
&& currentToplevelItem->Code() == item->Code()) {
fLanguageListView->AddUnder(item, currentToplevelItem);
} else {
// This is a generic language, add it at top-level
fLanguageListView->AddItem(item);
if (!currentLanguage.IsCountrySpecific()) {
item->SetExpanded(false);
lastAddedCountryItem = item;
}
item->SetExpanded(false);
currentToplevelItem = item;
}
}
@@ -181,38 +184,42 @@ LocaleWindow::LocaleWindow()
new BMessage(kMsgConventionsSelection));
// get all available formatting conventions (by language)
BFormattingConventions defaultConventions;
BLocale::Default()->GetFormattingConventions(&defaultConventions);
BString conventionID;
BFormattingConventions initialConventions;
BLocale::Default()->GetFormattingConventions(&initialConventions);
BString conventionsID;
fInitialConventionsItem = NULL;
LanguageListItem* lastAddedConventionsItem = NULL;
LanguageListItem* currentToplevelItem = NULL;
for (int i = 0;
availableLanguages.FindString("language", i, &conventionID) == B_OK;
availableLanguages.FindString("language", i, &conventionsID) == B_OK;
i++) {
BFormattingConventions convention(conventionID);
BString conventionName;
convention.GetName(conventionName);
BFormattingConventions conventions(conventionsID);
BString conventionsName;
conventions.GetName(conventionsName);
LanguageListItem* item = new LanguageListItem(conventionName,
conventionID, convention.LanguageCode(), convention.CountryCode());
if (!strcmp(conventionID, "en_US"))
LanguageListItem* item;
if (conventions.AreCountrySpecific()) {
item = new LanguageListItemWithFlag(conventionsName, conventionsID,
conventions.LanguageCode(), conventions.CountryCode());
} else {
item = new LanguageListItem(conventionsName, conventionsID,
conventions.LanguageCode());
}
if (!strcmp(conventionsID, "en_US"))
fDefaultConventionsItem = item;
if (conventionID.FindFirst('_') >= 0
&& lastAddedConventionsItem != NULL
&& lastAddedConventionsItem->Code() == item->Code()) {
if (!strcmp(conventionID, defaultConventions.ID())) {
fConventionsListView->Expand(lastAddedConventionsItem);
if (conventions.AreCountrySpecific()
&& currentToplevelItem != NULL
&& currentToplevelItem->Code() == item->Code()) {
if (!strcmp(conventionsID, initialConventions.ID())) {
fConventionsListView->Expand(currentToplevelItem);
fInitialConventionsItem = item;
}
fConventionsListView->AddUnder(item, lastAddedConventionsItem);
fConventionsListView->AddUnder(item, currentToplevelItem);
} 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()))
item->SetExpanded(false);
currentToplevelItem = item;
if (!strcmp(conventionsID, initialConventions.ID()))
fInitialConventionsItem = item;
}
}
@@ -419,7 +426,7 @@ LocaleWindow::MessageReceived(BMessage* message)
{
MutableLocaleRoster::Default()->SetFilesystemTranslationPreferred(
fFilesystemTranslationCheckbox->Value());
BAlert* alert = new BAlert(B_TRANSLATE("Locale"),
B_TRANSLATE("Deskbar and Tracker need to be restarted for this "
"change to take effect. Would you like to restart them now?"),
@@ -430,7 +437,7 @@ LocaleWindow::MessageReceived(BMessage* message)
NULL, be_app));
break;
}
default:
BWindow::MessageReceived(message);
break;