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