diff options
Diffstat (limited to 'chrome/browser/chromeos/status/input_method_menu.cc')
-rw-r--r-- | chrome/browser/chromeos/status/input_method_menu.cc | 537 |
1 files changed, 0 insertions, 537 deletions
diff --git a/chrome/browser/chromeos/status/input_method_menu.cc b/chrome/browser/chromeos/status/input_method_menu.cc deleted file mode 100644 index 886458c..0000000 --- a/chrome/browser/chromeos/status/input_method_menu.cc +++ /dev/null @@ -1,537 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/chromeos/status/input_method_menu.h" - -#include <string> -#include <vector> - -#include "base/string_split.h" -#include "base/string_util.h" -#include "base/time.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chromeos/input_method/input_method_util.h" -#include "chrome/browser/chromeos/status/status_area_view_chromeos.h" -#include "content/public/browser/user_metrics.h" -#include "grit/generated_resources.h" -#include "grit/theme_resources.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/models/simple_menu_model.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/views/controls/menu/menu_model_adapter.h" -#include "ui/views/controls/menu/menu_runner.h" -#include "ui/views/controls/menu/submenu_view.h" -#include "ui/views/widget/widget.h" - -using content::UserMetricsAction; - -// The language menu consists of 3 parts (in this order): -// -// (1) input method names. The size of the list is always >= 1. -// (2) input method properties. This list might be empty. -// (3) "Customize language and input..." button. -// -// Example of the menu (Japanese): -// -// ============================== (border of the popup window) -// [ ] English (|index| in the following functions is 0) -// [*] Japanese -// [ ] Chinese (Simplified) -// ------------------------------ (separator) -// [*] Hiragana (index = 5, The property has 2 radio groups) -// [ ] Katakana -// [ ] HalfWidthKatakana -// [*] Roman -// [ ] Kana -// ------------------------------ (separator) -// Customize language and input...(index = 11) -// ============================== (border of the popup window) -// -// Example of the menu (Simplified Chinese): -// -// ============================== (border of the popup window) -// [ ] English -// [ ] Japanese -// [*] Chinese (Simplified) -// ------------------------------ (separator) -// Switch to full letter mode (The property has 2 command buttons) -// Switch to half punctuation mode -// ------------------------------ (separator) -// Customize language and input... -// ============================== (border of the popup window) -// - -namespace { - -// Constants to specify the type of items in |model_|. -enum { - COMMAND_ID_INPUT_METHODS = 0, // English, Chinese, Japanese, Arabic, ... - COMMAND_ID_IME_PROPERTIES, // Hiragana, Katakana, ... - COMMAND_ID_CUSTOMIZE_LANGUAGE, // "Customize language and input..." button. -}; - -// A group ID for IME properties starts from 0. We use the huge value for the -// input method list to avoid conflict. -const int kRadioGroupLanguage = 1 << 16; -const int kRadioGroupNone = -1; - -// Returns the language name for the given |language_code|. -string16 GetLanguageName(const std::string& language_code) { - const string16 language_name = l10n_util::GetDisplayNameForLocale( - language_code, g_browser_process->GetApplicationLocale(), true); - return language_name; -} - -} // namespace - -namespace chromeos { - -using input_method::InputMethodManager; - -//////////////////////////////////////////////////////////////////////////////// -// InputMethodMenu - -InputMethodMenu::InputMethodMenu() - : input_method_descriptors_( - InputMethodManager::GetInstance()->GetActiveInputMethods()), - model_(new ui::SimpleMenuModel(NULL)), - ALLOW_THIS_IN_INITIALIZER_LIST(input_method_menu_delegate_( - new views::MenuModelAdapter(this))), - input_method_menu_( - new views::MenuItemView(input_method_menu_delegate_.get())), - input_method_menu_runner_(new views::MenuRunner(input_method_menu_)), - minimum_input_method_menu_width_(0), - menu_alignment_(views::MenuItemView::TOPRIGHT) { - DCHECK(input_method_descriptors_.get() && - !input_method_descriptors_->empty()); - AddObserver(); -} - -InputMethodMenu::~InputMethodMenu() { - // RemoveObserver() is no-op if |this| object is already removed from the - // observer list - RemoveObserver(); -} - -//////////////////////////////////////////////////////////////////////////////// -// ui::MenuModel implementation: - -int InputMethodMenu::GetCommandIdAt(int index) const { - return index; -} - -bool InputMethodMenu::IsItemDynamicAt(int index) const { - // Menu content for the language button could change time by time. - return true; -} - -bool InputMethodMenu::GetAcceleratorAt( - int index, ui::Accelerator* accelerator) const { - // Views for Chromium OS does not support accelerators yet. - return false; -} - -bool InputMethodMenu::IsItemCheckedAt(int index) const { - DCHECK_GE(index, 0); - DCHECK(input_method_descriptors_.get()); - - if (IndexIsInInputMethodList(index)) { - const input_method::InputMethodDescriptor& input_method - = input_method_descriptors_->at(index); - return input_method == InputMethodManager::GetInstance()-> - GetCurrentInputMethod(); - } - - if (GetPropertyIndex(index, &index)) { - const input_method::InputMethodPropertyList& property_list - = InputMethodManager::GetInstance()->GetCurrentInputMethodProperties(); - return property_list.at(index).is_selection_item_checked; - } - - // Separator(s) or the "Customize language and input..." button. - return false; -} - -int InputMethodMenu::GetGroupIdAt(int index) const { - DCHECK_GE(index, 0); - - if (IndexIsInInputMethodList(index)) - return kRadioGroupLanguage; - - if (GetPropertyIndex(index, &index)) { - const input_method::InputMethodPropertyList& property_list - = InputMethodManager::GetInstance()->GetCurrentInputMethodProperties(); - return property_list.at(index).selection_item_id; - } - - return kRadioGroupNone; -} - -bool InputMethodMenu::HasIcons() const { - // We don't support icons on Chrome OS. - return false; -} - -bool InputMethodMenu::GetIconAt(int index, SkBitmap* icon) { - return false; -} - -ui::ButtonMenuItemModel* InputMethodMenu::GetButtonMenuItemAt( - int index) const { - return NULL; -} - -bool InputMethodMenu::IsEnabledAt(int index) const { - // Just return true so all input method names and input method propertie names - // could be clicked. - return true; -} - -ui::MenuModel* InputMethodMenu::GetSubmenuModelAt(int index) const { - // We don't use nested menus. - return NULL; -} - -void InputMethodMenu::HighlightChangedTo(int index) { - // Views for Chromium OS does not support this interface yet. -} - -void InputMethodMenu::MenuWillShow() { - // Views for Chromium OS does not support this interface yet. -} - -void InputMethodMenu::SetMenuModelDelegate(ui::MenuModelDelegate* delegate) { - // Not needed for current usage. -} - -int InputMethodMenu::GetItemCount() const { - if (!model_.get()) { - // Model is not constructed yet. This means that - // InputMethodMenu is being constructed. Return zero. - return 0; - } - return model_->GetItemCount(); -} - -ui::MenuModel::ItemType InputMethodMenu::GetTypeAt(int index) const { - DCHECK_GE(index, 0); - - if (IndexPointsToConfigureImeMenuItem(index)) { - return ui::MenuModel::TYPE_COMMAND; // "Customize language and input" - } - - if (IndexIsInInputMethodList(index)) - return ui::MenuModel::TYPE_RADIO; - - if (GetPropertyIndex(index, &index)) { - const input_method::InputMethodPropertyList& property_list - = InputMethodManager::GetInstance()->GetCurrentInputMethodProperties(); - if (property_list.at(index).is_selection_item) { - return ui::MenuModel::TYPE_RADIO; - } - return ui::MenuModel::TYPE_COMMAND; - } - - return ui::MenuModel::TYPE_SEPARATOR; -} - -string16 InputMethodMenu::GetLabelAt(int index) const { - DCHECK_GE(index, 0); - DCHECK(input_method_descriptors_.get()); - - // We use IDS_OPTIONS_SETTINGS_LANGUAGES_CUSTOMIZE here as the button - // opens the same dialog that is opened from the main options dialog. - if (IndexPointsToConfigureImeMenuItem(index)) { - return l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_CUSTOMIZE); - } - - string16 name; - if (IndexIsInInputMethodList(index)) { - name = GetTextForMenu(input_method_descriptors_->at(index)); - } else if (GetPropertyIndex(index, &index)) { - InputMethodManager* manager = InputMethodManager::GetInstance(); - const input_method::InputMethodPropertyList& property_list = - manager->GetCurrentInputMethodProperties(); - return manager->GetInputMethodUtil()->TranslateString( - property_list.at(index).label); - } - - return name; -} - -void InputMethodMenu::ActivatedAt(int index) { - DCHECK_GE(index, 0); - DCHECK(input_method_descriptors_.get()); - - if (IndexPointsToConfigureImeMenuItem(index)) { - OpenConfigUI(); - return; - } - - if (IndexIsInInputMethodList(index)) { - // Inter-IME switching. - const input_method::InputMethodDescriptor& input_method - = input_method_descriptors_->at(index); - InputMethodManager::GetInstance()->ChangeInputMethod( - input_method.id()); - content::RecordAction( - UserMetricsAction("LanguageMenuButton_InputMethodChanged")); - return; - } - - if (GetPropertyIndex(index, &index)) { - // Intra-IME switching (e.g. Japanese-Hiragana to Japanese-Katakana). - const input_method::InputMethodPropertyList& property_list - = InputMethodManager::GetInstance()->GetCurrentInputMethodProperties(); - const std::string key = property_list.at(index).key; - if (property_list.at(index).is_selection_item) { - // Radio button is clicked. - const int id = property_list.at(index).selection_item_id; - // First, deactivate all other properties in the same radio group. - for (int i = 0; i < static_cast<int>(property_list.size()); ++i) { - if (i != index && id == property_list.at(i).selection_item_id) { - InputMethodManager::GetInstance()->SetImePropertyActivated( - property_list.at(i).key, false); - } - } - // Then, activate the property clicked. - InputMethodManager::GetInstance()->SetImePropertyActivated( - key, true); - } else { - // Command button like "Switch to half punctuation mode" is clicked. - // We can always use "Deactivate" for command buttons. - InputMethodManager::GetInstance()->SetImePropertyActivated( - key, false); - } - return; - } - - LOG(ERROR) << "Unexpected index: " << index; -} - -//////////////////////////////////////////////////////////////////////////////// -// views::MenuButtonListener implementation: - -void InputMethodMenu::OnMenuButtonClicked(views::View* source, - const gfx::Point& point) { - PrepareForMenuOpen(); - - if (minimum_input_method_menu_width_ > 0) { - DCHECK(input_method_menu_->HasSubmenu()); - views::SubmenuView* submenu = input_method_menu_->GetSubmenu(); - submenu->set_minimum_preferred_width(minimum_input_method_menu_width_); - } - - gfx::Point screen_location; - views::View::ConvertPointToScreen(source, &screen_location); - gfx::Rect bounds(screen_location, source->size()); - if (input_method_menu_runner_->RunMenuAt( - source->GetWidget()->GetTopLevelWidget(), NULL, bounds, - menu_alignment_, views::MenuRunner::HAS_MNEMONICS) == - views::MenuRunner::MENU_DELETED) - return; -} - -//////////////////////////////////////////////////////////////////////////////// -// InputMethodManager::Observer implementation: - -void InputMethodMenu::InputMethodChanged( - InputMethodManager* manager, - const input_method::InputMethodDescriptor& current_input_method, - size_t num_active_input_methods) { - UpdateUIFromInputMethod(current_input_method, num_active_input_methods); -} - -void InputMethodMenu::PropertyListChanged( - InputMethodManager* manager, - const input_method::InputMethodPropertyList& current_ime_properties) { - // Usual order of notifications of input method change is: - // 1. RegisterProperties(empty) - // 2. RegisterProperties(list-of-new-properties) - // 3. GlobalInputMethodChanged - // However, due to the asynchronicity, we occasionally (but rarely) face to - // 1. RegisterProperties(empty) - // 2. GlobalInputMethodChanged - // 3. RegisterProperties(list-of-new-properties) - // this order. On this unusual case, we must rebuild the menu after the last - // RegisterProperties. For the other cases, no rebuild is needed. Actually - // it is better to be avoided. Otherwise users can sometimes observe the - // awkward clear-then-register behavior. - if (!current_ime_properties.empty()) { - const input_method::InputMethodDescriptor& input_method = - manager->GetCurrentInputMethod(); - size_t num_active_input_methods = manager->GetNumActiveInputMethods(); - UpdateUIFromInputMethod(input_method, num_active_input_methods); - } -} - -void InputMethodMenu::PrepareForMenuOpen() { - content::RecordAction(UserMetricsAction("LanguageMenuButton_Open")); - PrepareMenuModel(); -} - -void InputMethodMenu::PrepareMenuModel() { - input_method_descriptors_.reset(InputMethodManager::GetInstance()-> - GetActiveInputMethods()); - RebuildModel(); -} - -void InputMethodMenu::ActiveInputMethodsChanged( - InputMethodManager* manager, - const input_method::InputMethodDescriptor& current_input_method, - size_t num_active_input_methods) { - // Update the icon if active input methods are changed. See also - // comments in UpdateUI() in input_method_menu_button.cc. - UpdateUIFromInputMethod(current_input_method, num_active_input_methods); -} - -void InputMethodMenu::UpdateUIFromInputMethod( - const input_method::InputMethodDescriptor& input_method, - size_t num_active_input_methods) { - InputMethodManager* manager = InputMethodManager::GetInstance(); - const string16 name = manager->GetInputMethodUtil()-> - GetInputMethodShortName(input_method); - const string16 tooltip = GetTextForMenu(input_method); - UpdateUI(input_method.id(), name, tooltip, num_active_input_methods); -} - -void InputMethodMenu::RebuildModel() { - model_->Clear(); - string16 dummy_label = UTF8ToUTF16(""); - // Indicates if separator's needed before each section. - bool need_separator = false; - - if (!input_method_descriptors_->empty()) { - // We "abuse" the command_id and group_id arguments of AddRadioItem method. - // A COMMAND_ID_XXX enum value is passed as command_id, and array index of - // |input_method_descriptors_| or |property_list| is passed as group_id. - for (size_t i = 0; i < input_method_descriptors_->size(); ++i) { - model_->AddRadioItem(COMMAND_ID_INPUT_METHODS, dummy_label, i); - } - - need_separator = true; - } - - const input_method::InputMethodPropertyList& property_list - = InputMethodManager::GetInstance()->GetCurrentInputMethodProperties(); - if (!property_list.empty()) { - if (need_separator) { - model_->AddSeparator(); - } - for (size_t i = 0; i < property_list.size(); ++i) { - model_->AddRadioItem(COMMAND_ID_IME_PROPERTIES, dummy_label, i); - } - need_separator = true; - } - - if (ShouldSupportConfigUI()) { - // Note: We use AddSeparator() for separators, and AddRadioItem() for all - // other items even if an item is not actually a radio item. - if (need_separator) { - model_->AddSeparator(); - } - model_->AddRadioItem(COMMAND_ID_CUSTOMIZE_LANGUAGE, dummy_label, - 0 /* dummy */); - } - - // Rebuild the menu from the model. - input_method_menu_delegate_->BuildMenu(input_method_menu_); -} - -bool InputMethodMenu::IndexIsInInputMethodList(int index) const { - DCHECK_GE(index, 0); - DCHECK(model_.get()); - if (index >= model_->GetItemCount()) { - return false; - } - - return ((model_->GetTypeAt(index) == ui::MenuModel::TYPE_RADIO) && - (model_->GetCommandIdAt(index) == COMMAND_ID_INPUT_METHODS) && - input_method_descriptors_.get() && - (index < static_cast<int>(input_method_descriptors_->size()))); -} - -bool InputMethodMenu::GetPropertyIndex(int index, int* property_index) const { - DCHECK_GE(index, 0); - DCHECK(property_index); - DCHECK(model_.get()); - if (index >= model_->GetItemCount()) { - return false; - } - - if ((model_->GetTypeAt(index) == ui::MenuModel::TYPE_RADIO) && - (model_->GetCommandIdAt(index) == COMMAND_ID_IME_PROPERTIES)) { - const int tmp_property_index = model_->GetGroupIdAt(index); - const input_method::InputMethodPropertyList& property_list - = InputMethodManager::GetInstance()->GetCurrentInputMethodProperties(); - if (tmp_property_index < static_cast<int>(property_list.size())) { - *property_index = tmp_property_index; - return true; - } - } - return false; -} - -bool InputMethodMenu::IndexPointsToConfigureImeMenuItem(int index) const { - DCHECK_GE(index, 0); - DCHECK(model_.get()); - if (index >= model_->GetItemCount()) { - return false; - } - - return ((model_->GetTypeAt(index) == ui::MenuModel::TYPE_RADIO) && - (model_->GetCommandIdAt(index) == COMMAND_ID_CUSTOMIZE_LANGUAGE)); -} - -string16 InputMethodMenu::GetTextForMenu( - const input_method::InputMethodDescriptor& input_method) { - if (!input_method.name().empty()) { - // If the descriptor has a name, use it. - return UTF8ToUTF16(input_method.name()); - } - - // We don't show language here. Name of keyboard layout or input method - // usually imply (or explicitly include) its language. - - input_method::InputMethodManager* manager = - input_method::InputMethodManager::GetInstance(); - - // Special case for German, French and Dutch: these languages have multiple - // keyboard layouts and share the same layout of keyboard (Belgian). We need - // to show explicitly the language for the layout. For Arabic, Amharic, and - // Indic languages: they share "Standard Input Method". - const string16 standard_input_method_text = l10n_util::GetStringUTF16( - IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_STANDARD_INPUT_METHOD); - const std::string language_code = input_method.language_code(); - - string16 text = - manager->GetInputMethodUtil()->TranslateString(input_method.id()); - if (text == standard_input_method_text || - language_code == "de" || - language_code == "fr" || - language_code == "nl") { - text = GetLanguageName(language_code) + UTF8ToUTF16(" - ") + text; - } - - DCHECK(!text.empty()); - return text; -} - -void InputMethodMenu::SetMinimumWidth(int width) { - // On the OOBE network selection screen, fixed width menu would be preferable. - minimum_input_method_menu_width_ = width; -} - -void InputMethodMenu::AddObserver() { - InputMethodManager* manager = InputMethodManager::GetInstance(); - manager->AddObserver(this); -} - -void InputMethodMenu::RemoveObserver() { - InputMethodManager* manager = InputMethodManager::GetInstance(); - manager->RemoveObserver(this); -} - -} // namespace chromeos |