OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 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/language_menu_button.h" |
| 6 |
| 7 #include <string> |
| 8 |
| 9 #include "app/l10n_util.h" |
| 10 #include "app/resource_bundle.h" |
| 11 #include "base/time.h" |
| 12 #include "chrome/browser/browser.h" |
| 13 #include "grit/generated_resources.h" |
| 14 #include "grit/theme_resources.h" |
| 15 |
| 16 namespace { |
| 17 |
| 18 const int kRadioGroupNone = 0; |
| 19 const int kRadioGroupLanguage = 1; |
| 20 const size_t kMaxLanguageNameLen = 7; |
| 21 const wchar_t kSpacer[] = L"MMMMMMM"; |
| 22 |
| 23 // Returns true if the |index| points to the "Configure IME" menu item. |
| 24 bool IsIndexShowControlPanel( |
| 25 int index, chromeos::InputLanguageList* language_list) { |
| 26 DCHECK_GE(index, 0); |
| 27 if (language_list->empty()) { |
| 28 // If language_list is empty, then there's no separator. So "Configure IME" |
| 29 // should be at index 0. |
| 30 DCHECK_EQ(index, 0); |
| 31 return index == 0; |
| 32 } |
| 33 return static_cast<size_t>(index) == (language_list->size() + 1); |
| 34 } |
| 35 |
| 36 // Converts chromeos::InputLanguage object into human readable string. Returns |
| 37 // a string for the drop-down menu if |for_menu| is true. Otherwise, returns a |
| 38 // string for the status area. |
| 39 std::string FormatInputLanguage( |
| 40 const chromeos::InputLanguage& language, bool for_menu) { |
| 41 std::string formatted = language.display_name; |
| 42 if (formatted.empty()) { |
| 43 formatted = language.id; |
| 44 } |
| 45 if (for_menu) { |
| 46 switch (language.category) { |
| 47 case chromeos::LANGUAGE_CATEGORY_XKB: |
| 48 // TODO(yusukes): Use message catalog. |
| 49 formatted += " (Layout)"; |
| 50 break; |
| 51 case chromeos::LANGUAGE_CATEGORY_IME: |
| 52 // TODO(yusukes): Use message catalog. |
| 53 formatted += " (IME)"; |
| 54 break; |
| 55 } |
| 56 } else { |
| 57 // For status area. Trim the string. |
| 58 formatted = formatted.substr(0, kMaxLanguageNameLen); |
| 59 // TODO(yusukes): Simple substr() does not work for non-ASCII string. |
| 60 // TODO(yusukes): How can we ensure that the trimmed string does not |
| 61 // overflow the area? |
| 62 } |
| 63 return formatted; |
| 64 } |
| 65 |
| 66 } // namespace |
| 67 |
| 68 namespace chromeos { |
| 69 |
| 70 //////////////////////////////////////////////////////////////////////////////// |
| 71 // LanguageMenuButton |
| 72 |
| 73 LanguageMenuButton::LanguageMenuButton(Browser* browser) |
| 74 : MenuButton(NULL, std::wstring(), this, false), |
| 75 language_list_(LanguageLibrary::Get()->GetLanguages()), |
| 76 // Since the constructor of |language_menu_| calls this->GetItemCount(), |
| 77 // we have to initialize |language_list_| before hand. |
| 78 ALLOW_THIS_IN_INITIALIZER_LIST(language_menu_(this)), |
| 79 browser_(browser) { |
| 80 DCHECK(language_list_.get() && !language_list_->empty()); |
| 81 // Grab the real estate. |
| 82 UpdateIcon(kSpacer); |
| 83 // Display the default XKB name (usually "US"). |
| 84 const std::string name = FormatInputLanguage(language_list_->at(0), false); |
| 85 UpdateIcon(UTF8ToWide(name)); |
| 86 LanguageLibrary::Get()->AddObserver(this); |
| 87 } |
| 88 |
| 89 LanguageMenuButton::~LanguageMenuButton() { |
| 90 LanguageLibrary::Get()->RemoveObserver(this); |
| 91 } |
| 92 |
| 93 //////////////////////////////////////////////////////////////////////////////// |
| 94 // LanguageMenuButton, menus::MenuModel implementation: |
| 95 |
| 96 int LanguageMenuButton::GetCommandIdAt(int index) const { |
| 97 return index; // dummy |
| 98 } |
| 99 |
| 100 bool LanguageMenuButton::IsLabelDynamicAt(int index) const { |
| 101 // Menu content for the language button could change time by time. |
| 102 return true; |
| 103 } |
| 104 |
| 105 bool LanguageMenuButton::GetAcceleratorAt( |
| 106 int index, menus::Accelerator* accelerator) const { |
| 107 // Views for Chromium OS does not support accelerators yet. |
| 108 return false; |
| 109 } |
| 110 |
| 111 bool LanguageMenuButton::IsItemCheckedAt(int index) const { |
| 112 DCHECK_GE(index, 0); |
| 113 DCHECK(language_list_.get()); |
| 114 if (static_cast<size_t>(index) < language_list_->size()) { |
| 115 const InputLanguage& language = language_list_->at(index); |
| 116 return language == LanguageLibrary::Get()->current_language(); |
| 117 } |
| 118 return false; |
| 119 } |
| 120 |
| 121 int LanguageMenuButton::GetGroupIdAt(int index) const { |
| 122 DCHECK_GE(index, 0); |
| 123 DCHECK(language_list_.get()); |
| 124 if (static_cast<size_t>(index) < language_list_->size()) { |
| 125 return kRadioGroupLanguage; |
| 126 } |
| 127 return kRadioGroupNone; |
| 128 } |
| 129 |
| 130 bool LanguageMenuButton::HasIcons() const { |
| 131 // TODO(yusukes): Display IME icons. |
| 132 return false; |
| 133 } |
| 134 |
| 135 bool LanguageMenuButton::GetIconAt(int index, SkBitmap* icon) const { |
| 136 return false; |
| 137 } |
| 138 |
| 139 bool LanguageMenuButton::IsEnabledAt(int index) const { |
| 140 // Just return true so all IMEs and XLB layouts listed could be clicked. |
| 141 return true; |
| 142 } |
| 143 |
| 144 menus::MenuModel* LanguageMenuButton::GetSubmenuModelAt(int index) const { |
| 145 return NULL; |
| 146 } |
| 147 |
| 148 void LanguageMenuButton::HighlightChangedTo(int index) { |
| 149 // Views for Chromium OS does not support this interface yet. |
| 150 } |
| 151 |
| 152 void LanguageMenuButton::MenuWillShow() { |
| 153 // Views for Chromium OS does not support this interface yet. |
| 154 } |
| 155 |
| 156 int LanguageMenuButton::GetItemCount() const { |
| 157 DCHECK(language_list_.get()); |
| 158 if (language_list_->empty()) { |
| 159 return 1; // no separator; "Configure IME" only |
| 160 } |
| 161 return language_list_->size() + 2; // separator + "Configure IME" |
| 162 } |
| 163 |
| 164 menus::MenuModel::ItemType LanguageMenuButton::GetTypeAt(int index) const { |
| 165 DCHECK_GE(index, 0); |
| 166 DCHECK(language_list_.get()); |
| 167 if (IsIndexShowControlPanel(index, language_list_.get())) { |
| 168 return menus::MenuModel::TYPE_COMMAND; // "Configure IME" |
| 169 } |
| 170 if (static_cast<size_t>(index) < language_list_->size()) { |
| 171 return menus::MenuModel::TYPE_RADIO; |
| 172 } |
| 173 |
| 174 DCHECK_EQ(static_cast<size_t>(index), language_list_->size()); |
| 175 return menus::MenuModel::TYPE_SEPARATOR; |
| 176 } |
| 177 |
| 178 string16 LanguageMenuButton::GetLabelAt(int index) const { |
| 179 DCHECK_GE(index, 0); |
| 180 DCHECK(language_list_.get()); |
| 181 if (IsIndexShowControlPanel(index, language_list_.get())) { |
| 182 // TODO(yusukes): Use message catalog. |
| 183 return WideToUTF16(L"Configure IME..."); |
| 184 } |
| 185 if (static_cast<size_t>(index) < language_list_->size()) { |
| 186 std::string name = FormatInputLanguage(language_list_->at(index), true); |
| 187 return UTF8ToUTF16(name); |
| 188 } |
| 189 NOTREACHED(); |
| 190 return WideToUTF16(L""); |
| 191 } |
| 192 |
| 193 void LanguageMenuButton::ActivatedAt(int index) { |
| 194 DCHECK_GE(index, 0); |
| 195 DCHECK(language_list_.get()); |
| 196 if (IsIndexShowControlPanel(index, language_list_.get())) { |
| 197 browser_->ShowControlPanel(); |
| 198 return; |
| 199 } |
| 200 if (static_cast<size_t>(index) < language_list_->size()) { |
| 201 const InputLanguage& language = language_list_->at(index); |
| 202 LanguageLibrary::Get()->ChangeLanguage(language.category, language.id); |
| 203 return; |
| 204 } |
| 205 NOTREACHED(); |
| 206 } |
| 207 |
| 208 //////////////////////////////////////////////////////////////////////////////// |
| 209 // LanguageMenuButton, views::ViewMenuDelegate implementation: |
| 210 |
| 211 void LanguageMenuButton::RunMenu(views::View* source, const gfx::Point& pt) { |
| 212 language_list_.reset(LanguageLibrary::Get()->GetLanguages()); |
| 213 language_menu_.Rebuild(); |
| 214 language_menu_.UpdateStates(); |
| 215 language_menu_.RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT); |
| 216 } |
| 217 |
| 218 //////////////////////////////////////////////////////////////////////////////// |
| 219 // LanguageMenuButton, PowerLibrary::Observer implementation: |
| 220 |
| 221 void LanguageMenuButton::LanguageChanged(LanguageLibrary* obj) { |
| 222 const std::string name = FormatInputLanguage(obj->current_language(), false); |
| 223 UpdateIcon(UTF8ToWide(name)); |
| 224 } |
| 225 |
| 226 void LanguageMenuButton::UpdateIcon(const std::wstring& name) { |
| 227 set_border(NULL); |
| 228 SetFont(ResourceBundle::GetSharedInstance().GetFont( |
| 229 ResourceBundle::BaseFont).DeriveFont(0, gfx::Font::BOLD)); |
| 230 SetEnabledColor(SK_ColorWHITE); |
| 231 SetShowHighlighted(false); |
| 232 SetText(name); |
| 233 // TODO(yusukes): Show icon on the status area? |
| 234 set_alignment(TextButton::ALIGN_RIGHT); |
| 235 SchedulePaint(); |
| 236 } |
| 237 |
| 238 // TODO(yusukes): Register and handle hotkeys for IME and XKB switching? |
| 239 |
| 240 } // namespace chromeos |
| 241 |
OLD | NEW |