* 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:
@@ -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
|
||||||
@@ -28,29 +26,37 @@ enum script_direction {
|
|||||||
|
|
||||||
|
|
||||||
class BLanguage {
|
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"
|
|
||||||
const char* Code();
|
|
||||||
bool IsCountry();
|
|
||||||
|
|
||||||
uint8 Direction() const;
|
// ISO-639 language code, e.g. "en", "de"
|
||||||
|
const char* Code() const;
|
||||||
|
const char* Country() const;
|
||||||
|
const char* Variant() const;
|
||||||
|
const char* ID() const;
|
||||||
|
|
||||||
// see definitions below
|
bool IsCountrySpecific() const;
|
||||||
const char *GetString(uint32 id) const;
|
bool IsVariant() const;
|
||||||
|
|
||||||
private:
|
uint8 Direction() const;
|
||||||
friend class BLocaleRoster;
|
|
||||||
|
|
||||||
BLanguage(const char *language);
|
// see definitions below
|
||||||
void Default();
|
const char* GetString(uint32 id) const;
|
||||||
|
|
||||||
char *fStrings[B_NUM_LANGUAGE_STRINGS];
|
private:
|
||||||
uint8 fDirection;
|
friend class BLocaleRoster;
|
||||||
icu_4_2::Locale* fICULocale;
|
|
||||||
|
BLanguage(const char *language);
|
||||||
|
void Default();
|
||||||
|
|
||||||
|
private:
|
||||||
|
char* fStrings[B_NUM_LANGUAGE_STRINGS];
|
||||||
|
uint8 fDirection;
|
||||||
|
icu_4_2::Locale* fICULocale;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _LANGUAGE_H_ */
|
|
||||||
|
#endif // _LANGUAGE_H_
|
||||||
|
|||||||
@@ -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 *);
|
||||||
|
|||||||
@@ -80,10 +80,7 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -123,10 +120,11 @@ 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;
|
|
||||||
|
name.Truncate(0);
|
||||||
preferredLanguage.FindString("language", 0, &appLanguage);
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
@@ -47,7 +74,7 @@ typedef BCatalogAddOn *(*CreateCatalogFunc)(const char *name,
|
|||||||
|
|
||||||
typedef BCatalogAddOn *(*InstantiateEmbeddedCatalogFunc)(
|
typedef BCatalogAddOn *(*InstantiateEmbeddedCatalogFunc)(
|
||||||
entry_ref *appOrAddOnRef);
|
entry_ref *appOrAddOnRef);
|
||||||
|
|
||||||
typedef status_t (*GetAvailableLanguagesFunc)(BMessage*, const char*,
|
typedef status_t (*GetAvailableLanguagesFunc)(BMessage*, const char*,
|
||||||
const char*, int32);
|
const char*, int32);
|
||||||
|
|
||||||
@@ -211,7 +238,7 @@ RosterData::RosterData()
|
|||||||
Locale::setDefault(icuLocale,icuError);
|
Locale::setDefault(icuLocale,icuError);
|
||||||
assert(icuError == U_ZERO_ERROR);
|
assert(icuError == U_ZERO_ERROR);
|
||||||
fPreferredLanguages.RemoveName("language");
|
fPreferredLanguages.RemoveName("language");
|
||||||
for (int i = 0; settingsMessage.FindString("language", i,
|
for (int i = 0; settingsMessage.FindString("language", i,
|
||||||
&langName) == B_OK; i++) {
|
&langName) == B_OK; i++) {
|
||||||
fPreferredLanguages.AddString("language", langName);
|
fPreferredLanguages.AddString("language", langName);
|
||||||
}
|
}
|
||||||
@@ -310,7 +337,7 @@ RosterData::InitializeCatalogAddOns()
|
|||||||
priority = -1;
|
priority = -1;
|
||||||
if (node.ReadAttr(kPriorityAttr, B_INT8_TYPE, 0,
|
if (node.ReadAttr(kPriorityAttr, B_INT8_TYPE, 0,
|
||||||
&priority, sizeof(int8)) <= 0) {
|
&priority, sizeof(int8)) <= 0) {
|
||||||
// add-on has no priority-attribute yet, so we load it
|
// add-on has no priority-attribute yet, so we load it
|
||||||
// to fetch the priority from the corresponding
|
// to fetch the priority from the corresponding
|
||||||
// symbol...
|
// symbol...
|
||||||
BString fullAddOnPath(addOnFolderName);
|
BString fullAddOnPath(addOnFolderName);
|
||||||
@@ -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,17 +475,23 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BLocaleRoster::SetDefaultCountry(BCountry * newDefault) const
|
BLocaleRoster::SetDefaultCountry(BCountry* newDefault) const
|
||||||
{
|
{
|
||||||
gRosterData.fCountryCodeName = newDefault->Code();
|
gRosterData.fCountryCodeName = newDefault->Code();
|
||||||
newDefault->DateFormat(gRosterData.fCountryDateFormat, true);
|
newDefault->DateFormat(gRosterData.fCountryDateFormat, true);
|
||||||
@@ -491,7 +499,7 @@ BLocaleRoster::SetDefaultCountry(BCountry * newDefault) const
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BLocaleRoster::GetPreferredLanguages(BMessage *languages) const
|
BLocaleRoster::GetPreferredLanguages(BMessage* languages) const
|
||||||
{
|
{
|
||||||
if (!languages)
|
if (!languages)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -548,7 +556,7 @@ BLocaleRoster::GetInstalledCatalogs(BMessage * languageList, const char* sigPatt
|
|||||||
{
|
{
|
||||||
if (languageList == NULL)
|
if (languageList == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
int32 count = gRosterData.fCatalogAddOnInfos.CountItems();
|
int32 count = gRosterData.fCatalogAddOnInfos.CountItems();
|
||||||
for (int32 i = 0; i < count; ++i) {
|
for (int32 i = 0; i < count; ++i) {
|
||||||
BCatalogAddOnInfo *info
|
BCatalogAddOnInfo *info
|
||||||
@@ -556,11 +564,11 @@ BLocaleRoster::GetInstalledCatalogs(BMessage * languageList, const char* sigPatt
|
|||||||
|
|
||||||
if (!info->MakeSureItsLoaded() || !info->fLanguagesFunc)
|
if (!info->MakeSureItsLoaded() || !info->fLanguagesFunc)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
info->fLanguagesFunc(languageList, sigPattern, langPattern,
|
info->fLanguagesFunc(languageList, sigPattern, langPattern,
|
||||||
fingerprint);
|
fingerprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -51,10 +67,8 @@ LanguageListItem::~LanguageListItem()
|
|||||||
void
|
void
|
||||||
LanguageListItem::DrawItem(BView* owner, BRect frame, bool complete)
|
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;
|
||||||
@@ -64,33 +78,43 @@ 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());
|
||||||
|
|
||||||
frame.left += 4;
|
frame.left += 4;
|
||||||
BRect iconFrame(frame);
|
BRect iconFrame(frame);
|
||||||
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);
|
||||||
owner->SetHighColor(kBlack);
|
|
||||||
|
BString text = Text();
|
||||||
|
if (IsEnabled())
|
||||||
|
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,302 +195,141 @@ 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)
|
||||||
// create drag message
|
return false;
|
||||||
BMessage msg('DRAG');
|
|
||||||
msg.AddPointer("list", (void*)(this));
|
|
||||||
// first selection round, consider only superitems
|
|
||||||
int32 index;
|
|
||||||
for (int32 i = 0; (index = FullListCurrentSelection(i)) >= 0; i++) {
|
|
||||||
BListItem* item = FullListItemAt(index);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// figure out drag rect
|
// create drag message
|
||||||
float width = Bounds().Width();
|
BMessage message = *fDragMessage;
|
||||||
BRect dragRect(0.0, 0.0, width, -1.0);
|
message.AddPointer("listview", this);
|
||||||
// figure out, how many items fit into our bitmap
|
|
||||||
bool fade = false;
|
for (int32 i = 0;; i++) {
|
||||||
int32 numItems;
|
int32 index = FullListCurrentSelection(i);
|
||||||
int32 currIndex;
|
if (index < 0)
|
||||||
BListItem* item;
|
break;
|
||||||
for (numItems = 0;
|
|
||||||
msg.FindInt32("index", numItems, &currIndex) == B_OK
|
message.AddInt32("index", index);
|
||||||
&& (item = FullListItemAt(currIndex)) != NULL; numItems++) {
|
}
|
||||||
dragRect.bottom += ceilf(item->Height()) + 1.0;
|
|
||||||
if (dragRect.Height() > MAX_DRAG_HEIGHT) {
|
// figure out drag rect
|
||||||
fade = true;
|
|
||||||
dragRect.bottom = MAX_DRAG_HEIGHT;
|
BRect dragRect(0.0, 0.0, Bounds().Width(), -1.0);
|
||||||
numItems++;
|
int32 numItems = 0;
|
||||||
break;
|
bool fade = false;
|
||||||
}
|
|
||||||
|
// figure out, how many items fit into our bitmap
|
||||||
|
for (int32 i = 0, index; message.FindInt32("index", i, &index) == B_OK;
|
||||||
|
i++) {
|
||||||
|
BListItem* item = FullListItemAt(index);
|
||||||
|
if (item == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
dragRect.bottom += ceilf(item->Height()) + 1.0;
|
||||||
|
numItems++;
|
||||||
|
|
||||||
|
if (dragRect.Height() > MAX_DRAG_HEIGHT) {
|
||||||
|
dragRect.bottom = MAX_DRAG_HEIGHT;
|
||||||
|
fade = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
BBitmap* dragBitmap = new BBitmap(dragRect, B_RGB32, true);
|
}
|
||||||
if (dragBitmap && dragBitmap->IsValid()) {
|
|
||||||
BView* v = new BView(dragBitmap->Bounds(), "helper", B_FOLLOW_NONE,
|
|
||||||
B_WILL_DRAW);
|
|
||||||
dragBitmap->AddChild(v);
|
|
||||||
dragBitmap->Lock();
|
|
||||||
BRect itemBounds(dragRect) ;
|
|
||||||
itemBounds.bottom = 0.0;
|
|
||||||
// let all selected items, that fit into our drag_bitmap, draw
|
|
||||||
for (int32 i = 0; i < numItems; i++) {
|
|
||||||
int32 index = msg.FindInt32("index", i);
|
|
||||||
LanguageListItem* item
|
|
||||||
= static_cast<LanguageListItem*>(FullListItemAt(index));
|
|
||||||
itemBounds.bottom = itemBounds.top + ceilf(item->Height());
|
|
||||||
if (itemBounds.bottom > dragRect.bottom)
|
|
||||||
itemBounds.bottom = dragRect.bottom;
|
|
||||||
item->DrawItem(v, itemBounds);
|
|
||||||
itemBounds.top = itemBounds.bottom + 1.0;
|
|
||||||
}
|
|
||||||
// make a black frame arround the edge
|
|
||||||
v->SetHighColor(0, 0, 0, 255);
|
|
||||||
v->StrokeRect(v->Bounds());
|
|
||||||
v->Sync();
|
|
||||||
|
|
||||||
uint8* bits = (uint8*)dragBitmap->Bits();
|
BBitmap* dragBitmap = new BBitmap(dragRect, B_RGB32, true);
|
||||||
int32 height = (int32)dragBitmap->Bounds().Height() + 1;
|
if (dragBitmap->IsValid()) {
|
||||||
int32 width = (int32)dragBitmap->Bounds().Width() + 1;
|
BView* view = new BView(dragBitmap->Bounds(), "helper", B_FOLLOW_NONE,
|
||||||
int32 bpr = dragBitmap->BytesPerRow();
|
B_WILL_DRAW);
|
||||||
|
dragBitmap->AddChild(view);
|
||||||
|
dragBitmap->Lock();
|
||||||
|
BRect itemBounds(dragRect) ;
|
||||||
|
itemBounds.bottom = 0.0;
|
||||||
|
// let all selected items, that fit into our drag_bitmap, draw
|
||||||
|
for (int32 i = 0; i < numItems; i++) {
|
||||||
|
int32 index = message.FindInt32("index", i);
|
||||||
|
LanguageListItem* item
|
||||||
|
= static_cast<LanguageListItem*>(FullListItemAt(index));
|
||||||
|
itemBounds.bottom = itemBounds.top + ceilf(item->Height());
|
||||||
|
if (itemBounds.bottom > dragRect.bottom)
|
||||||
|
itemBounds.bottom = dragRect.bottom;
|
||||||
|
item->DrawItem(view, itemBounds);
|
||||||
|
itemBounds.top = itemBounds.bottom + 1.0;
|
||||||
|
}
|
||||||
|
// make a black frame arround the edge
|
||||||
|
view->SetHighColor(0, 0, 0, 255);
|
||||||
|
view->StrokeRect(view->Bounds());
|
||||||
|
view->Sync();
|
||||||
|
|
||||||
if (fade) {
|
uint8* bits = (uint8*)dragBitmap->Bits();
|
||||||
for (int32 y = 0; y < height - ALPHA / 2; y++, bits += bpr) {
|
int32 height = (int32)dragBitmap->Bounds().Height() + 1;
|
||||||
uint8* line = bits + 3;
|
int32 width = (int32)dragBitmap->Bounds().Width() + 1;
|
||||||
for (uint8* end = line + 4 * width; line < end; line += 4)
|
int32 bpr = dragBitmap->BytesPerRow();
|
||||||
*line = ALPHA;
|
|
||||||
}
|
if (fade) {
|
||||||
for (int32 y = height - ALPHA / 2; y < height;
|
for (int32 y = 0; y < height - ALPHA / 2; y++, bits += bpr) {
|
||||||
y++, bits += bpr) {
|
uint8* line = bits + 3;
|
||||||
uint8* line = bits + 3;
|
for (uint8* end = line + 4 * width; line < end; line += 4)
|
||||||
for (uint8* end = line + 4 * width; line < end; line += 4)
|
*line = ALPHA;
|
||||||
*line = (height - y) << 1;
|
}
|
||||||
}
|
for (int32 y = height - ALPHA / 2; y < height;
|
||||||
} else {
|
y++, bits += bpr) {
|
||||||
for (int32 y = 0; y < height; y++, bits += bpr) {
|
uint8* line = bits + 3;
|
||||||
uint8* line = bits + 3;
|
for (uint8* end = line + 4 * width; line < end; line += 4)
|
||||||
for (uint8* end = line + 4 * width; line < end; line += 4)
|
*line = (height - y) << 1;
|
||||||
*line = ALPHA;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
dragBitmap->Unlock();
|
|
||||||
} else {
|
} else {
|
||||||
delete dragBitmap;
|
for (int32 y = 0; y < height; y++, bits += bpr) {
|
||||||
dragBitmap = NULL;
|
uint8* line = bits + 3;
|
||||||
|
for (uint8* end = line + 4 * width; line < end; line += 4)
|
||||||
|
*line = ALPHA;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (dragBitmap)
|
dragBitmap->Unlock();
|
||||||
DragMessage(&msg, dragBitmap, B_OP_ALPHA, BPoint(0.0, 0.0));
|
} else {
|
||||||
else
|
delete dragBitmap;
|
||||||
DragMessage(&msg, dragRect.OffsetToCopy(point), this);
|
dragBitmap = NULL;
|
||||||
|
|
||||||
success = true;
|
|
||||||
}
|
}
|
||||||
return success;
|
|
||||||
|
if (dragBitmap != NULL)
|
||||||
|
DragMessage(&message, dragBitmap, B_OP_ALPHA, BPoint(0.0, 0.0));
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
|
* Copyright 2005-2010, Axel Dörfler, axeld@pinc-software.de.
|
||||||
* 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 */
|
||||||
|
|||||||
@@ -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,34 +84,48 @@ 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, ¤tID)
|
||||||
i, ¤tLanguageCode) == 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(¤tLanguage,
|
be_locale_roster->GetLanguage(currentID.String(),
|
||||||
currentLanguageCode.String());
|
¤tLanguage);
|
||||||
|
|
||||||
currentLanguageName.Truncate(0);
|
BString name;
|
||||||
currentLanguage->GetName(¤tLanguageName);
|
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);
|
||||||
item->SetExpanded(false);
|
if (!currentLanguage->IsCountrySpecific()) {
|
||||||
lastAddedCountryItem = item;
|
item->SetExpanded(false);
|
||||||
|
lastAddedCountryItem = item;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete currentLanguage;
|
delete currentLanguage;
|
||||||
@@ -112,12 +133,12 @@ LocaleWindow::LocaleWindow()
|
|||||||
|
|
||||||
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));
|
||||||
.Add(tabView)
|
#if 0
|
||||||
.AddGroup(B_HORIZONTAL, 3)
|
fRevertButton = new BButton(B_TRANSLATE("Revert"),
|
||||||
.Add(button)
|
new BMessage(kMsgRevert));
|
||||||
.Add(fRevertButton)
|
fRevertButton->SetEnabled(false);
|
||||||
.AddGlue()
|
#endif
|
||||||
.End()
|
|
||||||
.SetInsets(5, 5, 5, 5)
|
|
||||||
.End();
|
|
||||||
|
|
||||||
|
BLayoutBuilder::Group<>(this, B_VERTICAL, spacing)
|
||||||
|
.Add(tabView)
|
||||||
|
.AddGroup(B_HORIZONTAL, spacing)
|
||||||
|
.Add(button)
|
||||||
|
// .Add(fRevertButton)
|
||||||
|
.AddGlue()
|
||||||
|
.End()
|
||||||
|
.SetInsets(spacing, spacing, spacing, spacing)
|
||||||
|
.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;
|
||||||
LanguageListItem* item = static_cast<LanguageListItem*>(
|
if (message->FindInt32("drop_index", &dropIndex) != B_OK)
|
||||||
fPreferredListView->FullListItemAt(index));
|
dropIndex = fPreferredListView->CountItems();
|
||||||
update.AddString("language", item->LanguageCode());
|
|
||||||
}
|
int32 index = 0;
|
||||||
index++;
|
for (int32 i = 0; message->FindInt32("index", i, &index) == B_OK;
|
||||||
|
i++) {
|
||||||
|
LanguageListItem* item = static_cast<LanguageListItem*>(
|
||||||
|
fLanguageListView->FullListItemAt(index));
|
||||||
|
_InsertPreferredLanguage(item, dropIndex++);
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
|
* Copyright 2005-2010, Axel Dörfler, axeld@pinc-software.de.
|
||||||
* 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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user