1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/chromeos/status/input_method_menu.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <vector>
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_split.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/cros/cros_library.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/input_method/input_method_util.h"
173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/chromeos/language_preferences.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/metrics/user_metrics.h"
193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h"
203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/pref_names.h"
21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_service.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h"
2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The language menu consists of 3 parts (in this order):
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//   (1) input method names. The size of the list is always >= 1.
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//   (2) input method properties. This list might be empty.
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//   (3) "Customize language and input..." button.
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Example of the menu (Japanese):
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ============================== (border of the popup window)
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// [ ] English                    (|index| in the following functions is 0)
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// [*] Japanese
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// [ ] Chinese (Simplified)
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ------------------------------ (separator)
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// [*] Hiragana                   (index = 5, The property has 2 radio groups)
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// [ ] Katakana
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// [ ] HalfWidthKatakana
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// [*] Roman
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// [ ] Kana
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ------------------------------ (separator)
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Customize language and input...(index = 11)
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ============================== (border of the popup window)
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Example of the menu (Simplified Chinese):
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ============================== (border of the popup window)
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// [ ] English
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// [ ] Japanese
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// [*] Chinese (Simplified)
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ------------------------------ (separator)
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Switch to full letter mode     (The property has 2 command buttons)
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Switch to half punctuation mode
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ------------------------------ (separator)
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Customize language and input...
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ============================== (border of the popup window)
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Constants to specify the type of items in |model_|.
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum {
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  COMMAND_ID_INPUT_METHODS = 0,  // English, Chinese, Japanese, Arabic, ...
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  COMMAND_ID_IME_PROPERTIES,  // Hiragana, Katakana, ...
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  COMMAND_ID_CUSTOMIZE_LANGUAGE,  // "Customize language and input..." button.
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A group ID for IME properties starts from 0. We use the huge value for the
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// input method list to avoid conflict.
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kRadioGroupLanguage = 1 << 16;
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kRadioGroupNone = -1;
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
77731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// A mapping from an input method id to a string for the language indicator. The
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// mapping is necessary since some input methods belong to the same language.
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// For example, both "xkb:us::eng" and "xkb:us:dvorak:eng" are for US English.
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst struct {
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* input_method_id;
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* indicator_text;
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} kMappingFromIdToIndicatorText[] = {
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // To distinguish from "xkb:us::eng"
85201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "xkb:us:altgr-intl:eng", "EXTD" },
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { "xkb:us:dvorak:eng", "DV" },
87201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { "xkb:us:intl:eng", "INTL" },
8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  { "xkb:us:colemak:eng", "CO" },
8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  { "xkb:de:neo:ger", "NEO" },
90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // To distinguish from "xkb:gb::eng"
91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "xkb:gb:dvorak:eng", "DV" },
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // To distinguish from "xkb:jp::jpn"
93731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  { "mozc", "\xe3\x81\x82" },  // U+3042, Japanese Hiragana letter A in UTF-8.
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { "mozc-dv", "\xe3\x81\x82" },
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { "mozc-jp", "\xe3\x81\x82" },
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // For simplified Chinese input methods
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { "pinyin", "\xe6\x8b\xbc" },  // U+62FC
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // For traditional Chinese input methods
99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  { "mozc-chewing", "\xe9\x85\xb7" },  // U+9177
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { "m17n:zh:cangjie", "\xe5\x80\x89" },  // U+5009
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  { "m17n:zh:quick", "\xe9\x80\x9f" },  // U+901F
1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // For Hangul input method.
1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  { "hangul", "\xed\x95\x9c" },  // U+D55C
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst size_t kMappingFromIdToIndicatorTextLen =
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ARRAYSIZE_UNSAFE(kMappingFromIdToIndicatorText);
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns the language name for the given |language_code|.
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::wstring GetLanguageName(const std::string& language_code) {
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const string16 language_name = l10n_util::GetDisplayNameForLocale(
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      language_code, g_browser_process->GetApplicationLocale(), true);
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return UTF16ToWide(language_name);
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace chromeos {
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
120731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// InputMethodMenu
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
122731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickInputMethodMenu::InputMethodMenu(PrefService* pref_service,
12372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                 StatusAreaHost::ScreenMode screen_mode,
12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                 bool for_out_of_box_experience_dialog)
125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    : input_method_descriptors_(CrosLibrary::Get()->GetInputMethodLibrary()->
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                GetActiveInputMethods()),
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      model_(NULL),
128513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // Be aware that the constructor of |input_method_menu_| calls
129513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // GetItemCount() in this class. Therefore, GetItemCount() have to return
130513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // 0 when |model_| is NULL.
131513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      ALLOW_THIS_IN_INITIALIZER_LIST(input_method_menu_(this)),
132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      minimum_input_method_menu_width_(0),
133731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      pref_service_(pref_service),
13472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      screen_mode_(screen_mode),
13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      for_out_of_box_experience_dialog_(for_out_of_box_experience_dialog) {
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(input_method_descriptors_.get() &&
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         !input_method_descriptors_->empty());
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Sync current and previous input methods on Chrome prefs with ibus-daemon.
14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (pref_service_ && (screen_mode_ == StatusAreaHost::kBrowserMode)) {
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    previous_input_method_pref_.Init(
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        prefs::kLanguagePreviousInputMethod, pref_service, this);
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    current_input_method_pref_.Init(
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        prefs::kLanguageCurrentInputMethod, pref_service, this);
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  InputMethodLibrary* library = CrosLibrary::Get()->GetInputMethodLibrary();
14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  library->AddObserver(this);  // FirstObserverIsAdded() might be called back.
14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (screen_mode_ == StatusAreaHost::kLoginMode) {
15172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // This button is for the login screen.
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    registrar_.Add(this,
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   NotificationType::LOGIN_USER_CHANGED,
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   NotificationService::AllSources());
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
158731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickInputMethodMenu::~InputMethodMenu() {
15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // RemoveObserver() is no-op if |this| object is already removed from the
16072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // observer list.
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CrosLibrary::Get()->GetInputMethodLibrary()->RemoveObserver(this);
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// ui::MenuModel implementation:
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
167731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint InputMethodMenu::GetCommandIdAt(int index) const {
16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return index;
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool InputMethodMenu::IsItemDynamicAt(int index) const {
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Menu content for the language button could change time by time.
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
176731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InputMethodMenu::GetAcceleratorAt(
17772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    int index, ui::Accelerator* accelerator) const {
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Views for Chromium OS does not support accelerators yet.
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
182731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InputMethodMenu::IsItemCheckedAt(int index) const {
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(index, 0);
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(input_method_descriptors_.get());
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IndexIsInInputMethodList(index)) {
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const InputMethodDescriptor& input_method
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        = input_method_descriptors_->at(index);
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return input_method == CrosLibrary::Get()->GetInputMethodLibrary()->
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          current_input_method();
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (GetPropertyIndex(index, &index)) {
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const ImePropertyList& property_list
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        = CrosLibrary::Get()->GetInputMethodLibrary()->current_ime_properties();
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return property_list.at(index).is_selection_item_checked;
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Separator(s) or the "Customize language and input..." button.
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
203731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint InputMethodMenu::GetGroupIdAt(int index) const {
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(index, 0);
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IndexIsInInputMethodList(index)) {
20772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return for_out_of_box_experience_dialog_ ?
208513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        kRadioGroupNone : kRadioGroupLanguage;
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (GetPropertyIndex(index, &index)) {
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const ImePropertyList& property_list
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        = CrosLibrary::Get()->GetInputMethodLibrary()->current_ime_properties();
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return property_list.at(index).selection_item_id;
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return kRadioGroupNone;
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
220731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InputMethodMenu::HasIcons() const  {
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We don't support icons on Chrome OS.
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool InputMethodMenu::GetIconAt(int index, SkBitmap* icon) {
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenui::ButtonMenuItemModel* InputMethodMenu::GetButtonMenuItemAt(
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int index) const {
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return NULL;
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
234731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InputMethodMenu::IsEnabledAt(int index) const {
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Just return true so all input method names and input method propertie names
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // could be clicked.
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenui::MenuModel* InputMethodMenu::GetSubmenuModelAt(int index) const {
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We don't use nested menus.
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return NULL;
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
245731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InputMethodMenu::HighlightChangedTo(int index) {
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Views for Chromium OS does not support this interface yet.
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
249731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InputMethodMenu::MenuWillShow() {
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Views for Chromium OS does not support this interface yet.
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid InputMethodMenu::SetMenuModelDelegate(ui::MenuModelDelegate* delegate) {
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Not needed for current usage.
255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
257731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint InputMethodMenu::GetItemCount() const {
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!model_.get()) {
259731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // Model is not constructed yet. This means that
260731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // InputMethodMenu is being constructed. Return zero.
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return model_->GetItemCount();
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
26672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenui::MenuModel::ItemType InputMethodMenu::GetTypeAt(int index) const {
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(index, 0);
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IndexPointsToConfigureImeMenuItem(index)) {
27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::MenuModel::TYPE_COMMAND;  // "Customize language and input"
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IndexIsInInputMethodList(index)) {
27472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return for_out_of_box_experience_dialog_ ?
27572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        ui::MenuModel::TYPE_COMMAND : ui::MenuModel::TYPE_RADIO;
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (GetPropertyIndex(index, &index)) {
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const ImePropertyList& property_list
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        = CrosLibrary::Get()->GetInputMethodLibrary()->current_ime_properties();
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (property_list.at(index).is_selection_item) {
28272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return ui::MenuModel::TYPE_RADIO;
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
28472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::MenuModel::TYPE_COMMAND;
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
28772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return ui::MenuModel::TYPE_SEPARATOR;
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
290731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstring16 InputMethodMenu::GetLabelAt(int index) const {
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(index, 0);
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(input_method_descriptors_.get());
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We use IDS_OPTIONS_SETTINGS_LANGUAGES_CUSTOMIZE here as the button
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // opens the same dialog that is opened from the main options dialog.
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IndexPointsToConfigureImeMenuItem(index)) {
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_LANGUAGES_CUSTOMIZE);
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::wstring name;
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IndexIsInInputMethodList(index)) {
3023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    name = GetTextForMenu(input_method_descriptors_->at(index));
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (GetPropertyIndex(index, &index)) {
304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    InputMethodLibrary* library = CrosLibrary::Get()->GetInputMethodLibrary();
305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const ImePropertyList& property_list = library->current_ime_properties();
306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& input_method_id = library->current_input_method().id;
307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return input_method::GetStringUTF16(
308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        property_list.at(index).label, input_method_id);
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return WideToUTF16(name);
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
314731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InputMethodMenu::ActivatedAt(int index) {
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(index, 0);
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(input_method_descriptors_.get());
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IndexPointsToConfigureImeMenuItem(index)) {
319731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    OpenConfigUI();
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IndexIsInInputMethodList(index)) {
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Inter-IME switching.
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const InputMethodDescriptor& input_method
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        = input_method_descriptors_->at(index);
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CrosLibrary::Get()->GetInputMethodLibrary()->ChangeInputMethod(
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        input_method.id);
32972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    UserMetrics::RecordAction(
33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        UserMetricsAction("LanguageMenuButton_InputMethodChanged"));
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (GetPropertyIndex(index, &index)) {
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Intra-IME switching (e.g. Japanese-Hiragana to Japanese-Katakana).
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const ImePropertyList& property_list
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        = CrosLibrary::Get()->GetInputMethodLibrary()->current_ime_properties();
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string key = property_list.at(index).key;
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (property_list.at(index).is_selection_item) {
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Radio button is clicked.
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const int id = property_list.at(index).selection_item_id;
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // First, deactivate all other properties in the same radio group.
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for (int i = 0; i < static_cast<int>(property_list.size()); ++i) {
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (i != index && id == property_list.at(i).selection_item_id) {
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          CrosLibrary::Get()->GetInputMethodLibrary()->SetImePropertyActivated(
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              property_list.at(i).key, false);
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Then, activate the property clicked.
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CrosLibrary::Get()->GetInputMethodLibrary()->SetImePropertyActivated(
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          key, true);
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Command button like "Switch to half punctuation mode" is clicked.
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We can always use "Deactivate" for command buttons.
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CrosLibrary::Get()->GetInputMethodLibrary()->SetImePropertyActivated(
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          key, false);
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  LOG(ERROR) << "Unexpected index: " << index;
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
365731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// views::ViewMenuDelegate implementation:
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
367731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InputMethodMenu::RunMenu(
368731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    views::View* unused_source, const gfx::Point& pt) {
369731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  PrepareForMenuOpen();
370513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  input_method_menu_.RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT);
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// InputMethodLibrary::Observer implementation:
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
37621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid InputMethodMenu::InputMethodChanged(
37721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    InputMethodLibrary* obj,
37821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const InputMethodDescriptor& current_input_method,
37921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    size_t num_active_input_methods) {
38021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  UpdateUIFromInputMethod(current_input_method, num_active_input_methods);
38121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
38321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid InputMethodMenu::PreferenceUpdateNeeded(
38421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    InputMethodLibrary* obj,
38521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const InputMethodDescriptor& previous_input_method,
38621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const InputMethodDescriptor& current_input_method) {
38772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (screen_mode_ == StatusAreaHost::kBrowserMode) {
388731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (pref_service_) {  // make sure we're not in unit tests.
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Sometimes (e.g. initial boot) |previous_input_method.id| is empty.
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      previous_input_method_pref_.SetValue(previous_input_method.id);
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      current_input_method_pref_.SetValue(current_input_method.id);
392ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      pref_service_->ScheduleSavePersistentPrefs();
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
39472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else if (screen_mode_ == StatusAreaHost::kLoginMode) {
39572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (g_browser_process && g_browser_process->local_state()) {
39672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      g_browser_process->local_state()->SetString(
39772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          language_prefs::kPreferredKeyboardLayout, current_input_method.id);
39872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      g_browser_process->local_state()->SavePersistentPrefs();
39972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
40072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
40172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
40272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid InputMethodMenu::PropertyListChanged(
404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    InputMethodLibrary* obj,
405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const ImePropertyList& current_ime_properties) {
406ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Usual order of notifications of input method change is:
407ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // 1. RegisterProperties(empty)
408ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // 2. RegisterProperties(list-of-new-properties)
409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // 3. GlobalInputMethodChanged
410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // However, due to the asynchronicity, we occasionally (but rarely) face to
411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // 1. RegisterProperties(empty)
412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // 2. GlobalInputMethodChanged
413ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // 3. RegisterProperties(list-of-new-properties)
414ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // this order. On this unusual case, we must rebuild the menu after the last
415ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // RegisterProperties. For the other cases, no rebuild is needed. Actually
416ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // it is better to be avoided. Otherwise users can sometimes observe the
417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // awkward clear-then-register behavior.
418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!current_ime_properties.empty()) {
419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    InputMethodLibrary* library = CrosLibrary::Get()->GetInputMethodLibrary();
420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const InputMethodDescriptor& input_method = library->current_input_method();
421ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    size_t num_active_input_methods = library->GetNumActiveInputMethods();
422ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    UpdateUIFromInputMethod(input_method, num_active_input_methods);
423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
424ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
425ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
42672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid InputMethodMenu::FirstObserverIsAdded(InputMethodLibrary* obj) {
42772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // NOTICE: Since this function might be called from the constructor of this
42872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // class, it's better to avoid calling virtual functions.
42972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
43072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (pref_service_ && (screen_mode_ == StatusAreaHost::kBrowserMode)) {
43172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Get the input method name in the Preferences file which was in use last
43272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // time, and switch to the method. We remember two input method names in the
43372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // preference so that the Control+space hot-key could work fine from the
43472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // beginning. InputMethodChanged() will be called soon and the indicator
43572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // will be updated.
43672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    InputMethodLibrary* library = CrosLibrary::Get()->GetInputMethodLibrary();
43772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::string previous_input_method_id =
43872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        previous_input_method_pref_.GetValue();
43972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!previous_input_method_id.empty()) {
44072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      library->ChangeInputMethod(previous_input_method_id);
44172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
44272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::string current_input_method_id =
44372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        current_input_method_pref_.GetValue();
44472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!current_input_method_id.empty()) {
44572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      library->ChangeInputMethod(current_input_method_id);
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
450731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InputMethodMenu::PrepareForMenuOpen() {
451731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  UserMetrics::RecordAction(UserMetricsAction("LanguageMenuButton_Open"));
45272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  PrepareMenu();
45372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
45472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
45572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid InputMethodMenu::PrepareMenu() {
456731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  input_method_descriptors_.reset(CrosLibrary::Get()->GetInputMethodLibrary()->
457731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                  GetActiveInputMethods());
458731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  RebuildModel();
459513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  input_method_menu_.Rebuild();
460513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (minimum_input_method_menu_width_ > 0) {
461513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    input_method_menu_.SetMinimumWidth(minimum_input_method_menu_width_);
462731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid InputMethodMenu::ActiveInputMethodsChanged(
46621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    InputMethodLibrary* obj,
46721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const InputMethodDescriptor& current_input_method,
46821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    size_t num_active_input_methods) {
469731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Update the icon if active input methods are changed. See also
47021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // comments in UpdateUI() in input_method_menu_button.cc.
47121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  UpdateUIFromInputMethod(current_input_method, num_active_input_methods);
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
474731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InputMethodMenu::UpdateUIFromInputMethod(
47521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const InputMethodDescriptor& input_method,
47621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    size_t num_active_input_methods) {
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::wstring name = GetTextForIndicator(input_method);
4783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const std::wstring tooltip = GetTextForMenu(input_method);
47921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  UpdateUI(input_method.id, name, tooltip, num_active_input_methods);
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
482731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InputMethodMenu::RebuildModel() {
48372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  model_.reset(new ui::SimpleMenuModel(NULL));
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  string16 dummy_label = UTF8ToUTF16("");
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Indicates if separator's needed before each section.
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool need_separator = false;
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!input_method_descriptors_->empty()) {
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We "abuse" the command_id and group_id arguments of AddRadioItem method.
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // A COMMAND_ID_XXX enum value is passed as command_id, and array index of
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // |input_method_descriptors_| or |property_list| is passed as group_id.
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (size_t i = 0; i < input_method_descriptors_->size(); ++i) {
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      model_->AddRadioItem(COMMAND_ID_INPUT_METHODS, dummy_label, i);
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
4953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    need_separator = true;
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const ImePropertyList& property_list
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      = CrosLibrary::Get()->GetInputMethodLibrary()->current_ime_properties();
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!property_list.empty()) {
502731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (need_separator) {
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      model_->AddSeparator();
504731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (size_t i = 0; i < property_list.size(); ++i) {
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      model_->AddRadioItem(COMMAND_ID_IME_PROPERTIES, dummy_label, i);
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    need_separator = true;
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
511731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (ShouldSupportConfigUI()) {
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Note: We use AddSeparator() for separators, and AddRadioItem() for all
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // other items even if an item is not actually a radio item.
514731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (need_separator) {
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      model_->AddSeparator();
516731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    model_->AddRadioItem(COMMAND_ID_CUSTOMIZE_LANGUAGE, dummy_label,
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         0 /* dummy */);
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
522731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InputMethodMenu::IndexIsInInputMethodList(int index) const {
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(index, 0);
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(model_.get());
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (index >= model_->GetItemCount()) {
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return ((model_->GetTypeAt(index) == ui::MenuModel::TYPE_RADIO) &&
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          (model_->GetCommandIdAt(index) == COMMAND_ID_INPUT_METHODS) &&
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          input_method_descriptors_.get() &&
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          (index < static_cast<int>(input_method_descriptors_->size())));
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
535731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InputMethodMenu::GetPropertyIndex(int index, int* property_index) const {
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(index, 0);
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(property_index);
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(model_.get());
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (index >= model_->GetItemCount()) {
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
54372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if ((model_->GetTypeAt(index) == ui::MenuModel::TYPE_RADIO) &&
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (model_->GetCommandIdAt(index) == COMMAND_ID_IME_PROPERTIES)) {
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int tmp_property_index = model_->GetGroupIdAt(index);
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const ImePropertyList& property_list
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        = CrosLibrary::Get()->GetInputMethodLibrary()->current_ime_properties();
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (tmp_property_index < static_cast<int>(property_list.size())) {
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *property_index = tmp_property_index;
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return true;
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
556731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InputMethodMenu::IndexPointsToConfigureImeMenuItem(int index) const {
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(index, 0);
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(model_.get());
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (index >= model_->GetItemCount()) {
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
56372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return ((model_->GetTypeAt(index) == ui::MenuModel::TYPE_RADIO) &&
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          (model_->GetCommandIdAt(index) == COMMAND_ID_CUSTOMIZE_LANGUAGE));
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
567731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstd::wstring InputMethodMenu::GetTextForIndicator(
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const InputMethodDescriptor& input_method) {
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // For the status area, we use two-letter, upper-case language code like
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // "US" and "JP".
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::wstring text;
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Check special cases first.
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < kMappingFromIdToIndicatorTextLen; ++i) {
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (kMappingFromIdToIndicatorText[i].input_method_id == input_method.id) {
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      text = UTF8ToWide(kMappingFromIdToIndicatorText[i].indicator_text);
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
58172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Display the keyboard layout name when using a keyboard layout.
58272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (text.empty() && input_method::IsKeyboardLayout(input_method.id)) {
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const size_t kMaxKeyboardLayoutNameLen = 2;
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::wstring keyboard_layout = UTF8ToWide(
585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        input_method::GetKeyboardLayoutName(input_method.id));
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    text = StringToUpperASCII(keyboard_layout).substr(
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        0, kMaxKeyboardLayoutNameLen);
588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(yusukes): Some languages have two or more input methods. For example,
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Thai has 3, Vietnamese has 4. If these input methods could be activated at
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the same time, we should do either of the following:
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //   (1) Add mappings to |kMappingFromIdToIndicatorText|
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //   (2) Add suffix (1, 2, ...) to |text| when ambiguous.
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (text.empty()) {
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const size_t kMaxLanguageNameLen = 2;
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string language_code =
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        input_method::GetLanguageCodeFromDescriptor(input_method);
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Use "CN" for simplified Chinese and "TW" for traditonal Chinese,
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // rather than "ZH".
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (StartsWithASCII(language_code, "zh-", false)) {
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::vector<std::string> portions;
605731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      base::SplitString(language_code, '-', &portions);
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (portions.size() >= 2 && !portions[1].empty()) {
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        language_code = portions[1];
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    text = StringToUpperASCII(UTF8ToWide(language_code)).substr(
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        0, kMaxLanguageNameLen);
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!text.empty());
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return text;
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
618731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstd::wstring InputMethodMenu::GetTextForMenu(
6193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const InputMethodDescriptor& input_method) {
6203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We don't show language here.  Name of keyboard layout or input method
6213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // usually imply (or explicitly include) its language.
6223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Special case for Dutch, French and German: these languages have multiple
6243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // keyboard layouts and share the same laout of keyboard (Belgian). We need to
6253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // show explicitly the language for the layout.
6263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // For Arabic and Hindi: they share "Standard Input Method".
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::string language_code
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      = input_method::GetLanguageCodeFromDescriptor(input_method);
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::wstring text;
6303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (language_code == "ar" ||
6313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      language_code == "hi" ||
6323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      language_code == "nl" ||
6333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      language_code == "fr" ||
6343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      language_code == "de") {
6353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    text = GetLanguageName(language_code) + L" - ";
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
637ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  text += input_method::GetString(input_method.display_name, input_method.id);
638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!text.empty());
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return text;
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
643731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InputMethodMenu::RegisterPrefs(PrefService* local_state) {
644731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  local_state->RegisterStringPref(language_prefs::kPreferredKeyboardLayout, "");
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
647731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InputMethodMenu::Observe(NotificationType type,
648731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                              const NotificationSource& source,
649731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                              const NotificationDetails& details) {
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (type == NotificationType::LOGIN_USER_CHANGED) {
65172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // When a user logs in, we should remove |this| object from the observer
65272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // list so that PreferenceUpdateNeeded() does not update the local state
65372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // anymore.
65472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    CrosLibrary::Get()->GetInputMethodLibrary()->RemoveObserver(this);
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
658731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InputMethodMenu::SetMinimumWidth(int width) {
659731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // On the OOBE network selection screen, fixed width menu would be preferable.
660513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  minimum_input_method_menu_width_ = width;
661731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
662731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace chromeos
664