language_switch_menu.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
1// Copyright (c) 2010 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/login/language_switch_menu.h" 6 7#include "app/resource_bundle.h" 8#include "base/i18n/rtl.h" 9#include "base/utf_string_conversions.h" 10#include "chrome/browser/browser_process.h" 11#include "chrome/browser/chromeos/cros/cros_library.h" 12#include "chrome/browser/chromeos/cros/keyboard_library.h" 13#include "chrome/browser/chromeos/input_method/input_method_util.h" 14#include "chrome/browser/chromeos/language_preferences.h" 15#include "chrome/browser/chromeos/login/screen_observer.h" 16#include "chrome/browser/prefs/pref_service.h" 17#include "chrome/common/pref_names.h" 18#include "grit/generated_resources.h" 19#include "views/controls/button/menu_button.h" 20#include "views/widget/widget_gtk.h" 21 22namespace { 23 24const int kLanguageMainMenuSize = 5; 25// TODO(glotov): need to specify the list as a part of the image customization. 26const char kLanguagesTopped[] = "es,it,de,fr,en-US"; 27const int kMoreLanguagesSubMenu = 200; 28 29} // namespace 30 31namespace chromeos { 32 33LanguageSwitchMenu::LanguageSwitchMenu() 34 : ALLOW_THIS_IN_INITIALIZER_LIST(menu_model_(this)), 35 ALLOW_THIS_IN_INITIALIZER_LIST(menu_model_submenu_(this)), 36 menu_alignment_(views::Menu2::ALIGN_TOPRIGHT) { 37} 38 39void LanguageSwitchMenu::InitLanguageMenu() { 40 // Update LanguageList to contain entries in current locale. 41 language_list_.reset(new LanguageList); 42 language_list_->CopySpecifiedLanguagesUp(kLanguagesTopped); 43 44 // Clear older menu items. 45 menu_model_.Clear(); 46 menu_model_submenu_.Clear(); 47 48 // Fill menu items with updated items. 49 for (int line = 0; line != kLanguageMainMenuSize; line++) { 50 menu_model_.AddItem(line, language_list_->GetLanguageNameAt(line)); 51 } 52 menu_model_.AddSeparator(); 53 menu_model_.AddSubMenuWithStringId(kMoreLanguagesSubMenu, 54 IDS_LANGUAGES_MORE, 55 &menu_model_submenu_); 56 for (int line = kLanguageMainMenuSize; 57 line != language_list_->get_languages_count(); line++) { 58 menu_model_submenu_.AddItem( 59 line, language_list_->GetLanguageNameAt(line)); 60 } 61 62 // Initialize menu here so it appears fast when called. 63 menu_.reset(new views::Menu2(&menu_model_)); 64} 65 66string16 LanguageSwitchMenu::GetCurrentLocaleName() const { 67 DCHECK(g_browser_process); 68 const std::string locale = g_browser_process->GetApplicationLocale(); 69 int index = language_list_->GetIndexFromLocale(locale); 70 CHECK_NE(-1, index) << "Unknown locale: " << locale; 71 return language_list_->GetLanguageNameAt(index); 72}; 73 74void LanguageSwitchMenu::SetFirstLevelMenuWidth(int width) { 75 DCHECK(menu_ != NULL); 76 menu_->SetMinimumWidth(width); 77} 78 79// static 80void LanguageSwitchMenu::SwitchLanguage(const std::string& locale) { 81 DCHECK(g_browser_process); 82 if (g_browser_process->GetApplicationLocale() == locale) { 83 return; 84 } 85 // Save new locale. 86 PrefService* prefs = g_browser_process->local_state(); 87 // TODO(markusheintz): If the preference is managed and can not be changed by 88 // the user, changing the language should be disabled in the UI. 89 // TODO(markusheintz): Change the if condition to prefs->IsUserModifiable() 90 // once Mattias landed his pending patch. 91 if (!prefs->IsManagedPreference(prefs::kApplicationLocale)) { 92 prefs->SetString(prefs::kApplicationLocale, locale); 93 prefs->SavePersistentPrefs(); 94 95 // Switch the locale. 96 const std::string loaded_locale = 97 ResourceBundle::ReloadSharedInstance(locale); 98 CHECK(!loaded_locale.empty()) << "Locale could not be found for " << locale; 99 100 // Enable the keyboard layouts that are necessary for the new locale. 101 input_method::EnableInputMethods( 102 locale, input_method::kKeyboardLayoutsOnly, 103 CrosLibrary::Get()->GetKeyboardLibrary()-> 104 GetHardwareKeyboardLayoutName()); 105 106 // The following line does not seem to affect locale anyhow. Maybe in 107 // future.. 108 g_browser_process->SetApplicationLocale(locale); 109 } 110} 111 112//////////////////////////////////////////////////////////////////////////////// 113// views::ViewMenuDelegate implementation. 114 115void LanguageSwitchMenu::RunMenu(views::View* source, const gfx::Point& pt) { 116 DCHECK(menu_ != NULL); 117 views::MenuButton* button = static_cast<views::MenuButton*>(source); 118 // We align the on left edge of the button for non RTL case. 119 gfx::Point new_pt(pt); 120 if (menu_alignment_ == views::Menu2::ALIGN_TOPLEFT) { 121 int reverse_offset = button->width() + button->menu_offset().x() * 2; 122 if (base::i18n::IsRTL()) { 123 new_pt.set_x(pt.x() + reverse_offset); 124 } else { 125 new_pt.set_x(pt.x() - reverse_offset); 126 } 127 } 128 menu_->RunMenuAt(new_pt, menu_alignment_); 129} 130 131//////////////////////////////////////////////////////////////////////////////// 132// menus::SimpleMenuModel::Delegate implementation. 133 134bool LanguageSwitchMenu::IsCommandIdChecked(int command_id) const { 135 return false; 136} 137 138bool LanguageSwitchMenu::IsCommandIdEnabled(int command_id) const { 139 return true; 140} 141 142bool LanguageSwitchMenu::GetAcceleratorForCommandId( 143 int command_id, menus::Accelerator* accelerator) { 144 return false; 145} 146 147void LanguageSwitchMenu::ExecuteCommand(int command_id) { 148 const std::string locale = language_list_->GetLocaleFromIndex(command_id); 149 SwitchLanguage(locale); 150 InitLanguageMenu(); 151 152 // Update all view hierarchies that the locale has changed. 153 views::Widget::NotifyLocaleChanged(); 154} 155 156} // namespace chromeos 157