OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/status/input_method_menu.h" | 5 #include "chrome/browser/chromeos/status/input_method_menu.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/string_split.h" | 10 #include "base/string_split.h" |
11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
12 #include "base/time.h" | 12 #include "base/time.h" |
13 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
14 #include "chrome/browser/browser_process.h" | 14 #include "chrome/browser/browser_process.h" |
15 #include "chrome/browser/chromeos/cros/cros_library.h" | 15 #include "chrome/browser/chromeos/cros/cros_library.h" |
16 #include "chrome/browser/chromeos/input_method/input_method_util.h" | 16 #include "chrome/browser/chromeos/input_method/input_method_util.h" |
17 #include "chrome/browser/chromeos/language_preferences.h" | 17 #include "chrome/browser/chromeos/language_preferences.h" |
18 #include "chrome/browser/prefs/pref_service.h" | 18 #include "chrome/browser/prefs/pref_service.h" |
19 #include "chrome/common/pref_names.h" | 19 #include "chrome/common/pref_names.h" |
20 #include "content/browser/user_metrics.h" | 20 #include "content/browser/user_metrics.h" |
21 #include "content/common/notification_service.h" | 21 #include "content/common/notification_service.h" |
22 #include "grit/generated_resources.h" | 22 #include "grit/generated_resources.h" |
23 #include "grit/theme_resources.h" | 23 #include "grit/theme_resources.h" |
24 #include "ui/base/l10n/l10n_util.h" | 24 #include "ui/base/l10n/l10n_util.h" |
| 25 #include "ui/base/models/simple_menu_model.h" |
25 #include "ui/base/resource/resource_bundle.h" | 26 #include "ui/base/resource/resource_bundle.h" |
| 27 #include "views/controls/menu/menu_model_adapter.h" |
| 28 #include "views/controls/menu/submenu_view.h" |
| 29 #include "views/window/window.h" |
26 | 30 |
27 // The language menu consists of 3 parts (in this order): | 31 // The language menu consists of 3 parts (in this order): |
28 // | 32 // |
29 // (1) input method names. The size of the list is always >= 1. | 33 // (1) input method names. The size of the list is always >= 1. |
30 // (2) input method properties. This list might be empty. | 34 // (2) input method properties. This list might be empty. |
31 // (3) "Customize language and input..." button. | 35 // (3) "Customize language and input..." button. |
32 // | 36 // |
33 // Example of the menu (Japanese): | 37 // Example of the menu (Japanese): |
34 // | 38 // |
35 // ============================== (border of the popup window) | 39 // ============================== (border of the popup window) |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 | 125 |
122 //////////////////////////////////////////////////////////////////////////////// | 126 //////////////////////////////////////////////////////////////////////////////// |
123 // InputMethodMenu | 127 // InputMethodMenu |
124 | 128 |
125 InputMethodMenu::InputMethodMenu(PrefService* pref_service, | 129 InputMethodMenu::InputMethodMenu(PrefService* pref_service, |
126 StatusAreaHost::ScreenMode screen_mode, | 130 StatusAreaHost::ScreenMode screen_mode, |
127 bool for_out_of_box_experience_dialog) | 131 bool for_out_of_box_experience_dialog) |
128 : input_method_descriptors_(CrosLibrary::Get()->GetInputMethodLibrary()-> | 132 : input_method_descriptors_(CrosLibrary::Get()->GetInputMethodLibrary()-> |
129 GetActiveInputMethods()), | 133 GetActiveInputMethods()), |
130 model_(NULL), | 134 model_(NULL), |
131 // Be aware that the constructor of |input_method_menu_| calls | 135 ALLOW_THIS_IN_INITIALIZER_LIST(input_method_menu_delegate_( |
132 // GetItemCount() in this class. Therefore, GetItemCount() have to return | 136 new views::MenuModelAdapter(this))), |
133 // 0 when |model_| is NULL. | |
134 ALLOW_THIS_IN_INITIALIZER_LIST(input_method_menu_(this)), | |
135 minimum_input_method_menu_width_(0), | 137 minimum_input_method_menu_width_(0), |
| 138 menu_alignment_(views::MenuItemView::TOPRIGHT), |
136 pref_service_(pref_service), | 139 pref_service_(pref_service), |
137 screen_mode_(screen_mode), | 140 screen_mode_(screen_mode), |
138 for_out_of_box_experience_dialog_(for_out_of_box_experience_dialog) { | 141 for_out_of_box_experience_dialog_(for_out_of_box_experience_dialog) { |
139 DCHECK(input_method_descriptors_.get() && | 142 DCHECK(input_method_descriptors_.get() && |
140 !input_method_descriptors_->empty()); | 143 !input_method_descriptors_->empty()); |
141 | 144 |
142 // Sync current and previous input methods on Chrome prefs with ibus-daemon. | 145 // Sync current and previous input methods on Chrome prefs with ibus-daemon. |
143 if (pref_service_ && (screen_mode_ == StatusAreaHost::kBrowserMode)) { | 146 if (pref_service_ && (screen_mode_ == StatusAreaHost::kBrowserMode)) { |
144 previous_input_method_pref_.Init( | 147 previous_input_method_pref_.Init( |
145 prefs::kLanguagePreviousInputMethod, pref_service, this); | 148 prefs::kLanguagePreviousInputMethod, pref_service, this); |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 } | 363 } |
361 return; | 364 return; |
362 } | 365 } |
363 | 366 |
364 LOG(ERROR) << "Unexpected index: " << index; | 367 LOG(ERROR) << "Unexpected index: " << index; |
365 } | 368 } |
366 | 369 |
367 //////////////////////////////////////////////////////////////////////////////// | 370 //////////////////////////////////////////////////////////////////////////////// |
368 // views::ViewMenuDelegate implementation: | 371 // views::ViewMenuDelegate implementation: |
369 | 372 |
370 void InputMethodMenu::RunMenu( | 373 void InputMethodMenu::RunMenu(views::View* source, const gfx::Point& pt) { |
371 views::View* unused_source, const gfx::Point& pt) { | |
372 PrepareForMenuOpen(); | 374 PrepareForMenuOpen(); |
373 input_method_menu_.RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT); | 375 |
| 376 views::MenuItemView menu(input_method_menu_delegate_.get()); |
| 377 input_method_menu_delegate_->BuildMenu(&menu); |
| 378 if (minimum_input_method_menu_width_ > 0) { |
| 379 DCHECK(menu.HasSubmenu()); |
| 380 views::SubmenuView* submenu = menu.GetSubmenu(); |
| 381 submenu->set_minimum_preferred_width(minimum_input_method_menu_width_); |
| 382 } |
| 383 |
| 384 // TODO(rhashimoto): Remove this workaround when WebUI provides a |
| 385 // top-level widget on the ChromeOS login screen that is a window. |
| 386 // The current BackgroundView class for the ChromeOS login screen |
| 387 // creates a owning Widget that has a native GtkWindow but is not a |
| 388 // Window. This makes it impossible to get the NativeWindow via |
| 389 // the views API. This workaround casts the top-level NativeWidget |
| 390 // to a NativeWindow that we can pass to MenuItemView::RunMenuAt(). |
| 391 gfx::NativeWindow window = GTK_WINDOW(source->GetWidget()->GetNativeView()); |
| 392 |
| 393 menu.RunMenuAt(window, NULL, |
| 394 gfx::Rect(pt, gfx::Size(0, 0)), |
| 395 menu_alignment_, |
| 396 true); |
374 } | 397 } |
375 | 398 |
376 //////////////////////////////////////////////////////////////////////////////// | 399 //////////////////////////////////////////////////////////////////////////////// |
377 // InputMethodLibrary::Observer implementation: | 400 // InputMethodLibrary::Observer implementation: |
378 | 401 |
379 void InputMethodMenu::InputMethodChanged( | 402 void InputMethodMenu::InputMethodChanged( |
380 InputMethodLibrary* obj, | 403 InputMethodLibrary* obj, |
381 const InputMethodDescriptor& current_input_method, | 404 const InputMethodDescriptor& current_input_method, |
382 size_t num_active_input_methods) { | 405 size_t num_active_input_methods) { |
383 UpdateUIFromInputMethod(current_input_method, num_active_input_methods); | 406 UpdateUIFromInputMethod(current_input_method, num_active_input_methods); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 const std::string current_input_method_id = | 468 const std::string current_input_method_id = |
446 current_input_method_pref_.GetValue(); | 469 current_input_method_pref_.GetValue(); |
447 if (!current_input_method_id.empty()) { | 470 if (!current_input_method_id.empty()) { |
448 library->ChangeInputMethod(current_input_method_id); | 471 library->ChangeInputMethod(current_input_method_id); |
449 } | 472 } |
450 } | 473 } |
451 } | 474 } |
452 | 475 |
453 void InputMethodMenu::PrepareForMenuOpen() { | 476 void InputMethodMenu::PrepareForMenuOpen() { |
454 UserMetrics::RecordAction(UserMetricsAction("LanguageMenuButton_Open")); | 477 UserMetrics::RecordAction(UserMetricsAction("LanguageMenuButton_Open")); |
455 PrepareMenu(); | 478 PrepareMenuModel(); |
456 } | 479 } |
457 | 480 |
458 void InputMethodMenu::PrepareMenu() { | 481 void InputMethodMenu::PrepareMenuModel() { |
459 input_method_descriptors_.reset(CrosLibrary::Get()->GetInputMethodLibrary()-> | 482 input_method_descriptors_.reset(CrosLibrary::Get()->GetInputMethodLibrary()-> |
460 GetActiveInputMethods()); | 483 GetActiveInputMethods()); |
461 RebuildModel(); | 484 RebuildModel(); |
462 input_method_menu_.Rebuild(); | |
463 if (minimum_input_method_menu_width_ > 0) { | |
464 input_method_menu_.SetMinimumWidth(minimum_input_method_menu_width_); | |
465 } | |
466 } | 485 } |
467 | 486 |
468 void InputMethodMenu::ActiveInputMethodsChanged( | 487 void InputMethodMenu::ActiveInputMethodsChanged( |
469 InputMethodLibrary* obj, | 488 InputMethodLibrary* obj, |
470 const InputMethodDescriptor& current_input_method, | 489 const InputMethodDescriptor& current_input_method, |
471 size_t num_active_input_methods) { | 490 size_t num_active_input_methods) { |
472 // Update the icon if active input methods are changed. See also | 491 // Update the icon if active input methods are changed. See also |
473 // comments in UpdateUI() in input_method_menu_button.cc. | 492 // comments in UpdateUI() in input_method_menu_button.cc. |
474 UpdateUIFromInputMethod(current_input_method, num_active_input_methods); | 493 UpdateUIFromInputMethod(current_input_method, num_active_input_methods); |
475 } | 494 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 | 532 |
514 if (ShouldSupportConfigUI()) { | 533 if (ShouldSupportConfigUI()) { |
515 // Note: We use AddSeparator() for separators, and AddRadioItem() for all | 534 // Note: We use AddSeparator() for separators, and AddRadioItem() for all |
516 // other items even if an item is not actually a radio item. | 535 // other items even if an item is not actually a radio item. |
517 if (need_separator) { | 536 if (need_separator) { |
518 model_->AddSeparator(); | 537 model_->AddSeparator(); |
519 } | 538 } |
520 model_->AddRadioItem(COMMAND_ID_CUSTOMIZE_LANGUAGE, dummy_label, | 539 model_->AddRadioItem(COMMAND_ID_CUSTOMIZE_LANGUAGE, dummy_label, |
521 0 /* dummy */); | 540 0 /* dummy */); |
522 } | 541 } |
| 542 |
| 543 // Wrap new model with views::MenuDelegate interface. |
| 544 input_method_menu_delegate_.reset(new views::MenuModelAdapter(this)); |
523 } | 545 } |
524 | 546 |
525 bool InputMethodMenu::IndexIsInInputMethodList(int index) const { | 547 bool InputMethodMenu::IndexIsInInputMethodList(int index) const { |
526 DCHECK_GE(index, 0); | 548 DCHECK_GE(index, 0); |
527 DCHECK(model_.get()); | 549 DCHECK(model_.get()); |
528 if (index >= model_->GetItemCount()) { | 550 if (index >= model_->GetItemCount()) { |
529 return false; | 551 return false; |
530 } | 552 } |
531 | 553 |
532 return ((model_->GetTypeAt(index) == ui::MenuModel::TYPE_RADIO) && | 554 return ((model_->GetTypeAt(index) == ui::MenuModel::TYPE_RADIO) && |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 CrosLibrary::Get()->GetInputMethodLibrary()->RemoveObserver(this); | 685 CrosLibrary::Get()->GetInputMethodLibrary()->RemoveObserver(this); |
664 } | 686 } |
665 } | 687 } |
666 | 688 |
667 void InputMethodMenu::SetMinimumWidth(int width) { | 689 void InputMethodMenu::SetMinimumWidth(int width) { |
668 // On the OOBE network selection screen, fixed width menu would be preferable. | 690 // On the OOBE network selection screen, fixed width menu would be preferable. |
669 minimum_input_method_menu_width_ = width; | 691 minimum_input_method_menu_width_ = width; |
670 } | 692 } |
671 | 693 |
672 } // namespace chromeos | 694 } // namespace chromeos |
OLD | NEW |