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