172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Use of this source code is governed by a BSD-style license that can be
3731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// found in the LICENSE file.
4731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
5731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/chromeos/status/input_method_menu_button.h"
6731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
7731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include <string>
8731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/utf_string_conversions.h"
10731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/chromeos/cros/cros_library.h"
11731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/chromeos/input_method/input_method_util.h"
12731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/chromeos/status/status_area_host.h"
13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/prefs/pref_service.h"
1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_window.h"
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "views/window/window.h"
19731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
20731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace {
21731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
22731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Returns PrefService object associated with |host|. Returns NULL if we are NOT
23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// within a browser.
24731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickPrefService* GetPrefService(chromeos::StatusAreaHost* host) {
25731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (host->GetProfile()) {
26731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return host->GetProfile()->GetPrefs();
27731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return NULL;
29731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
30731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// A class which implements interfaces of chromeos::InputMethodMenu. This class
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// is just for avoiding multiple inheritance.
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenclass MenuImpl : public chromeos::InputMethodMenu {
3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen public:
3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  MenuImpl(chromeos::InputMethodMenuButton* button,
3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen           PrefService* pref_service,
3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen           chromeos::StatusAreaHost::ScreenMode screen_mode)
3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      : InputMethodMenu(pref_service, screen_mode, false), button_(button) {}
3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen private:
4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // InputMethodMenu implementation.
4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void UpdateUI(const std::string& input_method_id,
4372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                        const std::wstring& name,
4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                        const std::wstring& tooltip,
4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                        size_t num_active_input_methods) {
4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    button_->UpdateUI(input_method_id, name, tooltip, num_active_input_methods);
4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual bool ShouldSupportConfigUI() {
4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return button_->ShouldSupportConfigUI();
5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void OpenConfigUI() {
5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    button_->OpenConfigUI();
5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The UI (views button) to which this class delegates all requests.
5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  chromeos::InputMethodMenuButton* button_;
5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
5772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DISALLOW_COPY_AND_ASSIGN(MenuImpl);
5872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen};
5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
60731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}  // namespace
61731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
62731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace chromeos {
63731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
64731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick////////////////////////////////////////////////////////////////////////////////
65731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// InputMethodMenuButton
66731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
67731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickInputMethodMenuButton::InputMethodMenuButton(StatusAreaHost* host)
68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : StatusAreaButton(host, this),
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      menu_(new MenuImpl(this, GetPrefService(host), host->GetScreenMode())) {
7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  UpdateUIFromCurrentInputMethod();
71731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
72731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
73731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick////////////////////////////////////////////////////////////////////////////////
74731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// views::View implementation:
75731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
76513209b27ff55e2841eac0e4120199c23acce758Ben Murdochgfx::Size InputMethodMenuButton::GetPreferredSize() {
77513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // If not enabled, then hide this button.
78513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!IsEnabled()) {
79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return gfx::Size(0, 0);
80513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return StatusAreaButton::GetPreferredSize();
82513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
83513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
84731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InputMethodMenuButton::OnLocaleChanged() {
85731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  input_method::OnLocaleChanged();
8672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  UpdateUIFromCurrentInputMethod();
87731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Layout();
88731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  SchedulePaint();
89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
90731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
91731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick////////////////////////////////////////////////////////////////////////////////
9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// views::ViewMenuDelegate implementation:
9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid InputMethodMenuButton::RunMenu(views::View* unused_source,
9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                    const gfx::Point& pt) {
9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  menu_->RunMenu(unused_source, pt);
9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool InputMethodMenuButton::WindowIsActive() {
100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Browser* active_browser = BrowserList::GetLastActive();
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!active_browser) {
102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Can't get an active browser. Just return true, which is safer.
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return true;
104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BrowserWindow* active_window = active_browser->window();
106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const views::Window* current_window = GetWindow();
107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!active_window || !current_window) {
108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Can't get an active or current window. Just return true as well.
109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return true;
110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return active_window->GetNativeHandle() == current_window->GetNativeWindow();
112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid InputMethodMenuButton::UpdateUI(const std::string& input_method_id,
11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                     const std::wstring& name,
11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                     const std::wstring& tooltip,
11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                     size_t num_active_input_methods) {
118731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Hide the button only if there is only one input method, and the input
119731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // method is a XKB keyboard layout. We don't hide the button for other
120731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // types of input methods as these might have intra input method modes,
121731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // like Hiragana and Katakana modes in Japanese input methods.
12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (num_active_input_methods == 1 &&
12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      input_method::IsKeyboardLayout(input_method_id) &&
12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      host_->GetScreenMode() == StatusAreaHost::kBrowserMode) {
125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // As the disabled color is set to invisible, disabling makes the
126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // button disappear.
127731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    SetEnabled(false);
128731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    SetTooltipText(L"");  // remove tooltip
129731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  } else {
130731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    SetEnabled(true);
131731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    SetTooltipText(tooltip);
132731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
133731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  SetText(name);
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (WindowIsActive()) {
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // We don't call these functions if the |current_window| is not active since
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // the calls are relatively expensive (crosbug.com/9206). Please note that
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // PrepareMenu() is necessary for fixing crosbug.com/7522 when the window
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // is active.
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    menu_->PrepareMenu();
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SchedulePaint();
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(yusukes): For a window which isn't on top, probably it's better to
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // update the texts when the window gets activated because SetTooltipText()
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // and SetText() are also expensive.
147731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
148731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
149731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid InputMethodMenuButton::OpenConfigUI() {
15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  host_->OpenButtonOptions(this);  // ask browser to open the WebUI page.
151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
152731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InputMethodMenuButton::ShouldSupportConfigUI() {
154731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return host_->ShouldOpenButtonOptions(this);
155731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
15772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid InputMethodMenuButton::UpdateUIFromCurrentInputMethod() {
15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  chromeos::InputMethodLibrary* input_method_library =
15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      chromeos::CrosLibrary::Get()->GetInputMethodLibrary();
16072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const InputMethodDescriptor& input_method =
16172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      input_method_library->current_input_method();
16272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const std::wstring name = InputMethodMenu::GetTextForIndicator(input_method);
16372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const std::wstring tooltip = InputMethodMenu::GetTextForMenu(input_method);
16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const size_t num_active_input_methods =
16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      input_method_library->GetNumActiveInputMethods();
16672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  UpdateUI(input_method.id, name, tooltip, num_active_input_methods);
16772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
169731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}  // namespace chromeos
170