// Copyright (c) 2011 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_button.h" #include <string> #include "base/utf_string_conversions.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/input_method/input_method_util.h" #include "chrome/browser/chromeos/status/status_area_host.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window.h" #include "views/window/window.h" namespace { // Returns PrefService object associated with |host|. Returns NULL if we are NOT // within a browser. PrefService* GetPrefService(chromeos::StatusAreaHost* host) { if (host->GetProfile()) { return host->GetProfile()->GetPrefs(); } return NULL; } // A class which implements interfaces of chromeos::InputMethodMenu. This class // is just for avoiding multiple inheritance. class MenuImpl : public chromeos::InputMethodMenu { public: MenuImpl(chromeos::InputMethodMenuButton* button, PrefService* pref_service, chromeos::StatusAreaHost::ScreenMode screen_mode) : InputMethodMenu(pref_service, screen_mode, false), button_(button) {} private: // InputMethodMenu implementation. virtual void UpdateUI(const std::string& input_method_id, const std::wstring& name, const std::wstring& tooltip, size_t num_active_input_methods) { button_->UpdateUI(input_method_id, name, tooltip, num_active_input_methods); } virtual bool ShouldSupportConfigUI() { return button_->ShouldSupportConfigUI(); } virtual void OpenConfigUI() { button_->OpenConfigUI(); } // The UI (views button) to which this class delegates all requests. chromeos::InputMethodMenuButton* button_; DISALLOW_COPY_AND_ASSIGN(MenuImpl); }; } // namespace namespace chromeos { //////////////////////////////////////////////////////////////////////////////// // InputMethodMenuButton InputMethodMenuButton::InputMethodMenuButton(StatusAreaHost* host) : StatusAreaButton(host, this), menu_(new MenuImpl(this, GetPrefService(host), host->GetScreenMode())) { UpdateUIFromCurrentInputMethod(); } //////////////////////////////////////////////////////////////////////////////// // views::View implementation: gfx::Size InputMethodMenuButton::GetPreferredSize() { // If not enabled, then hide this button. if (!IsEnabled()) { return gfx::Size(0, 0); } return StatusAreaButton::GetPreferredSize(); } void InputMethodMenuButton::OnLocaleChanged() { input_method::OnLocaleChanged(); UpdateUIFromCurrentInputMethod(); Layout(); SchedulePaint(); } //////////////////////////////////////////////////////////////////////////////// // views::ViewMenuDelegate implementation: void InputMethodMenuButton::RunMenu(views::View* unused_source, const gfx::Point& pt) { menu_->RunMenu(unused_source, pt); } bool InputMethodMenuButton::WindowIsActive() { Browser* active_browser = BrowserList::GetLastActive(); if (!active_browser) { // Can't get an active browser. Just return true, which is safer. return true; } BrowserWindow* active_window = active_browser->window(); const views::Window* current_window = GetWindow(); if (!active_window || !current_window) { // Can't get an active or current window. Just return true as well. return true; } return active_window->GetNativeHandle() == current_window->GetNativeWindow(); } void InputMethodMenuButton::UpdateUI(const std::string& input_method_id, const std::wstring& name, const std::wstring& tooltip, size_t num_active_input_methods) { // Hide the button only if there is only one input method, and the input // method is a XKB keyboard layout. We don't hide the button for other // types of input methods as these might have intra input method modes, // like Hiragana and Katakana modes in Japanese input methods. if (num_active_input_methods == 1 && input_method::IsKeyboardLayout(input_method_id) && host_->GetScreenMode() == StatusAreaHost::kBrowserMode) { // As the disabled color is set to invisible, disabling makes the // button disappear. SetEnabled(false); SetTooltipText(L""); // remove tooltip } else { SetEnabled(true); SetTooltipText(tooltip); } SetText(name); if (WindowIsActive()) { // We don't call these functions if the |current_window| is not active since // the calls are relatively expensive (crosbug.com/9206). Please note that // PrepareMenu() is necessary for fixing crosbug.com/7522 when the window // is active. menu_->PrepareMenu(); SchedulePaint(); } // TODO(yusukes): For a window which isn't on top, probably it's better to // update the texts when the window gets activated because SetTooltipText() // and SetText() are also expensive. } void InputMethodMenuButton::OpenConfigUI() { host_->OpenButtonOptions(this); // ask browser to open the WebUI page. } bool InputMethodMenuButton::ShouldSupportConfigUI() { return host_->ShouldOpenButtonOptions(this); } void InputMethodMenuButton::UpdateUIFromCurrentInputMethod() { chromeos::InputMethodLibrary* input_method_library = chromeos::CrosLibrary::Get()->GetInputMethodLibrary(); const InputMethodDescriptor& input_method = input_method_library->current_input_method(); const std::wstring name = InputMethodMenu::GetTextForIndicator(input_method); const std::wstring tooltip = InputMethodMenu::GetTextForMenu(input_method); const size_t num_active_input_methods = input_method_library->GetNumActiveInputMethods(); UpdateUI(input_method.id, name, tooltip, num_active_input_methods); } } // namespace chromeos