| 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 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "build/build_config.h" | 13 #include "build/build_config.h" |
| 14 #include "ui/accessibility/ax_view_state.h" | 14 #include "ui/accessibility/ax_view_state.h" |
| 15 #include "ui/base/default_style.h" | 15 #include "ui/base/default_style.h" |
| 16 #include "ui/base/ime/input_method.h" | 16 #include "ui/base/ime/input_method.h" |
| 17 #include "ui/base/material_design/material_design_controller.h" |
| 17 #include "ui/base/models/combobox_model.h" | 18 #include "ui/base/models/combobox_model.h" |
| 18 #include "ui/base/models/combobox_model_observer.h" | 19 #include "ui/base/models/combobox_model_observer.h" |
| 19 #include "ui/base/resource/resource_bundle.h" | 20 #include "ui/base/resource/resource_bundle.h" |
| 20 #include "ui/events/event.h" | 21 #include "ui/events/event.h" |
| 21 #include "ui/gfx/animation/throb_animation.h" | 22 #include "ui/gfx/animation/throb_animation.h" |
| 22 #include "ui/gfx/canvas.h" | 23 #include "ui/gfx/canvas.h" |
| 23 #include "ui/gfx/color_palette.h" | 24 #include "ui/gfx/color_palette.h" |
| 24 #include "ui/gfx/scoped_canvas.h" | 25 #include "ui/gfx/scoped_canvas.h" |
| 25 #include "ui/gfx/text_utils.h" | 26 #include "ui/gfx/text_utils.h" |
| 26 #include "ui/native_theme/common_theme.h" | 27 #include "ui/native_theme/common_theme.h" |
| 27 #include "ui/native_theme/native_theme.h" | 28 #include "ui/native_theme/native_theme.h" |
| 28 #include "ui/native_theme/native_theme_aura.h" | 29 #include "ui/native_theme/native_theme_aura.h" |
| 29 #include "ui/resources/grit/ui_resources.h" | 30 #include "ui/resources/grit/ui_resources.h" |
| 31 #include "ui/views/animation/flood_fill_ink_drop_ripple.h" |
| 32 #include "ui/views/animation/ink_drop_highlight.h" |
| 30 #include "ui/views/background.h" | 33 #include "ui/views/background.h" |
| 31 #include "ui/views/controls/button/custom_button.h" | 34 #include "ui/views/controls/button/custom_button.h" |
| 32 #include "ui/views/controls/button/label_button.h" | 35 #include "ui/views/controls/button/label_button.h" |
| 33 #include "ui/views/controls/combobox/combobox_listener.h" | 36 #include "ui/views/controls/combobox/combobox_listener.h" |
| 34 #include "ui/views/controls/focusable_border.h" | 37 #include "ui/views/controls/focusable_border.h" |
| 35 #include "ui/views/controls/menu/menu_config.h" | 38 #include "ui/views/controls/menu/menu_config.h" |
| 36 #include "ui/views/controls/menu/menu_model_adapter.h" | 39 #include "ui/views/controls/menu/menu_model_adapter.h" |
| 37 #include "ui/views/controls/menu/menu_runner.h" | 40 #include "ui/views/controls/menu/menu_runner.h" |
| 38 #include "ui/views/controls/prefix_selector.h" | 41 #include "ui/views/controls/prefix_selector.h" |
| 39 #include "ui/views/controls/textfield/textfield.h" | 42 #include "ui/views/controls/textfield/textfield.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 const int kHoveredMenuButtonImages[] = MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_H); | 84 const int kHoveredMenuButtonImages[] = MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_H); |
| 82 const int kPressedMenuButtonImages[] = MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_P); | 85 const int kPressedMenuButtonImages[] = MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_P); |
| 83 const int kFocusedMenuButtonImages[] = MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_F); | 86 const int kFocusedMenuButtonImages[] = MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_F); |
| 84 const int kFocusedHoveredMenuButtonImages[] = | 87 const int kFocusedHoveredMenuButtonImages[] = |
| 85 MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_F_H); | 88 MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_F_H); |
| 86 const int kFocusedPressedMenuButtonImages[] = | 89 const int kFocusedPressedMenuButtonImages[] = |
| 87 MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_F_P); | 90 MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_F_P); |
| 88 | 91 |
| 89 #undef MENU_IMAGE_GRID | 92 #undef MENU_IMAGE_GRID |
| 90 | 93 |
| 94 bool UseMd() { |
| 95 return ui::MaterialDesignController::IsSecondaryUiMaterial(); |
| 96 } |
| 97 |
| 91 gfx::Rect PositionArrowWithinContainer(const gfx::Rect& container_bounds, | 98 gfx::Rect PositionArrowWithinContainer(const gfx::Rect& container_bounds, |
| 92 const gfx::Size& arrow_size, | 99 const gfx::Size& arrow_size, |
| 93 Combobox::Style style) { | 100 Combobox::Style style) { |
| 94 gfx::Rect bounds(container_bounds); | 101 gfx::Rect bounds(container_bounds); |
| 95 if (style == Combobox::STYLE_ACTION) { | 102 if (style == Combobox::STYLE_ACTION) { |
| 96 // This positions the arrow horizontally. The later call to | 103 // This positions the arrow horizontally. The later call to |
| 97 // ClampToCenteredSize will position it vertically without touching the | 104 // ClampToCenteredSize will position it vertically without touching the |
| 98 // horizontal position. | 105 // horizontal position. |
| 99 bounds.Inset(kActionLeftPadding, 0, kActionRightPadding, 0); | 106 bounds.Inset(kActionLeftPadding, 0, kActionRightPadding, 0); |
| 100 DCHECK_EQ(bounds.width(), arrow_size.width()); | 107 DCHECK_EQ(bounds.width(), arrow_size.width()); |
| 101 } | 108 } |
| 102 | 109 |
| 103 bounds.ClampToCenteredSize(arrow_size); | 110 bounds.ClampToCenteredSize(arrow_size); |
| 104 return bounds; | 111 return bounds; |
| 105 } | 112 } |
| 106 | 113 |
| 107 // The transparent button which holds a button state but is not rendered. | 114 // The transparent button which holds a button state but is not rendered. |
| 108 class TransparentButton : public CustomButton { | 115 class TransparentButton : public CustomButton { |
| 109 public: | 116 public: |
| 110 TransparentButton(ButtonListener* listener) | 117 TransparentButton(ButtonListener* listener) |
| 111 : CustomButton(listener) { | 118 : CustomButton(listener) { |
| 112 SetAnimationDuration(LabelButton::kHoverAnimationDurationMs); | 119 SetAnimationDuration(LabelButton::kHoverAnimationDurationMs); |
| 113 SetFocusBehavior(FocusBehavior::NEVER); | 120 SetFocusBehavior(FocusBehavior::NEVER); |
| 114 set_notify_action(PlatformStyle::kMenuNotifyActivationAction); | 121 set_notify_action(PlatformStyle::kMenuNotifyActivationAction); |
| 122 |
| 123 if (UseMd()) { |
| 124 SetInkDropMode(PlatformStyle::kUseRipples ? InkDropMode::ON |
| 125 : InkDropMode::OFF); |
| 126 set_has_ink_drop_action_on_click(true); |
| 127 } |
| 115 } | 128 } |
| 116 ~TransparentButton() override {} | 129 ~TransparentButton() override {} |
| 117 | 130 |
| 118 #if !defined(OS_MACOSX) | |
| 119 // Override OnMousePressed() to transfer focus to the parent() on a click | |
| 120 // except on Mac, which doesn't transfer focus when buttons are clicked. | |
| 121 bool OnMousePressed(const ui::MouseEvent& mouse_event) override { | 131 bool OnMousePressed(const ui::MouseEvent& mouse_event) override { |
| 122 parent()->RequestFocus(); | 132 if (!UseMd()) |
| 123 return true; | 133 parent()->RequestFocus(); |
| 134 return CustomButton::OnMousePressed(mouse_event); |
| 124 } | 135 } |
| 125 #endif | |
| 126 | 136 |
| 127 double GetAnimationValue() const { | 137 double GetAnimationValue() const { |
| 128 return hover_animation().GetCurrentValue(); | 138 return hover_animation().GetCurrentValue(); |
| 129 } | 139 } |
| 130 | 140 |
| 141 // Overridden from InkDropHost: |
| 142 std::unique_ptr<InkDropRipple> CreateInkDropRipple() const override { |
| 143 return std::unique_ptr<views::InkDropRipple>( |
| 144 new views::FloodFillInkDropRipple( |
| 145 GetLocalBounds(), GetInkDropCenterBasedOnLastEvent(), |
| 146 GetNativeTheme()->GetSystemColor( |
| 147 ui::NativeTheme::kColorId_LabelEnabledColor), |
| 148 ink_drop_visible_opacity())); |
| 149 } |
| 150 |
| 151 std::unique_ptr<InkDropHighlight> CreateInkDropHighlight() const override { |
| 152 return nullptr; |
| 153 } |
| 154 |
| 131 private: | 155 private: |
| 132 DISALLOW_COPY_AND_ASSIGN(TransparentButton); | 156 DISALLOW_COPY_AND_ASSIGN(TransparentButton); |
| 133 }; | 157 }; |
| 134 | 158 |
| 135 // Returns the next or previous valid index (depending on |increment|'s value). | 159 // Returns the next or previous valid index (depending on |increment|'s value). |
| 136 // Skips separator or disabled indices. Returns -1 if there is no valid adjacent | 160 // Skips separator or disabled indices. Returns -1 if there is no valid adjacent |
| 137 // index. | 161 // index. |
| 138 int GetAdjacentIndex(ui::ComboboxModel* model, int increment, int index) { | 162 int GetAdjacentIndex(ui::ComboboxModel* model, int increment, int index) { |
| 139 DCHECK(increment == -1 || increment == 1); | 163 DCHECK(increment == -1 || increment == 1); |
| 140 | 164 |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 if (invalid == invalid_) | 498 if (invalid == invalid_) |
| 475 return; | 499 return; |
| 476 | 500 |
| 477 invalid_ = invalid; | 501 invalid_ = invalid; |
| 478 | 502 |
| 479 UpdateBorder(); | 503 UpdateBorder(); |
| 480 SchedulePaint(); | 504 SchedulePaint(); |
| 481 } | 505 } |
| 482 | 506 |
| 483 void Combobox::Layout() { | 507 void Combobox::Layout() { |
| 484 PrefixDelegate::Layout(); | 508 View::Layout(); |
| 485 | 509 |
| 486 int text_button_width = 0; | 510 int text_button_width = 0; |
| 487 int arrow_button_width = 0; | 511 int arrow_button_width = 0; |
| 488 | 512 |
| 489 switch (style_) { | 513 switch (style_) { |
| 490 case STYLE_NORMAL: { | 514 case STYLE_NORMAL: { |
| 491 arrow_button_width = width(); | 515 arrow_button_width = width(); |
| 492 break; | 516 break; |
| 493 } | 517 } |
| 494 case STYLE_ACTION: { | 518 case STYLE_ACTION: { |
| 495 arrow_button_width = GetArrowContainerWidth(); | 519 arrow_button_width = GetArrowContainerWidth(); |
| 496 text_button_width = width() - arrow_button_width; | 520 text_button_width = width() - arrow_button_width; |
| 497 break; | 521 break; |
| 498 } | 522 } |
| 499 } | 523 } |
| 500 | 524 |
| 501 int arrow_button_x = std::max(0, text_button_width); | 525 int arrow_button_x = std::max(0, text_button_width); |
| 502 text_button_->SetBounds(0, 0, std::max(0, text_button_width), height()); | 526 text_button_->SetBounds(0, 0, std::max(0, text_button_width), height()); |
| 503 arrow_button_->SetBounds(arrow_button_x, 0, arrow_button_width, height()); | 527 arrow_button_->SetBounds(arrow_button_x, 0, arrow_button_width, height()); |
| 504 } | 528 } |
| 505 | 529 |
| 506 void Combobox::OnEnabledChanged() { | 530 void Combobox::OnEnabledChanged() { |
| 507 PrefixDelegate::OnEnabledChanged(); | 531 View::OnEnabledChanged(); |
| 508 arrow_image_ = PlatformStyle::CreateComboboxArrow(enabled(), style_); | 532 arrow_image_ = PlatformStyle::CreateComboboxArrow(enabled(), style_); |
| 509 } | 533 } |
| 510 | 534 |
| 511 int Combobox::GetRowCount() { | 535 int Combobox::GetRowCount() { |
| 512 return model()->GetItemCount(); | 536 return model()->GetItemCount(); |
| 513 } | 537 } |
| 514 | 538 |
| 515 int Combobox::GetSelectedRow() { | 539 int Combobox::GetSelectedRow() { |
| 516 return selected_index_; | 540 return selected_index_; |
| 517 } | 541 } |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 state->name = accessible_name_; | 709 state->name = accessible_name_; |
| 686 state->value = model_->GetItemAt(selected_index_); | 710 state->value = model_->GetItemAt(selected_index_); |
| 687 state->index = selected_index_; | 711 state->index = selected_index_; |
| 688 state->count = model_->GetItemCount(); | 712 state->count = model_->GetItemCount(); |
| 689 } | 713 } |
| 690 | 714 |
| 691 void Combobox::ButtonPressed(Button* sender, const ui::Event& event) { | 715 void Combobox::ButtonPressed(Button* sender, const ui::Event& event) { |
| 692 if (!enabled()) | 716 if (!enabled()) |
| 693 return; | 717 return; |
| 694 | 718 |
| 695 RequestFocus(); | 719 if (!UseMd()) |
| 720 RequestFocus(); |
| 696 | 721 |
| 697 if (sender == text_button_) { | 722 if (sender == text_button_) { |
| 698 OnPerformAction(); | 723 OnPerformAction(); |
| 699 } else { | 724 } else { |
| 700 DCHECK_EQ(arrow_button_, sender); | 725 DCHECK_EQ(arrow_button_, sender); |
| 701 // TODO(hajimehoshi): Fix the problem that the arrow button blinks when | 726 // TODO(hajimehoshi): Fix the problem that the arrow button blinks when |
| 702 // cliking this while the dropdown menu is opened. | 727 // cliking this while the dropdown menu is opened. |
| 703 const base::TimeDelta delta = base::Time::Now() - closed_time_; | 728 const base::TimeDelta delta = base::Time::Now() - closed_time_; |
| 704 if (delta.InMilliseconds() <= kMinimumMsBetweenButtonClicks) | 729 if (delta.InMilliseconds() <= kMinimumMsBetweenButtonClicks) |
| 705 return; | 730 return; |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 899 if (size_to_largest_label_ || i == selected_index_) { | 924 if (size_to_largest_label_ || i == selected_index_) { |
| 900 width = std::max( | 925 width = std::max( |
| 901 width, gfx::GetStringWidth(menu_model_->GetLabelAt(i), font_list)); | 926 width, gfx::GetStringWidth(menu_model_->GetLabelAt(i), font_list)); |
| 902 } | 927 } |
| 903 } | 928 } |
| 904 return gfx::Size(width, font_list.GetHeight()); | 929 return gfx::Size(width, font_list.GetHeight()); |
| 905 } | 930 } |
| 906 | 931 |
| 907 PrefixSelector* Combobox::GetPrefixSelector() { | 932 PrefixSelector* Combobox::GetPrefixSelector() { |
| 908 if (!selector_) | 933 if (!selector_) |
| 909 selector_.reset(new PrefixSelector(this)); | 934 selector_.reset(new PrefixSelector(this, this)); |
| 910 return selector_.get(); | 935 return selector_.get(); |
| 911 } | 936 } |
| 912 | 937 |
| 913 int Combobox::GetArrowContainerWidth() const { | 938 int Combobox::GetArrowContainerWidth() const { |
| 914 int padding = style_ == STYLE_NORMAL | 939 int padding = style_ == STYLE_NORMAL |
| 915 ? PlatformStyle::kComboboxNormalArrowPadding * 2 | 940 ? PlatformStyle::kComboboxNormalArrowPadding * 2 |
| 916 : kActionLeftPadding + kActionRightPadding; | 941 : kActionLeftPadding + kActionRightPadding; |
| 917 return ArrowSize().width() + padding; | 942 return ArrowSize().width() + padding; |
| 918 } | 943 } |
| 919 | 944 |
| 920 } // namespace views | 945 } // namespace views |
| OLD | NEW |