diff --git a/src/preferences/locale/LanguageListView.cpp b/src/preferences/locale/LanguageListView.cpp index 7c50c7e92d..55a11a6578 100644 --- a/src/preferences/locale/LanguageListView.cpp +++ b/src/preferences/locale/LanguageListView.cpp @@ -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); } diff --git a/src/preferences/locale/LanguageListView.h b/src/preferences/locale/LanguageListView.h index 4e78359293..8d0b0d9482 100644 --- a/src/preferences/locale/LanguageListView.h +++ b/src/preferences/locale/LanguageListView.h @@ -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; }; diff --git a/src/preferences/locale/LocaleWindow.cpp b/src/preferences/locale/LocaleWindow.cpp index be653de4b5..29b3180a6c 100644 --- a/src/preferences/locale/LocaleWindow.cpp +++ b/src/preferences/locale/LocaleWindow.cpp @@ -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, ¤tID) == 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;