diff options
author | yusukes@google.com <yusukes@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-05 11:41:38 +0000 |
---|---|---|
committer | yusukes@google.com <yusukes@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-05 11:41:38 +0000 |
commit | a58663cc43b9362a1121c54a157f5f922b7e353d (patch) | |
tree | c23edb80e5456e2f91ba15e5a8df246564a69e3b | |
parent | 4ae5be984f290428bc2ae86361024fe9c86a4752 (diff) | |
download | chromium_src-a58663cc43b9362a1121c54a157f5f922b7e353d.zip chromium_src-a58663cc43b9362a1121c54a157f5f922b7e353d.tar.gz chromium_src-a58663cc43b9362a1121c54a157f5f922b7e353d.tar.bz2 |
Use "preload_engines" pref on Chrome side to save the list of active IMEs (2nd try).
Original review: http://codereview.chromium.org/1576010
BUG=crosbug.com/488
TEST=manual
TBR=satorux
Review URL: http://codereview.chromium.org/1606010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@43608 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/chromeos/options/language_config_view.cc | 295 | ||||
-rw-r--r-- | chrome/browser/chromeos/options/language_config_view.h | 68 |
2 files changed, 239 insertions, 124 deletions
diff --git a/chrome/browser/chromeos/options/language_config_view.cc b/chrome/browser/chromeos/options/language_config_view.cc index 51bd685..6a2bf51 100644 --- a/chrome/browser/chromeos/options/language_config_view.cc +++ b/chrome/browser/chromeos/options/language_config_view.cc @@ -14,7 +14,10 @@ #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros/language_library.h" #include "chrome/browser/chromeos/options/language_hangul_config_view.h" +#include "chrome/browser/chromeos/preferences.h" #include "chrome/browser/language_combobox_model.h" +#include "chrome/common/notification_type.h" +#include "chrome/common/pref_names.h" #include "gfx/font.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" @@ -33,8 +36,7 @@ using views::GridLayout; namespace { // Creates the LanguageHangulConfigView. The function is used to create -// the object via a function pointer. See also -// InitInputMethodConfigViewMap(). +// the object via a function pointer. See also InitInputMethodConfigViewMap(). views::DialogDelegate* CreateLanguageHangulConfigView(Profile* profile) { return new LanguageHangulConfigView(profile); } @@ -138,17 +140,8 @@ class AddLanguageView : public views::View, // Creates the language combobox model from the supported languages. LanguageComboboxModel* CreateLanguageComboboxModel() { - // GetSupportedLanguages() never return NULL. - scoped_ptr<InputLanguageList> supported_language_list( - CrosLibrary::Get()->GetLanguageLibrary()->GetSupportedLanguages()); - - std::set<std::string> language_set; - for (size_t i = 0; i < supported_language_list->size(); ++i) { - const InputLanguage& language = supported_language_list->at(i); - language_set.insert(language.language_code); - } - const std::vector<std::string> language_codes(language_set.begin(), - language_set.end()); + std::vector<std::string> language_codes; + parent_view_->GetSupportedLangageCodes(&language_codes); // LanguageComboboxModel sorts languages by their display names. return new LanguageComboboxModelWithOthers(NULL, language_codes); } @@ -170,40 +163,40 @@ class InputMethodButton : public views::NativeButton { public: InputMethodButton(views::ButtonListener* listener, const std::wstring& label, - const InputLanguage& language) + const std::string& language_id) : views::NativeButton(listener, label), - language_(language) { + language_id_(language_id) { } - const InputLanguage& language() const { - return language_; + const std::string& language_id() const { + return language_id_; } private: - InputLanguage language_; + std::string language_id_; DISALLOW_COPY_AND_ASSIGN(InputMethodButton); }; // This is a checkbox associated with input method information. class InputMethodCheckbox : public views::Checkbox { public: - explicit InputMethodCheckbox(const InputLanguage& language) - : views::Checkbox(UTF8ToWide(language.display_name)), - language_(language) { + InputMethodCheckbox( + const std::string& language_id, const std::string& display_name) + : views::Checkbox(UTF8ToWide(display_name)), + language_id_(language_id) { } - const InputLanguage& language() const { - return language_; + const std::string& language_id() const { + return language_id_; } private: - InputLanguage language_; + std::string language_id_; DISALLOW_COPY_AND_ASSIGN(InputMethodCheckbox); }; LanguageConfigView::LanguageConfigView(Profile* profile) - : profile_(profile), - language_library_(NULL), + : OptionsPageView(profile), root_container_(NULL), right_container_(NULL), add_language_button_(NULL), @@ -234,24 +227,21 @@ void LanguageConfigView::ButtonPressed( } else if (input_method_checkboxes_.count( static_cast<InputMethodCheckbox*>(sender)) > 0) { InputMethodCheckbox* checkbox = static_cast<InputMethodCheckbox*>(sender); - const InputLanguage& language = checkbox->language(); - if (!language_library_->SetLanguageActivated(language.category, - language.id, - checkbox->checked())) { - LOG(ERROR) << "Failed to SetLanguageActivated(" - << language.category << ", " << language.id << ", " - << checkbox->checked() << ")"; - // Revert the checkbox. - checkbox->SetChecked(!checkbox->checked()); + const std::string language_id = checkbox->language_id(); + if (language_id == "USA") { + // For the time being, we don't allow users to disable "USA" layout. + // TODO(yusukes): remove this hack when XKB switcher gets ready. + checkbox->SetChecked(true); + } else { + SetLanguageActivated(language_id, checkbox->checked()); } } else if (input_method_buttons_.count( static_cast<InputMethodButton*>(sender)) > 0) { InputMethodButton* button = static_cast<InputMethodButton*>(sender); views::DialogDelegate* config_view = - CreateInputMethodConfigureView(button->language()); + CreateInputMethodConfigureView(button->language_id()); if (!config_view) { - DLOG(FATAL) << "Config view not found: " - << button->language().ToString(); + DLOG(FATAL) << "Config view not found: " << button->language_id(); return; } views::Window* window = views::Window::CreateChromeWindow( @@ -278,16 +268,8 @@ gfx::Size LanguageConfigView::GetPreferredSize() { IDS_FONTSLANG_DIALOG_HEIGHT_LINES)); } -void LanguageConfigView::ViewHierarchyChanged( - bool is_add, views::View* parent, views::View* child) { - // Can't init before we're inserted into a Container. - if (is_add && child == this) { - Init(); - } -} - views::View* LanguageConfigView::CreatePerLanguageConfigView( - const std::string& language_code) { + const std::string& target_language_code) { views::View* contents = new views::View; GridLayout* layout = new GridLayout(contents); contents->SetLayoutManager(layout); @@ -321,29 +303,30 @@ views::View* LanguageConfigView::CreatePerLanguageConfigView( layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); // Add input method names and configuration buttons. - scoped_ptr<InputLanguageList> supported_language_list( - CrosLibrary::Get()->GetLanguageLibrary()->GetSupportedLanguages()); input_method_buttons_.clear(); input_method_checkboxes_.clear(); - for (size_t i = 0; i < supported_language_list->size(); ++i) { - const InputLanguage& language = supported_language_list->at(i); - if (language.language_code == language_code) { + std::vector<std::string> language_ids; + GetSupportedLangageIDs(&language_ids); + for (size_t i = 0; i < language_ids.size(); ++i) { + const std::string& language_id = language_ids[i]; + const std::string language_code = GetLanguageCodeFromID(language_id); + const std::string display_name = GetDisplayNameFromID(language_id); + if (language_code == target_language_code) { layout->StartRow(0, kDoubleColumnSetId); - InputMethodCheckbox* checkbox = new InputMethodCheckbox(language); + InputMethodCheckbox* checkbox + = new InputMethodCheckbox(language_id, display_name); checkbox->set_listener(this); - checkbox->SetChecked( - language_library_->LanguageIsActivated(language.category, - language.id)); + checkbox->SetChecked(LanguageIsActivated(language_id)); layout->AddView(checkbox); input_method_checkboxes_.insert(checkbox); // Add "configure" button for the input method if we have a // configuration dialog for it. - if (input_method_config_view_map_.count(language.id) > 0) { + if (input_method_config_view_map_.count(language_id) > 0) { InputMethodButton* button = new InputMethodButton( this, l10n_util::GetString(IDS_OPTIONS_SETTINGS_LANGUAGES_CONFIGURE), - language); + language_id); layout->AddView(button); input_method_buttons_.insert(button); } @@ -359,6 +342,7 @@ void LanguageConfigView::OnSelectionChanged() { const int row = preferred_language_table_->GetFirstSelectedRow(); const std::string& language_code = preferred_language_codes_[row]; // TODO(satorux): For now, don't allow users to remove English. + // TODO(yusukes): "en" should be changed to "xkb:en" or something like that. if (language_code == "en") { remove_language_button_->SetEnabled(false); } else { @@ -395,12 +379,20 @@ int LanguageConfigView::RowCount() { return preferred_language_codes_.size(); } -void LanguageConfigView::Init() { - if (root_container_) return; // Already initialized. +void LanguageConfigView::InitControlLayout() { + // Initialize the maps. + InitLanguageIdMaps(); + InitInputMethodConfigViewMap(); + + preload_engines_.Init( + prefs::kLanguagePreloadEngines, profile()->GetPrefs(), this); + // TODO(yusukes): It might be safer to call GetActiveLanguages() cros API + // here and compare the result and preload_engines_GetValue(). If there's + // a discrepancy between IBus setting and Chrome prefs, we can resolve it + // by calling preload_engines_SetValue() here. + root_container_ = new views::View; AddChildView(root_container_); - // Initialize the pointer to the language library. - language_library_ = CrosLibrary::Get()->GetLanguageLibrary(); // Set up the layout manager for the root container. We'll place the // language table on the left, and the per language config on the right. @@ -420,9 +412,7 @@ void LanguageConfigView::Init() { root_layout->StartRow(1 /* expand */, kRootColumnSetId); // Initialize the language codes currently activated. - InitPreferredLanguageCodes(); - // Initialize the input method config view map. - InitInputMethodConfigViewMap(); + NotifyPrefChanged(); // Set up the container for the contents on the right. Just adds a // place holder here. This will get replaced in OnSelectionChanged(). @@ -440,27 +430,24 @@ void LanguageConfigView::Init() { preferred_language_table_->SelectRow(0); } -void LanguageConfigView::InitPreferredLanguageCodes() { - scoped_ptr<InputLanguageList> active_language_list( - language_library_->GetActiveLanguages()); - - for (size_t i = 0; i < active_language_list->size(); ++i) { - const InputLanguage& language = active_language_list->at(i); - // Add the language if any input language is activated. - if (std::find(preferred_language_codes_.begin(), - preferred_language_codes_.end(), - language.language_code) == - preferred_language_codes_.end()) { - preferred_language_codes_.push_back(language.language_code); - } - } -} - void LanguageConfigView::InitInputMethodConfigViewMap() { input_method_config_view_map_["hangul"] = CreateLanguageHangulConfigView; } +void LanguageConfigView::InitLanguageIdMaps() { + // GetSupportedLanguages() never return NULL. + scoped_ptr<InputLanguageList> supported_language_list( + CrosLibrary::Get()->GetLanguageLibrary()->GetSupportedLanguages()); + for (size_t i = 0; i < supported_language_list->size(); ++i) { + const InputLanguage& language = supported_language_list->at(i); + id_to_language_code_map_.insert( + std::make_pair(language.id, language.language_code)); + id_to_display_name_map_.insert( + std::make_pair(language.id, language.display_name)); + } +} + views::View* LanguageConfigView::CreateContentsOnLeft() { views::View* contents = new views::View; GridLayout* layout = new GridLayout(contents); @@ -519,53 +506,150 @@ void LanguageConfigView::OnAddLanguage(const std::string& language_code) { if (std::find(preferred_language_codes_.begin(), preferred_language_codes_.end(), language_code) == preferred_language_codes_.end()) { + // Activate the first input language associated with the language. We have + // to call this before the OnItemsAdded() call below so the checkbox for + // the first input language gets checked. + std::vector<std::string> language_ids; + GetSupportedLangageIDs(&language_ids); + for (size_t i = 0; i < language_ids.size(); ++i) { + if (GetLanguageCodeFromID(language_ids[i]) == language_code) { + SetLanguageActivated(language_ids[i], true); + break; + } + } + // Append the language to the list of language codes. preferred_language_codes_.push_back(language_code); // Update the language table accordingly. preferred_language_table_->OnItemsAdded(RowCount() - 1, 1); preferred_language_table_->SelectRow(RowCount() - 1); - - // Activate the first input language associated with the language. - scoped_ptr<InputLanguageList> supported_language_list( - language_library_->GetSupportedLanguages()); - for (size_t i = 0; i < supported_language_list->size(); ++i) { - const InputLanguage& language = supported_language_list->at(i); - if (language.language_code == language_code) { - language_library_->SetLanguageActivated( - language.category, language.id, true); - break; - } - } } } void LanguageConfigView::DeactivateInputLanguagesFor( const std::string& language_code) { - scoped_ptr<InputLanguageList> active_language_list( - language_library_->GetActiveLanguages()); - - for (size_t i = 0; i < active_language_list->size(); ++i) { - const InputLanguage& language = active_language_list->at(i); - if (language.language_code == language_code) { - language_library_->SetLanguageActivated( - language.category, language.id, false); + std::vector<std::string> language_ids; + GetSupportedLangageIDs(&language_ids); + for (size_t i = 0; i < language_ids.size(); ++i) { + if (GetLanguageCodeFromID(language_ids[i]) == language_code) { + SetLanguageActivated(language_ids[i], false); + // Do not break; here in order to disable all engines that belong to + // |language_code|. } } + // Switch back to the US English. - language_library_->ChangeLanguage(chromeos::LANGUAGE_CATEGORY_XKB, "USA"); + // TODO(yusukes): what if "USA" is not active? + CrosLibrary::Get()->GetLanguageLibrary()->ChangeLanguage( + chromeos::LANGUAGE_CATEGORY_XKB, "USA"); } views::DialogDelegate* LanguageConfigView::CreateInputMethodConfigureView( - const InputLanguage& language) { + const std::string& language_id) { InputMethodConfigViewMap::const_iterator iter = - input_method_config_view_map_.find(language.id); + input_method_config_view_map_.find(language_id); if (iter != input_method_config_view_map_.end()) { CreateDialogDelegateFunction function = iter->second; - return function(profile_); + return function(profile()); } return NULL; } +void LanguageConfigView::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if (type == NotificationType::PREF_CHANGED) { + NotifyPrefChanged(); + } +} + +void LanguageConfigView::SetLanguageActivated( + const std::string& language_id, bool activated) { + DCHECK(!language_id.empty()); + std::vector<std::string> language_ids; + GetActiveLanguageIDs(&language_ids); + + std::set<std::string> id_set(language_ids.begin(), language_ids.end()); + if (activated) { + // Add |id| if it's not already added. + id_set.insert(language_id); + } else { + id_set.erase(language_id); + } + + // Update Chrome's preference. + std::vector<std::string> new_language_ids(id_set.begin(), id_set.end()); + preload_engines_.SetValue(UTF8ToWide(JoinString(new_language_ids, ','))); +} + +bool LanguageConfigView::LanguageIsActivated(const std::string& language_id) { + std::vector<std::string> language_ids; + GetActiveLanguageIDs(&language_ids); + return (std::find(language_ids.begin(), language_ids.end(), language_id) != + language_ids.end()); +} + +void LanguageConfigView::GetActiveLanguageIDs( + std::vector<std::string>* out_language_ids) { + const std::wstring value = preload_engines_.GetValue(); + out_language_ids->clear(); + SplitString(WideToUTF8(value), ',', out_language_ids); +} + +void LanguageConfigView::GetSupportedLangageIDs( + std::vector<std::string>* out_language_ids) const { + out_language_ids->clear(); + std::map<std::string, std::string>::const_iterator iter; + for (iter = id_to_language_code_map_.begin(); + iter != id_to_language_code_map_.end(); + ++iter) { + out_language_ids->push_back(iter->first); + } +} + +void LanguageConfigView::GetSupportedLangageCodes( + std::vector<std::string>* out_language_codes) const { + std::set<std::string> language_code_set; + std::map<std::string, std::string>::const_iterator iter; + for (iter = id_to_language_code_map_.begin(); + iter != id_to_language_code_map_.end(); + ++iter) { + language_code_set.insert(iter->second); + } + out_language_codes->clear(); + out_language_codes->assign( + language_code_set.begin(), language_code_set.end()); +} + +std::string LanguageConfigView::GetLanguageCodeFromID( + const std::string& language_id) const { + std::map<std::string, std::string>::const_iterator iter + = id_to_language_code_map_.find(language_id); + return (iter == id_to_language_code_map_.end()) ? "" : iter->second; +} + +std::string LanguageConfigView::GetDisplayNameFromID( + const std::string& language_id) const { + std::map<std::string, std::string>::const_iterator iter + = id_to_display_name_map_.find(language_id); + return (iter == id_to_display_name_map_.end()) ? "" : iter->second; +} + +void LanguageConfigView::NotifyPrefChanged() { + std::vector<std::string> language_ids; + GetActiveLanguageIDs(&language_ids); + + std::set<std::string> language_code_set; + for (size_t i = 0; i < language_ids.size(); ++i) { + const std::string language_code = GetLanguageCodeFromID(language_ids[i]); + language_code_set.insert(language_code); + } + + preferred_language_codes_.clear(); + preferred_language_codes_.assign( + language_code_set.begin(), language_code_set.end()); +} + std::wstring LanguageConfigView::MaybeRewriteLanguageName( const std::wstring& language_name) { // "t" is used as the language code for input methods that don't fall @@ -577,5 +661,4 @@ std::wstring LanguageConfigView::MaybeRewriteLanguageName( return language_name; } - } // namespace chromeos diff --git a/chrome/browser/chromeos/options/language_config_view.h b/chrome/browser/chromeos/options/language_config_view.h index 0604e99..2a1b932 100644 --- a/chrome/browser/chromeos/options/language_config_view.h +++ b/chrome/browser/chromeos/options/language_config_view.h @@ -11,7 +11,8 @@ #include <vector> #include "app/table_model.h" -#include "chrome/browser/chromeos/cros/language_library.h" +#include "chrome/browser/pref_member.h" +#include "chrome/browser/views/options/options_page_view.h" #include "views/controls/button/native_button.h" #include "views/controls/label.h" #include "views/controls/table/table_view2.h" @@ -30,7 +31,7 @@ class LanguageConfigView : public TableModel, public views::ButtonListener, public views::DialogDelegate, public views::TableViewObserver, - public views::View { + public OptionsPageView { public: explicit LanguageConfigView(Profile* profile); virtual ~LanguageConfigView(); @@ -47,9 +48,6 @@ class LanguageConfigView : public TableModel, // views::View overrides: virtual void Layout(); virtual gfx::Size GetPreferredSize(); - virtual void ViewHierarchyChanged(bool is_add, - views::View* parent, - views::View* child); // views::TableViewObserver overrides: virtual void OnSelectionChanged(); @@ -66,6 +64,18 @@ class LanguageConfigView : public TableModel, // Invoked when a language is added from the add button. void OnAddLanguage(const std::string& language_code); + // OptionsPageView overrides. + virtual void InitControlLayout(); + + // NotificationObserver overrides. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // Gets the list of supported language codes like "en" and "ja". + void GetSupportedLangageCodes( + std::vector<std::string>* out_language_codes) const; + // Rewrites the language name and returns the modified version if // necessary. Otherwise, returns the given language name as is. // In particular, this rewrites the special language name used for input @@ -74,16 +84,12 @@ class LanguageConfigView : public TableModel, const std::wstring& language_name); private: - // Initializes the view. - void Init(); - - // Initializes the preferred language table codes based on the active - // input languages. - void InitPreferredLanguageCodes(); - // Initializes the input method config view. void InitInputMethodConfigViewMap(); + // Initialize id_to_{code,display_name}_map_ member variables. + void InitLanguageIdMaps(); + // Creates the contents on the left, including the language table. views::View* CreateContentsOnLeft(); @@ -93,16 +99,38 @@ class LanguageConfigView : public TableModel, // Deactivates the input languages for the given language code. void DeactivateInputLanguagesFor(const std::string& language_code); - // Creates the input method config view based on the given |language|. + // Creates the input method config view based on the given |language_id|. // Returns NULL if the config view is not found. views::DialogDelegate* CreateInputMethodConfigureView( - const InputLanguage& language); + const std::string& language_id); + + // Activates or deactivates an IME whose ID is |language_id|. + void SetLanguageActivated(const std::string& language_id, bool activated); - // The profile object. Does not take ownership of the object. - Profile* profile_; + // Returns true if an IME of |language_id| is activated. + bool LanguageIsActivated(const std::string& language_id); + + // Gets the list of active IME IDs like "pinyin" and "m17n:ar:kbd". + void GetActiveLanguageIDs(std::vector<std::string>* out_language_ids); + + // Gets the list of supported IME IDs like "pinyin" and "m17n:ar:kbd". + void GetSupportedLangageIDs(std::vector<std::string>* out_language_ids) const; + + // Converts a language ID to a language code of the IME. Returns "" when + // |language_id| is unknown. + // Example: "hangul" => "ko" + std::string GetLanguageCodeFromID(const std::string& language_id) const; + + // Converts a language ID to a display name of the IME. Returns "" when + // |language_id| is unknown. + // Examples: "pinyin" => "Pinyin" + // "m17n:ar:kbd" => "kbd (m17n)" + std::string GetDisplayNameFromID(const std::string& language_id) const; + + // Callback for |preload_engines_| pref updates. Initializes the preferred + // language codes based on the updated pref value. + void NotifyPrefChanged(); - // The language library interface. - LanguageLibrary* language_library_; // The codes of the preferred languages. std::vector<std::string> preferred_language_codes_; // The map of the input language id to a pointer to the function for @@ -123,6 +151,10 @@ class LanguageConfigView : public TableModel, views::NativeButton* remove_language_button_; views::TableView2* preferred_language_table_; + StringPrefMember preload_engines_; + std::map<std::string, std::string> id_to_language_code_map_; + std::map<std::string, std::string> id_to_display_name_map_; + DISALLOW_COPY_AND_ASSIGN(LanguageConfigView); }; |