Home | History | Annotate | Download | only in status
      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 #include "chrome/browser/chromeos/status/input_method_menu_button.h"
      6 
      7 #include <string>
      8 
      9 #include "base/utf_string_conversions.h"
     10 #include "chrome/browser/chromeos/cros/cros_library.h"
     11 #include "chrome/browser/chromeos/input_method/input_method_util.h"
     12 #include "chrome/browser/chromeos/status/status_area_host.h"
     13 #include "chrome/browser/prefs/pref_service.h"
     14 #include "chrome/browser/profiles/profile.h"
     15 #include "chrome/browser/ui/browser.h"
     16 #include "chrome/browser/ui/browser_list.h"
     17 #include "chrome/browser/ui/browser_window.h"
     18 #include "views/window/window.h"
     19 
     20 namespace {
     21 
     22 // Returns PrefService object associated with |host|. Returns NULL if we are NOT
     23 // within a browser.
     24 PrefService* GetPrefService(chromeos::StatusAreaHost* host) {
     25   if (host->GetProfile()) {
     26     return host->GetProfile()->GetPrefs();
     27   }
     28   return NULL;
     29 }
     30 
     31 // A class which implements interfaces of chromeos::InputMethodMenu. This class
     32 // is just for avoiding multiple inheritance.
     33 class MenuImpl : public chromeos::InputMethodMenu {
     34  public:
     35   MenuImpl(chromeos::InputMethodMenuButton* button,
     36            PrefService* pref_service,
     37            chromeos::StatusAreaHost::ScreenMode screen_mode)
     38       : InputMethodMenu(pref_service, screen_mode, false), button_(button) {}
     39 
     40  private:
     41   // InputMethodMenu implementation.
     42   virtual void UpdateUI(const std::string& input_method_id,
     43                         const std::wstring& name,
     44                         const std::wstring& tooltip,
     45                         size_t num_active_input_methods) {
     46     button_->UpdateUI(input_method_id, name, tooltip, num_active_input_methods);
     47   }
     48   virtual bool ShouldSupportConfigUI() {
     49     return button_->ShouldSupportConfigUI();
     50   }
     51   virtual void OpenConfigUI() {
     52     button_->OpenConfigUI();
     53   }
     54   // The UI (views button) to which this class delegates all requests.
     55   chromeos::InputMethodMenuButton* button_;
     56 
     57   DISALLOW_COPY_AND_ASSIGN(MenuImpl);
     58 };
     59 
     60 }  // namespace
     61 
     62 namespace chromeos {
     63 
     64 ////////////////////////////////////////////////////////////////////////////////
     65 // InputMethodMenuButton
     66 
     67 InputMethodMenuButton::InputMethodMenuButton(StatusAreaHost* host)
     68     : StatusAreaButton(host, this),
     69       menu_(new MenuImpl(this, GetPrefService(host), host->GetScreenMode())) {
     70   UpdateUIFromCurrentInputMethod();
     71 }
     72 
     73 ////////////////////////////////////////////////////////////////////////////////
     74 // views::View implementation:
     75 
     76 gfx::Size InputMethodMenuButton::GetPreferredSize() {
     77   // If not enabled, then hide this button.
     78   if (!IsEnabled()) {
     79     return gfx::Size(0, 0);
     80   }
     81   return StatusAreaButton::GetPreferredSize();
     82 }
     83 
     84 void InputMethodMenuButton::OnLocaleChanged() {
     85   input_method::OnLocaleChanged();
     86   UpdateUIFromCurrentInputMethod();
     87   Layout();
     88   SchedulePaint();
     89 }
     90 
     91 ////////////////////////////////////////////////////////////////////////////////
     92 // views::ViewMenuDelegate implementation:
     93 
     94 void InputMethodMenuButton::RunMenu(views::View* unused_source,
     95                                     const gfx::Point& pt) {
     96   menu_->RunMenu(unused_source, pt);
     97 }
     98 
     99 bool InputMethodMenuButton::WindowIsActive() {
    100   Browser* active_browser = BrowserList::GetLastActive();
    101   if (!active_browser) {
    102     // Can't get an active browser. Just return true, which is safer.
    103     return true;
    104   }
    105   BrowserWindow* active_window = active_browser->window();
    106   const views::Window* current_window = GetWindow();
    107   if (!active_window || !current_window) {
    108     // Can't get an active or current window. Just return true as well.
    109     return true;
    110   }
    111   return active_window->GetNativeHandle() == current_window->GetNativeWindow();
    112 }
    113 
    114 void InputMethodMenuButton::UpdateUI(const std::string& input_method_id,
    115                                      const std::wstring& name,
    116                                      const std::wstring& tooltip,
    117                                      size_t num_active_input_methods) {
    118   // Hide the button only if there is only one input method, and the input
    119   // method is a XKB keyboard layout. We don't hide the button for other
    120   // types of input methods as these might have intra input method modes,
    121   // like Hiragana and Katakana modes in Japanese input methods.
    122   if (num_active_input_methods == 1 &&
    123       input_method::IsKeyboardLayout(input_method_id) &&
    124       host_->GetScreenMode() == StatusAreaHost::kBrowserMode) {
    125     // As the disabled color is set to invisible, disabling makes the
    126     // button disappear.
    127     SetEnabled(false);
    128     SetTooltipText(L"");  // remove tooltip
    129   } else {
    130     SetEnabled(true);
    131     SetTooltipText(tooltip);
    132   }
    133   SetText(name);
    134 
    135   if (WindowIsActive()) {
    136     // We don't call these functions if the |current_window| is not active since
    137     // the calls are relatively expensive (crosbug.com/9206). Please note that
    138     // PrepareMenu() is necessary for fixing crosbug.com/7522 when the window
    139     // is active.
    140     menu_->PrepareMenu();
    141     SchedulePaint();
    142   }
    143 
    144   // TODO(yusukes): For a window which isn't on top, probably it's better to
    145   // update the texts when the window gets activated because SetTooltipText()
    146   // and SetText() are also expensive.
    147 }
    148 
    149 void InputMethodMenuButton::OpenConfigUI() {
    150   host_->OpenButtonOptions(this);  // ask browser to open the WebUI page.
    151 }
    152 
    153 bool InputMethodMenuButton::ShouldSupportConfigUI() {
    154   return host_->ShouldOpenButtonOptions(this);
    155 }
    156 
    157 void InputMethodMenuButton::UpdateUIFromCurrentInputMethod() {
    158   chromeos::InputMethodLibrary* input_method_library =
    159       chromeos::CrosLibrary::Get()->GetInputMethodLibrary();
    160   const InputMethodDescriptor& input_method =
    161       input_method_library->current_input_method();
    162   const std::wstring name = InputMethodMenu::GetTextForIndicator(input_method);
    163   const std::wstring tooltip = InputMethodMenu::GetTextForMenu(input_method);
    164   const size_t num_active_input_methods =
    165       input_method_library->GetNumActiveInputMethods();
    166   UpdateUI(input_method.id, name, tooltip, num_active_input_methods);
    167 }
    168 
    169 }  // namespace chromeos
    170