OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/views/controls/combobox/combobox.h" | 5 #include "ui/views/controls/combobox/combobox.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 15 matching lines...) Expand all Loading... |
26 #include "ui/native_theme/common_theme.h" | 26 #include "ui/native_theme/common_theme.h" |
27 #include "ui/native_theme/native_theme.h" | 27 #include "ui/native_theme/native_theme.h" |
28 #include "ui/native_theme/native_theme_aura.h" | 28 #include "ui/native_theme/native_theme_aura.h" |
29 #include "ui/resources/grit/ui_resources.h" | 29 #include "ui/resources/grit/ui_resources.h" |
30 #include "ui/views/background.h" | 30 #include "ui/views/background.h" |
31 #include "ui/views/controls/button/custom_button.h" | 31 #include "ui/views/controls/button/custom_button.h" |
32 #include "ui/views/controls/button/label_button.h" | 32 #include "ui/views/controls/button/label_button.h" |
33 #include "ui/views/controls/combobox/combobox_listener.h" | 33 #include "ui/views/controls/combobox/combobox_listener.h" |
34 #include "ui/views/controls/focusable_border.h" | 34 #include "ui/views/controls/focusable_border.h" |
35 #include "ui/views/controls/menu/menu_config.h" | 35 #include "ui/views/controls/menu/menu_config.h" |
| 36 #include "ui/views/controls/menu/menu_model_adapter.h" |
36 #include "ui/views/controls/menu/menu_runner.h" | 37 #include "ui/views/controls/menu/menu_runner.h" |
37 #include "ui/views/controls/prefix_selector.h" | 38 #include "ui/views/controls/prefix_selector.h" |
38 #include "ui/views/controls/textfield/textfield.h" | 39 #include "ui/views/controls/textfield/textfield.h" |
39 #include "ui/views/mouse_constants.h" | 40 #include "ui/views/mouse_constants.h" |
40 #include "ui/views/painter.h" | 41 #include "ui/views/painter.h" |
41 #include "ui/views/resources/grit/views_resources.h" | 42 #include "ui/views/resources/grit/views_resources.h" |
42 #include "ui/views/style/platform_style.h" | 43 #include "ui/views/style/platform_style.h" |
43 #include "ui/views/widget/widget.h" | 44 #include "ui/views/widget/widget.h" |
44 | 45 |
45 namespace views { | 46 namespace views { |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 *arrow_button_images[2], | 243 *arrow_button_images[2], |
243 x, 0, arrow_button_images[0]->width(), height); | 244 x, 0, arrow_button_images[0]->width(), height); |
244 } | 245 } |
245 | 246 |
246 } // namespace | 247 } // namespace |
247 | 248 |
248 // static | 249 // static |
249 const char Combobox::kViewClassName[] = "views/Combobox"; | 250 const char Combobox::kViewClassName[] = "views/Combobox"; |
250 | 251 |
251 // Adapts a ui::ComboboxModel to a ui::MenuModel. | 252 // Adapts a ui::ComboboxModel to a ui::MenuModel. |
252 class Combobox::ComboboxMenuModelAdapter : public ui::MenuModel, | 253 class Combobox::ComboboxMenuModel : public ui::MenuModel, |
253 public ui::ComboboxModelObserver { | 254 public ui::ComboboxModelObserver { |
254 public: | 255 public: |
255 ComboboxMenuModelAdapter(Combobox* owner, ui::ComboboxModel* model) | 256 ComboboxMenuModel(Combobox* owner, ui::ComboboxModel* model) |
256 : owner_(owner), model_(model) { | 257 : owner_(owner), model_(model) { |
257 model_->AddObserver(this); | 258 model_->AddObserver(this); |
258 } | 259 } |
259 | 260 |
260 ~ComboboxMenuModelAdapter() override { model_->RemoveObserver(this); } | 261 ~ComboboxMenuModel() override { model_->RemoveObserver(this); } |
261 | 262 |
262 private: | 263 private: |
263 bool UseCheckmarks() const { | 264 bool UseCheckmarks() const { |
264 return owner_->style_ != STYLE_ACTION && | 265 return owner_->style_ != STYLE_ACTION && |
265 MenuConfig::instance().check_selected_combobox_item; | 266 MenuConfig::instance().check_selected_combobox_item; |
266 } | 267 } |
267 | 268 |
268 // Overridden from MenuModel: | 269 // Overridden from MenuModel: |
269 bool HasIcons() const override { return false; } | 270 bool HasIcons() const override { return false; } |
270 | 271 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 } | 350 } |
350 | 351 |
351 // Overridden from ComboboxModelObserver: | 352 // Overridden from ComboboxModelObserver: |
352 void OnComboboxModelChanged(ui::ComboboxModel* model) override { | 353 void OnComboboxModelChanged(ui::ComboboxModel* model) override { |
353 owner_->ModelChanged(); | 354 owner_->ModelChanged(); |
354 } | 355 } |
355 | 356 |
356 Combobox* owner_; // Weak. Owns this. | 357 Combobox* owner_; // Weak. Owns this. |
357 ui::ComboboxModel* model_; // Weak. | 358 ui::ComboboxModel* model_; // Weak. |
358 | 359 |
359 DISALLOW_COPY_AND_ASSIGN(ComboboxMenuModelAdapter); | 360 DISALLOW_COPY_AND_ASSIGN(ComboboxMenuModel); |
360 }; | 361 }; |
361 | 362 |
362 //////////////////////////////////////////////////////////////////////////////// | 363 //////////////////////////////////////////////////////////////////////////////// |
363 // Combobox, public: | 364 // Combobox, public: |
364 | 365 |
365 Combobox::Combobox(ui::ComboboxModel* model, Style style) | 366 Combobox::Combobox(ui::ComboboxModel* model, Style style) |
366 : model_(model), | 367 : model_(model), |
367 style_(style), | 368 style_(style), |
368 listener_(NULL), | 369 listener_(NULL), |
369 selected_index_(style == STYLE_ACTION ? 0 : model_->GetDefaultIndex()), | 370 selected_index_(style == STYLE_ACTION ? 0 : model_->GetDefaultIndex()), |
370 invalid_(false), | 371 invalid_(false), |
371 menu_model_adapter_(new ComboboxMenuModelAdapter(this, model)), | 372 menu_model_(new ComboboxMenuModel(this, model)), |
372 text_button_(new TransparentButton(this)), | 373 text_button_(new TransparentButton(this)), |
373 arrow_button_(new TransparentButton(this)), | 374 arrow_button_(new TransparentButton(this)), |
374 size_to_largest_label_(style_ == STYLE_NORMAL), | 375 size_to_largest_label_(style_ == STYLE_NORMAL), |
375 weak_ptr_factory_(this) { | 376 weak_ptr_factory_(this) { |
376 ModelChanged(); | 377 ModelChanged(); |
377 #if defined(OS_MACOSX) | 378 #if defined(OS_MACOSX) |
378 SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY); | 379 SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY); |
379 #else | 380 #else |
380 SetFocusBehavior(FocusBehavior::ALWAYS); | 381 SetFocusBehavior(FocusBehavior::ALWAYS); |
381 #endif | 382 #endif |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
839 if (arrow_button_) { | 840 if (arrow_button_) { |
840 original_state = arrow_button_->state(); | 841 original_state = arrow_button_->state(); |
841 arrow_button_->SetState(Button::STATE_PRESSED); | 842 arrow_button_->SetState(Button::STATE_PRESSED); |
842 } | 843 } |
843 MenuAnchorPosition anchor_position = | 844 MenuAnchorPosition anchor_position = |
844 style_ == STYLE_ACTION ? MENU_ANCHOR_TOPRIGHT : MENU_ANCHOR_TOPLEFT; | 845 style_ == STYLE_ACTION ? MENU_ANCHOR_TOPRIGHT : MENU_ANCHOR_TOPLEFT; |
845 | 846 |
846 // Allow |menu_runner_| to be set by the testing API, but if this method is | 847 // Allow |menu_runner_| to be set by the testing API, but if this method is |
847 // ever invoked recursively, ensure the old menu is closed. | 848 // ever invoked recursively, ensure the old menu is closed. |
848 if (!menu_runner_ || menu_runner_->IsRunning()) { | 849 if (!menu_runner_ || menu_runner_->IsRunning()) { |
| 850 menu_model_adapter_.reset(new MenuModelAdapter( |
| 851 menu_model_.get(), base::Bind(&Combobox::OnMenuClosed, |
| 852 base::Unretained(this), original_state))); |
849 menu_runner_.reset( | 853 menu_runner_.reset( |
850 new MenuRunner(menu_model_adapter_.get(), MenuRunner::COMBOBOX)); | 854 new MenuRunner(menu_model_adapter_->CreateMenu(), |
| 855 MenuRunner::COMBOBOX | MenuRunner::ASYNC)); |
851 } | 856 } |
852 if (menu_runner_->RunMenuAt(GetWidget(), nullptr, bounds, anchor_position, | 857 menu_runner_->RunMenuAt(GetWidget(), nullptr, bounds, anchor_position, |
853 source_type) == MenuRunner::MENU_DELETED) { | 858 source_type); |
854 return; | 859 } |
855 } | 860 |
| 861 void Combobox::OnMenuClosed(Button::ButtonState original_button_state) { |
856 menu_runner_.reset(); | 862 menu_runner_.reset(); |
| 863 menu_model_adapter_.reset(); |
857 if (arrow_button_) | 864 if (arrow_button_) |
858 arrow_button_->SetState(original_state); | 865 arrow_button_->SetState(original_button_state); |
859 closed_time_ = base::Time::Now(); | 866 closed_time_ = base::Time::Now(); |
860 | 867 |
861 // Need to explicitly clear mouse handler so that events get sent | 868 // Need to explicitly clear mouse handler so that events get sent |
862 // properly after the menu finishes running. If we don't do this, then | 869 // properly after the menu finishes running. If we don't do this, then |
863 // the first click to other parts of the UI is eaten. | 870 // the first click to other parts of the UI is eaten. |
864 SetMouseHandler(NULL); | 871 SetMouseHandler(NULL); |
865 } | 872 } |
866 | 873 |
867 void Combobox::OnPerformAction() { | 874 void Combobox::OnPerformAction() { |
868 NotifyAccessibilityEvent(ui::AX_EVENT_VALUE_CHANGED, false); | 875 NotifyAccessibilityEvent(ui::AX_EVENT_VALUE_CHANGED, false); |
(...skipping 15 matching lines...) Expand all Loading... |
884 gfx::Size Combobox::GetContentSize() const { | 891 gfx::Size Combobox::GetContentSize() const { |
885 const gfx::FontList& font_list = GetFontList(); | 892 const gfx::FontList& font_list = GetFontList(); |
886 | 893 |
887 int width = 0; | 894 int width = 0; |
888 for (int i = 0; i < model()->GetItemCount(); ++i) { | 895 for (int i = 0; i < model()->GetItemCount(); ++i) { |
889 if (model_->IsItemSeparatorAt(i)) | 896 if (model_->IsItemSeparatorAt(i)) |
890 continue; | 897 continue; |
891 | 898 |
892 if (size_to_largest_label_ || i == selected_index_) { | 899 if (size_to_largest_label_ || i == selected_index_) { |
893 width = std::max( | 900 width = std::max( |
894 width, | 901 width, gfx::GetStringWidth(menu_model_->GetLabelAt(i), font_list)); |
895 gfx::GetStringWidth(menu_model_adapter_->GetLabelAt(i), font_list)); | |
896 } | 902 } |
897 } | 903 } |
898 return gfx::Size(width, font_list.GetHeight()); | 904 return gfx::Size(width, font_list.GetHeight()); |
899 } | 905 } |
900 | 906 |
901 PrefixSelector* Combobox::GetPrefixSelector() { | 907 PrefixSelector* Combobox::GetPrefixSelector() { |
902 if (!selector_) | 908 if (!selector_) |
903 selector_.reset(new PrefixSelector(this)); | 909 selector_.reset(new PrefixSelector(this)); |
904 return selector_.get(); | 910 return selector_.get(); |
905 } | 911 } |
906 | 912 |
907 int Combobox::GetArrowContainerWidth() const { | 913 int Combobox::GetArrowContainerWidth() const { |
908 int padding = style_ == STYLE_NORMAL | 914 int padding = style_ == STYLE_NORMAL |
909 ? PlatformStyle::kComboboxNormalArrowPadding * 2 | 915 ? PlatformStyle::kComboboxNormalArrowPadding * 2 |
910 : kActionLeftPadding + kActionRightPadding; | 916 : kActionLeftPadding + kActionRightPadding; |
911 return ArrowSize().width() + padding; | 917 return ArrowSize().width() + padding; |
912 } | 918 } |
913 | 919 |
914 } // namespace views | 920 } // namespace views |
OLD | NEW |