1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_CHROMEOS_STATUS_INPUT_METHOD_MENU_H_
6#define CHROME_BROWSER_CHROMEOS_STATUS_INPUT_METHOD_MENU_H_
7#pragma once
8
9#include <string>
10
11#include "chrome/browser/chromeos/cros/input_method_library.h"
12#include "chrome/browser/chromeos/status/status_area_host.h"
13#include "chrome/browser/prefs/pref_member.h"
14#include "content/common/notification_observer.h"
15#include "content/common/notification_registrar.h"
16#include "content/common/notification_type.h"
17#include "ui/base/models/simple_menu_model.h"
18#include "views/controls/menu/menu_2.h"
19#include "views/controls/menu/view_menu_delegate.h"
20
21class PrefService;
22class SkBitmap;
23
24namespace chromeos {
25
26// A class for the dropdown menu for switching input method and keyboard layout.
27// Since the class provides the views::ViewMenuDelegate interface, it's easy to
28// create a button widget (e.g. views::MenuButton, chromeos::StatusAreaButton)
29// which shows the dropdown menu on click.
30class InputMethodMenu : public views::ViewMenuDelegate,
31                        public ui::MenuModel,
32                        public InputMethodLibrary::Observer,
33                        public NotificationObserver {
34 public:
35  InputMethodMenu(PrefService* pref_service,
36                  StatusAreaHost::ScreenMode screen_mode,
37                  bool for_out_of_box_experience_dialog);
38  virtual ~InputMethodMenu();
39
40  // ui::MenuModel implementation.
41  virtual bool HasIcons() const;
42  virtual int GetItemCount() const;
43  virtual ui::MenuModel::ItemType GetTypeAt(int index) const;
44  virtual int GetCommandIdAt(int index) const;
45  virtual string16 GetLabelAt(int index) const;
46  virtual bool IsItemDynamicAt(int index) const;
47  virtual bool GetAcceleratorAt(int index,
48                                ui::Accelerator* accelerator) const;
49  virtual bool IsItemCheckedAt(int index) const;
50  virtual int GetGroupIdAt(int index) const;
51  virtual bool GetIconAt(int index, SkBitmap* icon);
52  virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const;
53  virtual bool IsEnabledAt(int index) const;
54  virtual ui::MenuModel* GetSubmenuModelAt(int index) const;
55  virtual void HighlightChangedTo(int index);
56  virtual void ActivatedAt(int index);
57  virtual void MenuWillShow();
58  virtual void SetMenuModelDelegate(ui::MenuModelDelegate* delegate);
59
60  // views::ViewMenuDelegate implementation. Sub classes can override the method
61  // to adjust the position of the menu.
62  virtual void RunMenu(views::View* unused_source,
63                       const gfx::Point& pt);
64
65  // InputMethodLibrary::Observer implementation.
66  virtual void InputMethodChanged(
67      InputMethodLibrary* obj,
68      const InputMethodDescriptor& current_input_method,
69      size_t num_active_input_methods);
70  virtual void ActiveInputMethodsChanged(
71      InputMethodLibrary* obj,
72      const InputMethodDescriptor& current_input_method,
73      size_t num_active_input_methods);
74  virtual void PreferenceUpdateNeeded(
75    InputMethodLibrary* obj,
76    const InputMethodDescriptor& previous_input_method,
77    const InputMethodDescriptor& current_input_method);
78  virtual void PropertyListChanged(
79      InputMethodLibrary* obj,
80      const ImePropertyList& current_ime_properties);
81  virtual void FirstObserverIsAdded(InputMethodLibrary* obj);
82
83  // NotificationObserver implementation.
84  virtual void Observe(NotificationType type,
85                       const NotificationSource& source,
86                       const NotificationDetails& details);
87
88  // Sets the minimum width of the dropdown menu.
89  void SetMinimumWidth(int width);
90
91  // Rebuilds model and menu2 objects.
92  void PrepareMenu();
93
94  // Registers input method preferences for the login screen.
95  static void RegisterPrefs(PrefService* local_state);
96
97  // Returns a string for the indicator on top right corner of the Chrome
98  // window. The method is public for unit tests.
99  static std::wstring GetTextForIndicator(
100      const InputMethodDescriptor& input_method);
101
102  // Returns a string for the drop-down menu and the tooltip for the indicator.
103  // The method is public for unit tests.
104  static std::wstring GetTextForMenu(const InputMethodDescriptor& input_method);
105
106 protected:
107  // Prepares menu: saves user metrics and rebuilds.
108  void PrepareForMenuOpen();
109
110  // Returns menu2 object for language menu.
111  views::Menu2& input_method_menu() {
112    return input_method_menu_;
113  }
114
115 private:
116  // Updates UI of a container of the menu (e.g. the "US" menu button in the
117  // status area). Sub classes have to implement the interface for their own UI.
118  virtual void UpdateUI(const std::string& input_method_id,  // e.g. "mozc"
119                        const std::wstring& name,  // e.g. "US", "INTL"
120                        const std::wstring& tooltip,
121                        size_t num_active_input_methods) = 0;
122
123  // Sub classes have to implement the interface. This interface should return
124  // true if the dropdown menu should show an item like "Customize languages
125  // and input..." WebUI.
126  virtual bool ShouldSupportConfigUI() = 0;
127
128  // Sub classes have to implement the interface which opens an UI for
129  // customizing languages and input.
130  virtual void OpenConfigUI() = 0;
131
132  // Parses |input_method| and then calls UpdateUI().
133  void UpdateUIFromInputMethod(const InputMethodDescriptor& input_method,
134                               size_t num_active_input_methods);
135
136  // Rebuilds |model_|. This function should be called whenever
137  // |input_method_descriptors_| is updated, or ImePropertiesChanged() is
138  // called.
139  void RebuildModel();
140
141  // Returns true if the zero-origin |index| points to one of the input methods.
142  bool IndexIsInInputMethodList(int index) const;
143
144  // Returns true if the zero-origin |index| points to one of the IME
145  // properties. When returning true, |property_index| is updated so that
146  // property_list.at(property_index) points to the menu item.
147  bool GetPropertyIndex(int index, int* property_index) const;
148
149  // Returns true if the zero-origin |index| points to the "Configure IME" menu
150  // item.
151  bool IndexPointsToConfigureImeMenuItem(int index) const;
152
153  // The current input method list.
154  scoped_ptr<InputMethodDescriptors> input_method_descriptors_;
155
156  // Objects for reading/writing the Chrome prefs.
157  StringPrefMember previous_input_method_pref_;
158  StringPrefMember current_input_method_pref_;
159
160  // We borrow ui::SimpleMenuModel implementation to maintain the current
161  // content of the pop-up menu. The ui::MenuModel is implemented using this
162  // |model_|.
163  scoped_ptr<ui::SimpleMenuModel> model_;
164
165  // The language menu which pops up when the button in status area is clicked.
166  views::Menu2 input_method_menu_;
167  int minimum_input_method_menu_width_;
168
169  PrefService* pref_service_;
170  NotificationRegistrar registrar_;
171
172  // The mode of the host screen  (e.g. browser, screen locker, login screen.)
173  const StatusAreaHost::ScreenMode screen_mode_;
174  // true if the menu is for a dialog in OOBE screen. In the dialog, we don't
175  // use radio buttons.
176  const bool for_out_of_box_experience_dialog_;
177
178  DISALLOW_COPY_AND_ASSIGN(InputMethodMenu);
179};
180
181}  // namespace chromeos
182
183#endif  // CHROME_BROWSER_CHROMEOS_STATUS_INPUT_METHOD_MENU_H_
184