* Changed BLocaleRoster::GetLanguage() to a signature that makes more sense,

and looks more like the rest of the API.
* Also, it will now return an appropriate error code if the language couldn't
  be allocated (anything else than B_OK is an improvement :-)).
* Several changes in BLanguage:
  - GetName() now gets a BString reference, also
  - it now returns the name in its own language, ie. for German this would
    always be "deutsch", no matter the current language settings, and finally,
  - it now empties the string it gets before adding the name.
  - added GetTranslatedName() that behaves like the previous version.
  - added const where it made sense (ie. almost everywhere).
  - Code() now returns the code of the language only.
  - ID() now returns the full ID of this language, ie. including country,
    variant, and keywords if any.
  - added Country(), and Variant().
  - renamed IsCountry() to IsCountrySpecific().
  - added IsVariant().
* Cleaned up Language.h, minor cleanup in LocaleRoster.cpp.
* Removed the whole move item logic from LanguageListView; while this was not
  only spaghetti code, it doesn't make much sense in the first place.
* Instead of removing stuff from the left, and even worse, moving all countries
  for a language even if only one had been dragged, we now only mark the items
  that are already in the preferred list, and only those.
* Fixed various mixups of FullList*() vs. *() methods that could lead to things
  like bug #5896.
* Pressing the delete key in the preferred list view will now remove the
  language.
* Moved LocaleWindow specific message constants to LocaleWindow.cpp; Locale.h
  is supposed to contain application wide constants.
* The drop logic is now in LocaleWindow.
* We now make sure that each base language can only be in the list once.
* Lots of cleanup, even though I mostly replaced spaghettie code with different
  looking spaghettie code - still, I think things have slightly improved.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36727 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2010-05-07 17:38:40 +00:00
parent 8da96bede1
commit 96eaa02e8f
10 changed files with 728 additions and 532 deletions
+16 -10
View File
@@ -1,16 +1,14 @@
/* /*
** Copyright 2003, Haiku, Inc. * Copyright 2003-2010, Haiku, Inc.
** Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef _LANGUAGE_H_ #ifndef _LANGUAGE_H_
#define _LANGUAGE_H_ #define _LANGUAGE_H_
#include <LocaleStrings.h>
#include <String.h> #include <String.h>
#include <SupportDefs.h> #include <SupportDefs.h>
#include <LocaleStrings.h>
// We must not include the icu headers in there as it could mess up binary // We must not include the icu headers in there as it could mess up binary
@@ -31,11 +29,17 @@ class BLanguage {
public: public:
~BLanguage(); ~BLanguage();
// language name, e.g. "english", "deutsch" status_t GetName(BString& name) const;
status_t GetName(BString* name); status_t GetTranslatedName(BString& name) const;
// ISO-639 language code, e.g. "en", "de" // ISO-639 language code, e.g. "en", "de"
const char* Code(); const char* Code() const;
bool IsCountry(); const char* Country() const;
const char* Variant() const;
const char* ID() const;
bool IsCountrySpecific() const;
bool IsVariant() const;
uint8 Direction() const; uint8 Direction() const;
@@ -48,9 +52,11 @@ class BLanguage {
BLanguage(const char *language); BLanguage(const char *language);
void Default(); void Default();
private:
char* fStrings[B_NUM_LANGUAGE_STRINGS]; char* fStrings[B_NUM_LANGUAGE_STRINGS];
uint8 fDirection; uint8 fDirection;
icu_4_2::Locale* fICULocale; icu_4_2::Locale* fICULocale;
}; };
#endif /* _LANGUAGE_H_ */
#endif // _LANGUAGE_H_
+7 -3
View File
@@ -1,3 +1,7 @@
/*
* Copyright 2003-2010, Haiku. All rights reserved.
* Distributed under the terms of the MIT license.
*/
#ifndef _LOCALE_ROSTER_H_ #ifndef _LOCALE_ROSTER_H_
#define _LOCALE_ROSTER_H_ #define _LOCALE_ROSTER_H_
@@ -17,7 +21,7 @@ struct entry_ref;
namespace BPrivate { namespace BPrivate {
class EditableCatalog; class EditableCatalog;
}; }
enum { enum {
B_LOCALE_CHANGED = '_LCC', B_LOCALE_CHANGED = '_LCC',
@@ -25,7 +29,6 @@ enum {
class BLocaleRoster { class BLocaleRoster {
public: public:
BLocaleRoster(); BLocaleRoster();
~BLocaleRoster(); ~BLocaleRoster();
@@ -42,7 +45,8 @@ class BLocaleRoster {
status_t GetDefaultCountry(BCountry **) const; status_t GetDefaultCountry(BCountry **) const;
void SetDefaultCountry(BCountry *) const; void SetDefaultCountry(BCountry *) const;
status_t GetLanguage(BLanguage** language, BString languageCode) const; status_t GetLanguage(const char* languageCode,
BLanguage** _language) const;
status_t GetPreferredLanguages(BMessage *) const; status_t GetPreferredLanguages(BMessage *) const;
status_t SetPreferredLanguages(BMessage *); status_t SetPreferredLanguages(BMessage *);
+69 -17
View File
@@ -80,9 +80,6 @@ static const char *gBuiltInStrings[] = {
}; };
// #pragma mark -
BLanguage::BLanguage(const char* language) BLanguage::BLanguage(const char* language)
: :
fDirection(B_LEFT_TO_RIGHT) fDirection(B_LEFT_TO_RIGHT)
@@ -126,7 +123,8 @@ BLanguage::Direction() const
const char* const char*
BLanguage::GetString(uint32 id) const BLanguage::GetString(uint32 id) const
{ {
if (id < B_LANGUAGE_STRINGS_BASE || id > B_LANGUAGE_STRINGS_BASE + B_NUM_LANGUAGE_STRINGS) if (id < B_LANGUAGE_STRINGS_BASE
|| id > B_LANGUAGE_STRINGS_BASE + B_NUM_LANGUAGE_STRINGS)
return NULL; return NULL;
return fStrings[id - B_LANGUAGE_STRINGS_BASE]; return fStrings[id - B_LANGUAGE_STRINGS_BASE];
@@ -134,30 +132,84 @@ BLanguage::GetString(uint32 id) const
status_t status_t
BLanguage::GetName(BString* name) BLanguage::GetName(BString& name) const
{ {
BMessage preferredLanguage; UnicodeString string;
be_locale_roster->GetPreferredLanguages(&preferredLanguage); fICULocale->getDisplayName(*fICULocale, string);
BString appLanguage;
preferredLanguage.FindString("language", 0, &appLanguage); name.Truncate(0);
BStringByteSink converter(&name);
string.toUTF8(converter);
UnicodeString s;
fICULocale->getDisplayName(Locale(appLanguage), s);
BStringByteSink converter(name);
s.toUTF8(converter);
return B_OK; return B_OK;
} }
status_t
BLanguage::GetTranslatedName(BString& name) const
{
BMessage preferredLanguage;
be_locale_roster->GetPreferredLanguages(&preferredLanguage);
BString appLanguage;
preferredLanguage.FindString("language", 0, &appLanguage);
UnicodeString string;
fICULocale->getDisplayName(Locale(appLanguage), string);
name.Truncate(0);
BStringByteSink converter(&name);
string.toUTF8(converter);
return B_OK;
}
const char* const char*
BLanguage::Code() BLanguage::Code() const
{ {
return fICULocale->getLanguage(); return fICULocale->getLanguage();
} }
bool const char*
BLanguage::IsCountry() BLanguage::Country() const
{ {
return *(fICULocale->getCountry()) != '\0'; const char* country = fICULocale->getCountry();
if (country == NULL || country[0] == '\0')
return NULL;
return country;
}
const char*
BLanguage::Variant() const
{
const char* variant = fICULocale->getVariant();
if (variant == NULL || variant[0] == '\0')
return NULL;
return variant;
}
const char*
BLanguage::ID() const
{
return fICULocale->getName();
}
bool
BLanguage::IsCountrySpecific() const
{
return Country() != NULL;
}
bool
BLanguage::IsVariant() const
{
return Variant() != NULL;
} }
+38 -30
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2004, Haiku. All rights reserved. * Copyright 2003-2010, Haiku. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -37,8 +37,35 @@
#include <unicode/locid.h> #include <unicode/locid.h>
/*
* several attributes/resource-IDs used within the Locale Kit:
*/
static const char *kPriorityAttr = "ADDON:priority"; static const char *kPriorityAttr = "ADDON:priority";
const char *BLocaleRoster::kCatLangAttr = "BEOS:LOCALE_LANGUAGE";
// name of catalog language, lives in every catalog file
const char *BLocaleRoster::kCatSigAttr = "BEOS:LOCALE_SIGNATURE";
// catalog signature, lives in every catalog file
const char *BLocaleRoster::kCatFingerprintAttr = "BEOS:LOCALE_FINGERPRINT";
// catalog fingerprint, may live in catalog file
const char *BLocaleRoster::kCatManagerMimeType
= "application/x-vnd.Be.locale.catalog-manager";
// signature of catalog managing app
const char *BLocaleRoster::kCatEditorMimeType
= "application/x-vnd.Be.locale.catalog-editor";
// signature of catalog editor app
const char *BLocaleRoster::kEmbeddedCatAttr = "BEOS:LOCALE_EMBEDDED_CATALOG";
// attribute which contains flattened data of embedded catalog
// this may live in an app- or add-on-file
int32 BLocaleRoster::kEmbeddedCatResId = 0xCADA;
// a unique value used to identify the resource (=> embedded CAtalog DAta)
// which contains flattened data of embedded catalog.
// this may live in an app- or add-on-file
typedef BCatalogAddOn *(*InstantiateCatalogFunc)(const char *name, typedef BCatalogAddOn *(*InstantiateCatalogFunc)(const char *name,
const char *language, uint32 fingerprint); const char *language, uint32 fingerprint);
@@ -385,34 +412,9 @@ RosterData::CleanupCatalogAddOns()
} }
/* // #pragma mark - BLocaleRoster
* several attributes/resource-IDs used within the Locale Kit:
*/
const char *BLocaleRoster::kCatLangAttr = "BEOS:LOCALE_LANGUAGE";
// name of catalog language, lives in every catalog file
const char *BLocaleRoster::kCatSigAttr = "BEOS:LOCALE_SIGNATURE";
// catalog signature, lives in every catalog file
const char *BLocaleRoster::kCatFingerprintAttr = "BEOS:LOCALE_FINGERPRINT";
// catalog fingerprint, may live in catalog file
const char *BLocaleRoster::kCatManagerMimeType
= "application/x-vnd.Be.locale.catalog-manager";
// signature of catalog managing app
const char *BLocaleRoster::kCatEditorMimeType
= "application/x-vnd.Be.locale.catalog-editor";
// signature of catalog editor app
const char *BLocaleRoster::kEmbeddedCatAttr = "BEOS:LOCALE_EMBEDDED_CATALOG";
// attribute which contains flattened data of embedded catalog
// this may live in an app- or add-on-file
int32 BLocaleRoster::kEmbeddedCatResId = 0xCADA;
// a unique value used to identify the resource (=> embedded CAtalog DAta)
// which contains flattened data of embedded catalog.
// this may live in an app- or add-on-file
/*
* BLocaleRoster, the exported interface to the locale roster data:
*/
BLocaleRoster::BLocaleRoster() BLocaleRoster::BLocaleRoster()
{ {
} }
@@ -473,11 +475,17 @@ BLocaleRoster::GetDefaultCountry(BCountry **country) const
status_t status_t
BLocaleRoster::GetLanguage(BLanguage **language, BString languageCode) const BLocaleRoster::GetLanguage(const char* languageCode,
BLanguage** _language) const
{ {
if (!language) if (_language == NULL || languageCode == NULL || languageCode[0] == '\0')
return B_BAD_VALUE; return B_BAD_VALUE;
*language = new(std::nothrow) BLanguage(languageCode);
BLanguage* language = new(std::nothrow) BLanguage(languageCode);
if (language == NULL)
return B_NO_MEMORY;
*_language = language;
return B_OK; return B_OK;
} }
+3 -4
View File
@@ -9,16 +9,15 @@ Preference Locale :
Locale.cpp Locale.cpp
LocaleWindow.cpp LocaleWindow.cpp
TimeFormatSettingsView.cpp TimeFormatSettingsView.cpp
: be liblocale.so $(TARGET_LIBSTDC++) $(TARGET_LIBSUPC++) libicu-common.so : be liblocale.so $(TARGET_LIBSTDC++) $(TARGET_LIBSUPC++) libicu-common.so
libicu-data.so libshared.a libicu-data.so libshared.a
: Locale.rdef : Locale.rdef
; ;
DoCatalogs Locale # application name DoCatalogs Locale : x-vnd.Haiku-Locale :
: x-vnd.Haiku-Locale # app MIME signature LanguageListView.cpp
: # sources to extract the keys from
Locale.cpp Locale.cpp
LocaleWindow.cpp LocaleWindow.cpp
TimeFormatSettingsView.cpp TimeFormatSettingsView.cpp
; ;
+175 -239
View File
@@ -5,6 +5,7 @@
* Authors: * Authors:
* Stephan Aßmus <[email protected]> * Stephan Aßmus <[email protected]>
* Adrien Destugues <[email protected]> * Adrien Destugues <[email protected]>
* Axel Dörfler, [email protected]
* Oliver Tappe <[email protected]> * Oliver Tappe <[email protected]>
*/ */
@@ -17,31 +18,46 @@
#include <Bitmap.h> #include <Bitmap.h>
#include <Country.h> #include <Country.h>
#include <Catalog.h>
#include "Locale.h" #include <Window.h>
#define MAX_DRAG_HEIGHT 200.0 #define MAX_DRAG_HEIGHT 200.0
#define ALPHA 170 #define ALPHA 170
#define TEXT_OFFSET 5.0
#define TR_CONTEXT "LanguageListView"
LanguageListItem::LanguageListItem(const char* text, const char* code) LanguageListItem::LanguageListItem(const char* text, const char* id,
const char* code)
: :
BStringItem(text), BStringItem(text),
fLanguageCode(code) fID(id),
fCode(code)
{ {
// TODO: should probably keep the BCountry as a member of the class // TODO: should probably keep the BCountry as a member of the class
BCountry myCountry(code); BCountry country(id);
BRect bounds(0, 0, 15, 15);
fIcon = new(std::nothrow) BBitmap(bounds, B_RGBA32); fIcon = new(std::nothrow) BBitmap(BRect(0, 0, 15, 15), B_RGBA32);
if (fIcon && myCountry.GetIcon(fIcon) != B_OK) { if (fIcon != NULL && country.GetIcon(fIcon) != B_OK) {
delete fIcon; delete fIcon;
fIcon = NULL; fIcon = NULL;
} }
} }
LanguageListItem::LanguageListItem(const LanguageListItem& other)
:
BStringItem(other.Text()),
fID(other.ID()),
fCode(other.Code()),
fIcon(NULL)
{
if (other.fIcon != NULL)
fIcon = new BBitmap(*other.fIcon);
}
LanguageListItem::~LanguageListItem() LanguageListItem::~LanguageListItem()
{ {
delete fIcon; delete fIcon;
@@ -54,8 +70,6 @@ LanguageListItem::DrawItem(BView* owner, BRect frame, bool complete)
rgb_color kHighlight = {140, 140, 140, 0}; rgb_color kHighlight = {140, 140, 140, 0};
rgb_color kBlack = {0, 0, 0, 0}; rgb_color kBlack = {0, 0, 0, 0};
BRect r(frame);
if (IsSelected() || complete) { if (IsSelected() || complete) {
rgb_color color; rgb_color color;
if (IsSelected()) if (IsSelected())
@@ -64,7 +78,7 @@ LanguageListItem::DrawItem(BView* owner, BRect frame, bool complete)
color = owner->ViewColor(); color = owner->ViewColor();
owner->SetHighColor(color); owner->SetHighColor(color);
owner->SetLowColor(color); owner->SetLowColor(color);
owner->FillRect(r); owner->FillRect(frame);
owner->SetHighColor(kBlack); owner->SetHighColor(kBlack);
} else } else
owner->SetLowColor(owner->ViewColor()); owner->SetLowColor(owner->ViewColor());
@@ -74,23 +88,33 @@ LanguageListItem::DrawItem(BView* owner, BRect frame, bool complete)
iconFrame.Set(iconFrame.left, iconFrame.top + 1, iconFrame.left + 15, iconFrame.Set(iconFrame.left, iconFrame.top + 1, iconFrame.left + 15,
iconFrame.top + 16); iconFrame.top + 16);
if (fIcon && fIcon->IsValid()) { if (fIcon != NULL && fIcon->IsValid()) {
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);
} }
frame.left += 16 * (OutlineLevel() + 1); frame.left += 16 * (OutlineLevel() + 1);
BString text = Text();
if (IsEnabled())
owner->SetHighColor(kBlack); owner->SetHighColor(kBlack);
else {
owner->SetHighColor(tint_color(owner->LowColor(), B_DARKEN_3_TINT));
text += " (";
text += B_TRANSLATE("already chosen");
text += ")";
}
BFont font = be_plain_font; BFont font = be_plain_font;
font_height finfo; font_height finfo;
font.GetHeight(&finfo); font.GetHeight(&finfo);
owner->SetFont(&font); owner->SetFont(&font);
owner->MovePenTo(frame.left+8, frame.top + ((frame.Height() - (finfo.ascent // TODO: the position is unnecessarily complicated, and not correct either
+ finfo.descent + finfo.leading)) / 2) + (finfo.ascent owner->MovePenTo(frame.left + 8, frame.top
+ finfo.descent) - 1); + (frame.Height() - (finfo.ascent + finfo.descent + finfo.leading)) / 2
owner->DrawString(Text()); + (finfo.ascent + finfo.descent) - 1);
owner->DrawString(text.String());
} }
@@ -100,14 +124,66 @@ LanguageListItem::DrawItem(BView* owner, BRect frame, bool complete)
LanguageListView::LanguageListView(const char* name, list_view_type type) LanguageListView::LanguageListView(const char* name, list_view_type type)
: :
BOutlineListView(name, type), BOutlineListView(name, type),
fMsgPrefLanguagesChanged(new BMessage(kMsgPrefLanguagesChanged)) fDeleteMessage(NULL),
fDragMessage(NULL)
{ {
} }
LanguageListView::~LanguageListView() LanguageListView::~LanguageListView()
{ {
delete fMsgPrefLanguagesChanged; }
LanguageListItem*
LanguageListView::ItemForLanguageID(const char* id, int32* _index) const
{
for (int32 index = 0; index < FullListCountItems(); index++) {
LanguageListItem* item
= static_cast<LanguageListItem*>(FullListItemAt(index));
if (item->ID() == id) {
if (_index != NULL)
*_index = index;
return item;
}
}
return NULL;
}
LanguageListItem*
LanguageListView::ItemForLanguageCode(const char* code, int32* _index) const
{
for (int32 index = 0; index < FullListCountItems(); index++) {
LanguageListItem* item
= static_cast<LanguageListItem*>(FullListItemAt(index));
if (item->Code() == code) {
if (_index != NULL)
*_index = index;
return item;
}
}
return NULL;
}
void
LanguageListView::SetDeleteMessage(BMessage* message)
{
delete fDeleteMessage;
fDeleteMessage = message;
}
void
LanguageListView::SetDragMessage(BMessage* message)
{
delete fDragMessage;
fDragMessage = message;
} }
@@ -119,257 +195,96 @@ LanguageListView::AttachedToWindow()
} }
void
LanguageListView::MoveItems(BList& items, int32 index)
{
// TODO : only allow moving top level item around other top level
// or sublevels within the same top level
DeselectAll();
// collect all items that must be moved (adding subitems as necessary)
int32 count = items.CountItems();
BList itemsToBeMoved;
for (int32 i = 0; i < count; i++) {
BListItem* item = (BListItem*)items.ItemAt(i);
itemsToBeMoved.AddItem(item);
if (item->OutlineLevel() == 0) {
// add all subitems, as they need to be moved, too
int32 subItemCount = CountItemsUnder(item, true);
for (int subIndex = 0; subIndex < subItemCount ; subIndex++)
itemsToBeMoved.AddItem(ItemUnderAt(item, true, subIndex));
}
}
// now remove all the items backwards (in order to remove children before
// their parent), decreasing target index if we are removing items before
// it
count = itemsToBeMoved.CountItems();
for (int32 i = count - 1; i >= 0; i--) {
BListItem* item = (BListItem*)itemsToBeMoved.ItemAt(i);
int32 removeIndex = FullListIndexOf(item);
if (RemoveItem(item)) {
if (removeIndex < index)
index--;
}
}
// finally add all the items at the given index
for (int32 i = 0; i < count; i++) {
BListItem* item = (BListItem*)itemsToBeMoved.ItemAt(i);
if (AddItem(item, index))
index++;
else
delete item;
}
}
void void
LanguageListView::MessageReceived(BMessage* message) LanguageListView::MessageReceived(BMessage* message)
{ {
if (message->what == 'DRAG') { if (message->WasDropped() && _AcceptsDragMessage(message)) {
// Someone just dropped something on us // Someone just dropped something on us
LanguageListView* list = NULL; BMessage dragMessage(*message);
if (message->FindPointer("list", (void**)&list) == B_OK) { dragMessage.AddInt32("drop_index", fDropIndex);
// It comes from a list dragMessage.AddPointer("drop_target", this);
int32 count = CountItems();
if (fDropIndex < 0 || fDropIndex > count)
fDropIndex = count;
if (list == this) { Invoke(&dragMessage);
// It comes from ourselves : move the item around in the list
BList items;
int32 index;
for (int32 i = 0;
message->FindInt32("index", i, &index) == B_OK; i++) {
if (BListItem* item = FullListItemAt(index))
items.AddItem((void*)item);
}
if (items.CountItems() > 0) {
// There is something to move
LanguageListItem* parent = static_cast<LanguageListItem*>(
Superitem(static_cast<LanguageListItem*>(
items.FirstItem())));
if (parent) {
// item has a parent - it should then stay
// below it
if (Superitem(FullListItemAt(fDropIndex - 1)) == parent
|| FullListItemAt(fDropIndex - 1) == parent)
MoveItems(items, fDropIndex);
} else {
// item is top level and should stay so.
if (Superitem(FullListItemAt(fDropIndex - 1)) == NULL)
MoveItems(items, fDropIndex);
else {
int itemCount = CountItemsUnder(
FullListItemAt(fDropIndex), true);
MoveItems(items, FullListIndexOf(Superitem(
FullListItemAt(fDropIndex - 1))
+ itemCount));
}
}
}
fDropIndex = -1;
} else {
// It comes from another list : move it here
// ensure we always drop things at top-level and not
// in the middle of another outline
if (Superitem(FullListItemAt(fDropIndex))) {
// Item has a parent
fDropIndex = FullListIndexOf(Superitem(FullListItemAt(
fDropIndex)));
}
// Item is now a top level one - we must insert just below its
// last child
fDropIndex += CountItemsUnder(FullListItemAt(fDropIndex), true)
+ 1;
int32 indexCount;
type_code dummy;
if (message->GetInfo("index", &dummy, &indexCount) == B_OK) {
for (int32 i = indexCount - 1; i >= 0; i--) {
int32 index;
if (message->FindInt32("index", i, &index) == B_OK)
MoveItemFrom(list, index, fDropIndex);
}
}
fDropIndex = -1;
}
Invoke(fMsgPrefLanguagesChanged);
}
} else } else
BOutlineListView::MessageReceived(message); BOutlineListView::MessageReceived(message);
} }
void
LanguageListView::MoveItemFrom(BOutlineListView* origin, int32 index,
int32 dropSpot)
{
// Check that the node we are going to move is a top-level one.
// If not, we want its parent instead
LanguageListItem* itemToMove = static_cast<LanguageListItem*>(
origin->Superitem(origin->FullListItemAt(index)));
if (itemToMove == NULL) {
itemToMove = static_cast<LanguageListItem*>(
origin->FullListItemAt(index));
if (itemToMove == NULL)
return;
} else
index = origin->FullListIndexOf(itemToMove);
// collect all items that must be moved (adding subitems as necessary)
BList itemsToBeMoved;
itemsToBeMoved.AddItem(itemToMove);
// add all subitems, as they need to be moved, too
int32 subItemCount = origin->CountItemsUnder(itemToMove, true);
for (int32 subIndex = 0; subIndex < subItemCount; subIndex++) {
itemsToBeMoved.AddItem(origin->ItemUnderAt(itemToMove, true,
subIndex));
}
// now remove all items from origin in reverse order (to remove the children
// before the parent) ...
// TODO: using RemoveItem() on the parent will delete the subitems, which
// may be a bug, actually.
int32 itemCount = itemsToBeMoved.CountItems();
for (int32 i = itemCount - 1; i >= 0; i--)
origin->RemoveItem(index + i);
// ... and add all the items to this list
AddList(&itemsToBeMoved, dropSpot);
}
bool bool
LanguageListView::InitiateDrag(BPoint point, int32 index, bool) LanguageListView::InitiateDrag(BPoint point, int32 dragIndex,
bool /*wasSelected*/)
{ {
bool success = false; if (fDragMessage == NULL)
return false;
BListItem* item = FullListItemAt(CurrentSelection(0)); BListItem* item = FullListItemAt(CurrentSelection(0));
if (!item) { if (item == NULL) {
// workaround for a timing problem // workaround for a timing problem
Select(index); // TODO: this should support extending the selection
item = FullListItemAt(index); item = ItemAt(dragIndex);
Select(dragIndex);
} }
if (item) { if (item == NULL)
return false;
// create drag message // create drag message
BMessage msg('DRAG'); BMessage message = *fDragMessage;
msg.AddPointer("list", (void*)(this)); message.AddPointer("listview", this);
// first selection round, consider only superitems
int32 index; for (int32 i = 0;; i++) {
for (int32 i = 0; (index = FullListCurrentSelection(i)) >= 0; i++) { int32 index = FullListCurrentSelection(i);
BListItem* item = FullListItemAt(index); if (index < 0)
if (item == NULL)
return false;
if (item->OutlineLevel() == 0)
msg.AddInt32("index", index);
}
if (!msg.HasInt32("index")) {
// second selection round, consider only subitems of the same
// (i.e. the first) parent
BListItem* seenSuperItem = NULL;
for (int32 i = 0; (index = FullListCurrentSelection(i)) >= 0; i++) {
BListItem* item = FullListItemAt(index);
if (item == NULL)
return false;
if (item->OutlineLevel() != 0) {
BListItem* superItem = Superitem(item);
if (seenSuperItem == NULL)
seenSuperItem = superItem;
if (superItem == seenSuperItem)
msg.AddInt32("index", index);
else
break; break;
}
} message.AddInt32("index", index);
} }
// figure out drag rect // figure out drag rect
float width = Bounds().Width();
BRect dragRect(0.0, 0.0, width, -1.0); BRect dragRect(0.0, 0.0, Bounds().Width(), -1.0);
// figure out, how many items fit into our bitmap int32 numItems = 0;
bool fade = false; bool fade = false;
int32 numItems;
int32 currIndex; // figure out, how many items fit into our bitmap
BListItem* item; for (int32 i = 0, index; message.FindInt32("index", i, &index) == B_OK;
for (numItems = 0; i++) {
msg.FindInt32("index", numItems, &currIndex) == B_OK BListItem* item = FullListItemAt(index);
&& (item = FullListItemAt(currIndex)) != NULL; numItems++) { if (item == NULL)
break;
dragRect.bottom += ceilf(item->Height()) + 1.0; dragRect.bottom += ceilf(item->Height()) + 1.0;
if (dragRect.Height() > MAX_DRAG_HEIGHT) {
fade = true;
dragRect.bottom = MAX_DRAG_HEIGHT;
numItems++; numItems++;
if (dragRect.Height() > MAX_DRAG_HEIGHT) {
dragRect.bottom = MAX_DRAG_HEIGHT;
fade = true;
break; break;
} }
} }
BBitmap* dragBitmap = new BBitmap(dragRect, B_RGB32, true); BBitmap* dragBitmap = new BBitmap(dragRect, B_RGB32, true);
if (dragBitmap && dragBitmap->IsValid()) { if (dragBitmap->IsValid()) {
BView* v = new BView(dragBitmap->Bounds(), "helper", B_FOLLOW_NONE, BView* view = new BView(dragBitmap->Bounds(), "helper", B_FOLLOW_NONE,
B_WILL_DRAW); B_WILL_DRAW);
dragBitmap->AddChild(v); dragBitmap->AddChild(view);
dragBitmap->Lock(); dragBitmap->Lock();
BRect itemBounds(dragRect) ; BRect itemBounds(dragRect) ;
itemBounds.bottom = 0.0; itemBounds.bottom = 0.0;
// let all selected items, that fit into our drag_bitmap, draw // let all selected items, that fit into our drag_bitmap, draw
for (int32 i = 0; i < numItems; i++) { for (int32 i = 0; i < numItems; i++) {
int32 index = msg.FindInt32("index", i); int32 index = message.FindInt32("index", i);
LanguageListItem* item LanguageListItem* item
= static_cast<LanguageListItem*>(FullListItemAt(index)); = static_cast<LanguageListItem*>(FullListItemAt(index));
itemBounds.bottom = itemBounds.top + ceilf(item->Height()); itemBounds.bottom = itemBounds.top + ceilf(item->Height());
if (itemBounds.bottom > dragRect.bottom) if (itemBounds.bottom > dragRect.bottom)
itemBounds.bottom = dragRect.bottom; itemBounds.bottom = dragRect.bottom;
item->DrawItem(v, itemBounds); item->DrawItem(view, itemBounds);
itemBounds.top = itemBounds.bottom + 1.0; itemBounds.top = itemBounds.bottom + 1.0;
} }
// make a black frame arround the edge // make a black frame arround the edge
v->SetHighColor(0, 0, 0, 255); view->SetHighColor(0, 0, 0, 255);
v->StrokeRect(v->Bounds()); view->StrokeRect(view->Bounds());
v->Sync(); view->Sync();
uint8* bits = (uint8*)dragBitmap->Bits(); uint8* bits = (uint8*)dragBitmap->Bits();
int32 height = (int32)dragBitmap->Bounds().Height() + 1; int32 height = (int32)dragBitmap->Bounds().Height() + 1;
@@ -400,21 +315,21 @@ LanguageListView::InitiateDrag(BPoint point, int32 index, bool)
delete dragBitmap; delete dragBitmap;
dragBitmap = NULL; dragBitmap = NULL;
} }
if (dragBitmap)
DragMessage(&msg, dragBitmap, B_OP_ALPHA, BPoint(0.0, 0.0));
else
DragMessage(&msg, dragRect.OffsetToCopy(point), this);
success = true; if (dragBitmap != NULL)
} DragMessage(&message, dragBitmap, B_OP_ALPHA, BPoint(0.0, 0.0));
return success; else
DragMessage(&message, dragRect.OffsetToCopy(point), this);
return true;
} }
void void
LanguageListView::MouseMoved(BPoint where, uint32 transit, const BMessage* msg) LanguageListView::MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage)
{ {
if (msg && msg->what == 'DRAG') { if (dragMessage != NULL && _AcceptsDragMessage(dragMessage)) {
switch (transit) { switch (transit) {
case B_ENTERED_VIEW: case B_ENTERED_VIEW:
case B_INSIDE_VIEW: case B_INSIDE_VIEW:
@@ -455,5 +370,26 @@ LanguageListView::MouseMoved(BPoint where, uint32 transit, const BMessage* msg)
} }
} }
} else } else
BOutlineListView::MouseMoved(where, transit, msg); BOutlineListView::MouseMoved(where, transit, dragMessage);
}
void
LanguageListView::KeyDown(const char* bytes, int32 numBytes)
{
if (bytes[0] == B_DELETE && fDeleteMessage != NULL) {
Invoke(fDeleteMessage);
return;
}
BOutlineListView::KeyDown(bytes, numBytes);
}
bool
LanguageListView::_AcceptsDragMessage(const BMessage* message) const
{
LanguageListView* sourceView = NULL;
return message != NULL
&& message->FindPointer("listview", (void**)&sourceView) == B_OK;
} }
+29 -13
View File
@@ -5,6 +5,7 @@
* Authors: * Authors:
* Stephan Aßmus <[email protected]> * Stephan Aßmus <[email protected]>
* Adrien Destugues <[email protected]> * Adrien Destugues <[email protected]>
* Axel Dörfler, [email protected]
* Oliver Tappe <[email protected]> * Oliver Tappe <[email protected]>
*/ */
#ifndef LANGUAGE_LIST_VIEW_H #ifndef LANGUAGE_LIST_VIEW_H
@@ -19,15 +20,19 @@
class LanguageListItem : public BStringItem { class LanguageListItem : public BStringItem {
public: public:
LanguageListItem(const char* text, LanguageListItem(const char* text,
const char* code); const char* id, const char* code);
LanguageListItem(const LanguageListItem& other);
virtual ~LanguageListItem(); virtual ~LanguageListItem();
const BString& LanguageCode() { return fLanguageCode; } const BString& ID() const { return fID; }
void DrawItem(BView* owner, BRect frame, const BString& Code() const { return fCode; }
virtual void DrawItem(BView* owner, BRect frame,
bool complete = false); bool complete = false);
private: private:
BString fLanguageCode; BString fID;
BString fCode;
BBitmap* fIcon; BBitmap* fIcon;
}; };
@@ -38,18 +43,29 @@ public:
list_view_type type); list_view_type type);
virtual ~LanguageListView(); virtual ~LanguageListView();
bool InitiateDrag(BPoint point, int32 index, LanguageListItem* ItemForLanguageID(const char* code,
int32* _index = NULL) const;
LanguageListItem* ItemForLanguageCode(const char* code,
int32* _index = NULL) const;
void SetDeleteMessage(BMessage* message);
void SetDragMessage(BMessage* message);
virtual bool InitiateDrag(BPoint point, int32 index,
bool wasSelected); bool wasSelected);
void MouseMoved(BPoint where, uint32 transit, virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* msg); const BMessage* dragMessage);
void MoveItems(BList& items, int32 index); virtual void AttachedToWindow();
void MoveItemFrom(BOutlineListView* origin, int32 index, virtual void MessageReceived(BMessage* message);
int32 dropSpot = 0); virtual void KeyDown(const char* bytes, int32 numBytes);
void AttachedToWindow();
void MessageReceived (BMessage* message); private:
bool _AcceptsDragMessage(const BMessage* message) const;
private: private:
int32 fDropIndex; int32 fDropIndex;
BMessage* fMsgPrefLanguagesChanged; BMessage* fDeleteMessage;
BMessage* fDragMessage;
}; };
+1 -7
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2005-2009, Axel Dörfler, [email protected]. * Copyright 2005-2010, Axel Dörfler, [email protected].
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*/ */
#ifndef LOCALE_H #ifndef LOCALE_H
@@ -11,13 +11,7 @@
extern const char* kSignature; extern const char* kSignature;
static const uint32 kMsgCountrySelection = 'csel';
static const uint32 kMsgSettingsChanged = 'SeCh'; static const uint32 kMsgSettingsChanged = 'SeCh';
static const uint32 kMsgPrefLanguagesChanged = 'lang';
static const uint32 kMsgLangInvoked = 'laiv';
static const uint32 kMsgPrefLangInvoked = 'pliv';
static const uint32 kMsgDefaults = 'dflt';
static const uint32 kMsgRevert = 'revt';
#endif /* LOCALE_H */ #endif /* LOCALE_H */
+283 -112
View File
@@ -15,6 +15,7 @@
#include <Application.h> #include <Application.h>
#include <Button.h> #include <Button.h>
#include <Catalog.h> #include <Catalog.h>
#include <ControlLook.h>
#include <GroupLayout.h> #include <GroupLayout.h>
#include <LayoutBuilder.h> #include <LayoutBuilder.h>
#include <Locale.h> #include <Locale.h>
@@ -23,6 +24,7 @@
#include <ScrollView.h> #include <ScrollView.h>
#include <StringView.h> #include <StringView.h>
#include <TabView.h> #include <TabView.h>
#include <UnicodeChar.h>
#include <ICUWrapper.h> #include <ICUWrapper.h>
@@ -35,6 +37,18 @@
#define TR_CONTEXT "Locale Preflet Window" #define TR_CONTEXT "Locale Preflet Window"
static const uint32 kMsgLanguageInvoked = 'LaIv';
static const uint32 kMsgLanguageDragged = 'LaDr';
static const uint32 kMsgPreferredLanguageInvoked = 'PLIv';
static const uint32 kMsgPreferredLanguageDragged = 'PLDr';
static const uint32 kMsgPreferredLanguageDeleted = 'PLDl';
static const uint32 kMsgCountrySelection = 'csel';
static const uint32 kMsgDefaults = 'dflt';
static const uint32 kMsgRevert = 'revt';
static const uint32 kMsgPreferredLanguagesChanged = 'lang';
static int static int
compare_typed_list_items(const BListItem* _a, const BListItem* _b) compare_typed_list_items(const BListItem* _a, const BListItem* _b)
{ {
@@ -50,26 +64,19 @@ compare_typed_list_items(const BListItem* _a, const BListItem* _b)
LocaleWindow::LocaleWindow() LocaleWindow::LocaleWindow()
: :
BWindow(BRect(0, 0, 0, 0), "Locale", B_TITLED_WINDOW, B_NOT_RESIZABLE BWindow(BRect(0, 0, 0, 0), "Locale", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE
| B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS)
| B_QUIT_ON_WINDOW_CLOSE),
fMsgPrefLanguagesChanged(new BMessage(kMsgPrefLanguagesChanged))
{ {
BCountry* defaultCountry; BCountry* defaultCountry;
be_locale_roster->GetDefaultCountry(&defaultCountry); be_locale_roster->GetDefaultCountry(&defaultCountry);
SetLayout(new BGroupLayout(B_HORIZONTAL)); SetLayout(new BGroupLayout(B_HORIZONTAL));
BButton* button = new BButton(B_TRANSLATE("Defaults"), float spacing = be_control_look->DefaultItemSpacing();
new BMessage(kMsgDefaults));
fRevertButton = new BButton(B_TRANSLATE("Revert"),
new BMessage(kMsgRevert));
fRevertButton->SetEnabled(false);
BTabView* tabView = new BTabView("tabview"); BTabView* tabView = new BTabView("tabview");
BGroupView* languageTab = new BGroupView(B_TRANSLATE("Language"),
BView* languageTab = new BView(B_TRANSLATE("Language"), B_WILL_DRAW); B_HORIZONTAL, spacing);
languageTab->SetLayout(new BGroupLayout(B_VERTICAL, 0));
// first list: available languages // first list: available languages
fLanguageListView = new LanguageListView("available", fLanguageListView = new LanguageListView("available",
@@ -77,47 +84,61 @@ LocaleWindow::LocaleWindow()
BScrollView* scrollView = new BScrollView("scroller", fLanguageListView, BScrollView* scrollView = new BScrollView("scroller", fLanguageListView,
B_WILL_DRAW | B_FRAME_EVENTS, false, true); B_WILL_DRAW | B_FRAME_EVENTS, false, true);
fLanguageListView->SetInvocationMessage(new BMessage(kMsgLangInvoked)); fLanguageListView->SetInvocationMessage(new BMessage(kMsgLanguageInvoked));
fLanguageListView->SetDragMessage(new BMessage(kMsgLanguageDragged));
// Fill the language list from the LocaleRoster data // Fill the language list from the LocaleRoster data
BMessage installedLanguages; BMessage installedLanguages;
if (be_locale_roster->GetInstalledLanguages(&installedLanguages) == B_OK) { if (be_locale_roster->GetInstalledLanguages(&installedLanguages) == B_OK) {
BString currentLanguageCode; BString currentID;
BString currentLanguageName;
LanguageListItem* lastAddedCountryItem = NULL; LanguageListItem* lastAddedCountryItem = NULL;
for (int i = 0; installedLanguages.FindString("langs", for (int i = 0; installedLanguages.FindString("langs", i, &currentID)
i, &currentLanguageCode) == B_OK; i++) { == B_OK; i++) {
// Now get an human-readable, localized name for each language // Now get an human-readable, localized name for each language
BLanguage* currentLanguage; BLanguage* currentLanguage;
be_locale_roster->GetLanguage(&currentLanguage, be_locale_roster->GetLanguage(currentID.String(),
currentLanguageCode.String()); &currentLanguage);
currentLanguageName.Truncate(0); BString name;
currentLanguage->GetName(&currentLanguageName); currentLanguage->GetName(name);
LanguageListItem* item = new LanguageListItem(currentLanguageName, // TODO: as long as the app_server doesn't support font overlays,
currentLanguageCode.String()); // use the translated name if problematic characters are used...
if (currentLanguage->IsCountry()) { const char* string = name.String();
while (uint32 code = BUnicodeChar::FromUTF8(&string)) {
if (code > 1424) {
currentLanguage->GetTranslatedName(name);
break;
}
}
LanguageListItem* item = new LanguageListItem(name,
currentID.String(), currentLanguage->Code());
if (currentLanguage->IsCountrySpecific()
&& lastAddedCountryItem != NULL
&& lastAddedCountryItem->Code() == item->Code()) {
fLanguageListView->AddUnder(item, lastAddedCountryItem); fLanguageListView->AddUnder(item, lastAddedCountryItem);
} else { } else {
// This is a language without country, add it at top-level // This is a language variant, add it at top-level
fLanguageListView->AddItem(item); fLanguageListView->AddItem(item);
if (!currentLanguage->IsCountrySpecific()) {
item->SetExpanded(false); item->SetExpanded(false);
lastAddedCountryItem = item; lastAddedCountryItem = item;
} }
}
delete currentLanguage; delete currentLanguage;
} }
fLanguageListView->FullListSortItems(compare_typed_list_items); fLanguageListView->FullListSortItems(compare_typed_list_items);
} else { } else {
BAlert* myAlert = new BAlert("Error", BAlert* alert = new BAlert("Error",
B_TRANSLATE("Unable to find the available languages! You can't " B_TRANSLATE("Unable to find the available languages! You can't "
"use this preflet!"), "use this preflet!"),
B_TRANSLATE("OK"), NULL, NULL, B_TRANSLATE("OK"), NULL, NULL,
B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_STOP_ALERT); B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_STOP_ALERT);
myAlert->Go(); alert->Go();
} }
// Second list: active languages // Second list: active languages
@@ -126,40 +147,23 @@ LocaleWindow::LocaleWindow()
BScrollView* scrollViewEnabled = new BScrollView("scroller", BScrollView* scrollViewEnabled = new BScrollView("scroller",
fPreferredListView, B_WILL_DRAW | B_FRAME_EVENTS, false, true); fPreferredListView, B_WILL_DRAW | B_FRAME_EVENTS, false, true);
fPreferredListView->SetInvocationMessage(new BMessage(kMsgPrefLangInvoked)); fPreferredListView->SetInvocationMessage(
new BMessage(kMsgPreferredLanguageInvoked));
fPreferredListView->SetDeleteMessage(
new BMessage(kMsgPreferredLanguageDeleted));
fPreferredListView->SetDragMessage(
new BMessage(kMsgPreferredLanguageDragged));
// get the preferred languages from the Settings. Move them here from BLayoutBuilder::Group<>(languageTab)
// the other list. .AddGroup(B_VERTICAL, spacing)
BMessage msg;
be_locale_roster->GetPreferredLanguages(&msg);
BString langCode;
for (int index = 0; msg.FindString("language", index, &langCode) == B_OK;
index++) {
for (int listPos = 0; LanguageListItem* item
= static_cast<LanguageListItem*>
(fLanguageListView->FullListItemAt(listPos));
listPos++) {
if (langCode == item->LanguageCode()) {
// We found the item we were looking for, now move it to
// the other list along with all its children
static_cast<LanguageListView*>(fPreferredListView)
->MoveItemFrom(fLanguageListView,
fLanguageListView->FullListIndexOf(item),
fLanguageListView->CountItems());
}
}
}
languageTab->AddChild(BLayoutBuilder::Group<>(B_HORIZONTAL, 10)
.AddGroup(B_VERTICAL, 10)
.Add(new BStringView("", B_TRANSLATE("Available languages"))) .Add(new BStringView("", B_TRANSLATE("Available languages")))
.Add(scrollView) .Add(scrollView)
.End() .End()
.AddGroup(B_VERTICAL, 10) .AddGroup(B_VERTICAL, spacing)
.Add(new BStringView("", B_TRANSLATE("Preferred languages"))) .Add(new BStringView("", B_TRANSLATE("Preferred languages")))
.Add(scrollViewEnabled) .Add(scrollViewEnabled)
.End() .End()
.View()); .SetInsets(spacing, spacing, spacing, spacing);
BView* countryTab = new BView(B_TRANSLATE("Country"), B_WILL_DRAW); BView* countryTab = new BView(B_TRANSLATE("Country"), B_WILL_DRAW);
countryTab->SetLayout(new BGroupLayout(B_VERTICAL, 0)); countryTab->SetLayout(new BGroupLayout(B_VERTICAL, 0));
@@ -183,48 +187,56 @@ LocaleWindow::LocaleWindow()
countryFullName.toUTF8(sink); countryFullName.toUTF8(sink);
LanguageListItem* item LanguageListItem* item
= new LanguageListItem(string, currentLocale[index].getName()); = new LanguageListItem(string, currentLocale[index].getName(),
NULL);
listView->AddItem(item); listView->AddItem(item);
if (!strcmp(currentLocale[index].getName(), defaultCountry->Code())) if (!strcmp(currentLocale[index].getName(), defaultCountry->Code()))
listView->Select(listView->CountItems() - 1); listView->Select(listView->CountItems() - 1);
} }
// TODO: find a real solution intead of this hack // TODO: find a real solution intead of this hack
listView->SetExplicitMinSize(BSize(300, B_SIZE_UNSET)); listView->SetExplicitMinSize(
BSize(25 * be_plain_font->Size(), B_SIZE_UNSET));
fFormatView = new FormatView(defaultCountry); fFormatView = new FormatView(defaultCountry);
countryTab->AddChild(BLayoutBuilder::Group<>(B_HORIZONTAL, 5) countryTab->AddChild(BLayoutBuilder::Group<>(B_HORIZONTAL, spacing)
.AddGroup(B_VERTICAL, 3) .AddGroup(B_VERTICAL, 3)
.Add(scrollView) .Add(scrollView)
.End() .End()
.Add(fFormatView) .Add(fFormatView)
.View() .SetInsets(spacing, spacing, spacing, spacing));
);
listView->ScrollToSelection(); listView->ScrollToSelection();
tabView->AddTab(languageTab); tabView->AddTab(languageTab);
tabView->AddTab(countryTab); tabView->AddTab(countryTab);
BLayoutBuilder::Group<>(this) BButton* button = new BButton(B_TRANSLATE("Defaults"),
.AddGroup(B_VERTICAL, 3) new BMessage(kMsgDefaults));
#if 0
fRevertButton = new BButton(B_TRANSLATE("Revert"),
new BMessage(kMsgRevert));
fRevertButton->SetEnabled(false);
#endif
BLayoutBuilder::Group<>(this, B_VERTICAL, spacing)
.Add(tabView) .Add(tabView)
.AddGroup(B_HORIZONTAL, 3) .AddGroup(B_HORIZONTAL, spacing)
.Add(button) .Add(button)
.Add(fRevertButton) // .Add(fRevertButton)
.AddGlue() .AddGlue()
.End() .End()
.SetInsets(5, 5, 5, 5) .SetInsets(spacing, spacing, spacing, spacing)
.End(); .End();
_UpdatePreferredFromLocaleRoster();
CenterOnScreen(); CenterOnScreen();
} }
LocaleWindow::~LocaleWindow() LocaleWindow::~LocaleWindow()
{ {
delete fMsgPrefLanguagesChanged;
} }
@@ -233,30 +245,86 @@ LocaleWindow::MessageReceived(BMessage* message)
{ {
switch (message->what) { switch (message->what) {
case kMsgDefaults: case kMsgDefaults:
// TODO _Defaults();
break; break;
case kMsgRevert: case kMsgRevert:
// TODO // TODO
break; break;
case kMsgPrefLanguagesChanged: case kMsgLanguageDragged:
{ {
BMessage update(kMsgSettingsChanged); void* target = NULL;
int index = 0; if (message->FindPointer("drop_target", &target) != B_OK
while (index < fPreferredListView->FullListCountItems()) { || target != fPreferredListView)
// only include subitems : we can guess the superitem break;
// from them anyway
if (fPreferredListView->Superitem( // Add from available languages to preferred languages
fPreferredListView->FullListItemAt(index)) != NULL) { int32 dropIndex;
if (message->FindInt32("drop_index", &dropIndex) != B_OK)
dropIndex = fPreferredListView->CountItems();
int32 index = 0;
for (int32 i = 0; message->FindInt32("index", i, &index) == B_OK;
i++) {
LanguageListItem* item = static_cast<LanguageListItem*>( LanguageListItem* item = static_cast<LanguageListItem*>(
fPreferredListView->FullListItemAt(index)); fLanguageListView->FullListItemAt(index));
update.AddString("language", item->LanguageCode()); _InsertPreferredLanguage(item, dropIndex++);
} }
index++; break;
}
case kMsgLanguageInvoked:
{
int32 index = 0;
for (int32 i = 0; message->FindInt32("index", i, &index) == B_OK;
i++) {
LanguageListItem* item = static_cast<LanguageListItem*>(
fLanguageListView->ItemAt(index));
_InsertPreferredLanguage(item);
}
break;
}
case kMsgPreferredLanguageDragged:
{
void* target = NULL;
if (fPreferredListView->CountItems() == 1
|| message->FindPointer("drop_target", &target) != B_OK)
break;
if (target == fPreferredListView) {
// change ordering
int32 dropIndex = message->FindInt32("drop_index");
int32 index = 0;
if (message->FindInt32("index", &index) == B_OK
&& dropIndex != index) {
BListItem* item = fPreferredListView->RemoveItem(index);
if (dropIndex > index)
index--;
fPreferredListView->AddItem(item, dropIndex);
_PreferredLanguagesChanged();
}
break;
}
// supposed to fall through - remove item
}
case kMsgPreferredLanguageDeleted:
case kMsgPreferredLanguageInvoked:
{
if (fPreferredListView->CountItems() == 1)
break;
// Remove from preferred languages
int32 index = 0;
if (message->FindInt32("index", &index) == B_OK) {
delete fPreferredListView->RemoveItem(index);
_PreferredLanguagesChanged();
if (message->what == kMsgPreferredLanguageDeleted)
fPreferredListView->Select(index);
} }
fLanguageListView->FullListSortItems(compare_typed_list_items);
be_app_messenger.SendMessage(&update);
break; break;
} }
@@ -274,42 +342,14 @@ LocaleWindow::MessageReceived(BMessage* message)
LanguageListItem* item = static_cast<LanguageListItem*> LanguageListItem* item = static_cast<LanguageListItem*>
(countryList->ItemAt(countryList->CurrentSelection())); (countryList->ItemAt(countryList->CurrentSelection()));
BMessage newMessage(kMsgSettingsChanged); BMessage newMessage(kMsgSettingsChanged);
newMessage.AddString("country", item->LanguageCode()); newMessage.AddString("country", item->ID());
be_app_messenger.SendMessage(&newMessage); be_app_messenger.SendMessage(&newMessage);
BCountry* country = new BCountry(item->LanguageCode()); BCountry* country = new BCountry(item->ID());
fFormatView->SetCountry(country); fFormatView->SetCountry(country);
break; break;
} }
case kMsgLangInvoked:
{
int32 index = 0;
if (message->FindInt32("index", &index) == B_OK) {
LanguageListItem* listItem = static_cast<LanguageListItem*>
(fLanguageListView->RemoveItem(index));
fPreferredListView->AddItem(listItem);
fPreferredListView->Invoke(fMsgPrefLanguagesChanged);
}
break;
}
case kMsgPrefLangInvoked:
{
if (fPreferredListView->CountItems() == 1)
break;
int32 index = 0;
if (message->FindInt32("index", &index) == B_OK) {
LanguageListItem* listItem = static_cast<LanguageListItem*>
(fPreferredListView->RemoveItem(index));
fLanguageListView->AddItem(listItem);
fLanguageListView->FullListSortItems(compare_typed_list_items);
fPreferredListView->Invoke(fMsgPrefLanguagesChanged);
}
break;
}
default: default:
BWindow::MessageReceived(message); BWindow::MessageReceived(message);
break; break;
@@ -317,11 +357,142 @@ LocaleWindow::MessageReceived(BMessage* message)
} }
void bool
LocaleWindow::FrameMoved(BPoint newPosition) LocaleWindow::QuitRequested()
{ {
BMessage update(kMsgSettingsChanged); BMessage update(kMsgSettingsChanged);
update.AddPoint("window_location", newPosition); update.AddPoint("window_location", Frame().LeftTop());
be_app_messenger.SendMessage(&update); be_app_messenger.SendMessage(&update);
return true;
} }
void
LocaleWindow::_PreferredLanguagesChanged()
{
BMessage update(kMsgSettingsChanged);
int index = 0;
while (index < fPreferredListView->FullListCountItems()) {
// only include subitems: we can guess the superitem
// from them anyway
LanguageListItem* item = static_cast<LanguageListItem*>(
fPreferredListView->FullListItemAt(index));
if (item != NULL)
update.AddString("language", item->ID());
index++;
}
be_app_messenger.SendMessage(&update);
_EnableDisableLanguages();
}
void
LocaleWindow::_EnableDisableLanguages()
{
DisableUpdates();
for (int32 i = 0; i < fLanguageListView->FullListCountItems(); i++) {
LanguageListItem* item = static_cast<LanguageListItem*>(
fLanguageListView->FullListItemAt(i));
bool enable = fPreferredListView->ItemForLanguageID(item->ID()) == NULL;
if (item->IsEnabled() != enable) {
item->SetEnabled(enable);
int32 visibleIndex = fLanguageListView->IndexOf(item);
if (visibleIndex >= 0) {
if (!enable)
fLanguageListView->Deselect(visibleIndex);
fLanguageListView->InvalidateItem(visibleIndex);
}
}
}
EnableUpdates();
}
//! Get the preferred languages from the settings.
void
LocaleWindow::_UpdatePreferredFromLocaleRoster()
{
DisableUpdates();
// Delete all existing items
for (int32 index = fPreferredListView->CountItems(); index-- > 0; ) {
delete fPreferredListView->ItemAt(index);
}
fPreferredListView->MakeEmpty();
// Add new ones from the locale roster
BMessage preferredLanguages;
be_locale_roster->GetPreferredLanguages(&preferredLanguages);
BString languageID;
for (int32 index = 0; preferredLanguages.FindString("language", index,
&languageID) == B_OK; index++) {
int32 listIndex;
LanguageListItem* item
= fLanguageListView->ItemForLanguageID(languageID.String(),
&listIndex);
if (item != NULL) {
// We found the item we were looking for, now copy it to
// the other list
fPreferredListView->AddItem(new LanguageListItem(*item));
}
}
_EnableDisableLanguages();
EnableUpdates();
}
void
LocaleWindow::_InsertPreferredLanguage(LanguageListItem* item, int32 atIndex)
{
if (item == NULL || fPreferredListView->ItemForLanguageID(
item->ID().String()) != NULL)
return;
if (atIndex == -1)
atIndex = fPreferredListView->CountItems();
BLanguage* language = NULL;
be_locale_roster->GetLanguage(item->Code(), &language);
LanguageListItem* baseItem = NULL;
if (language != NULL) {
baseItem = fPreferredListView->ItemForLanguageCode(language->Code(),
&atIndex);
delete language;
}
DisableUpdates();
fPreferredListView->AddItem(new LanguageListItem(*item), atIndex);
// Replace other languages with the same base
if (baseItem != NULL) {
fPreferredListView->RemoveItem(baseItem);
delete baseItem;
}
_PreferredLanguagesChanged();
EnableUpdates();
}
void
LocaleWindow::_Defaults()
{
BMessage update(kMsgSettingsChanged);
update.AddString("language", "en");
be_app_messenger.SendMessage(&update);
_UpdatePreferredFromLocaleRoster();
}
+17 -7
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2005-2009, Axel Dörfler, [email protected]. * Copyright 2005-2010, Axel Dörfler, [email protected].
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*/ */
#ifndef LOCALE_WINDOW_H #ifndef LOCALE_WINDOW_H
@@ -8,27 +8,37 @@
#include <Window.h> #include <Window.h>
class BButton; class BButton;
class BListView; class BListView;
class BOutlineListView;
class FormatView; class FormatView;
class LanguageListItem;
class LanguageListView;
class LocaleWindow : public BWindow { class LocaleWindow : public BWindow {
public: public:
LocaleWindow(); LocaleWindow();
~LocaleWindow(); virtual ~LocaleWindow();
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
virtual void FrameMoved(BPoint newPosition); virtual bool QuitRequested();
private:
void _PreferredLanguagesChanged();
void _EnableDisableLanguages();
void _UpdatePreferredFromLocaleRoster();
void _InsertPreferredLanguage(LanguageListItem* item,
int32 atIndex = -1);
void _Defaults();
private: private:
BButton* fRevertButton; BButton* fRevertButton;
BOutlineListView* fLanguageListView; LanguageListView* fLanguageListView;
BOutlineListView* fPreferredListView; LanguageListView* fPreferredListView;
FormatView* fFormatView; FormatView* fFormatView;
BMessage* fMsgPrefLanguagesChanged;
}; };
#endif // LOCALE_WINDOW_H #endif // LOCALE_WINDOW_H