| Index: ui/views/controls/combobox/combobox.cc
|
| diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc
|
| index 2600b174f07d27d2e9f3f8511ca71049270a444c..21dcf3e0c8952ec4f8bbcd5250c0a53911d30cfd 100644
|
| --- a/ui/views/controls/combobox/combobox.cc
|
| +++ b/ui/views/controls/combobox/combobox.cc
|
| @@ -12,9 +12,12 @@
|
| #include "ui/base/resource/resource_bundle.h"
|
| #include "ui/events/event.h"
|
| #include "ui/events/keycodes/keyboard_codes.h"
|
| +#include "ui/gfx/animation/slide_animation.h"
|
| #include "ui/gfx/canvas.h"
|
| +#include "ui/gfx/image/image.h"
|
| #include "ui/native_theme/native_theme.h"
|
| #include "ui/views/color_constants.h"
|
| +#include "ui/views/controls/button/custom_button.h"
|
| #include "ui/views/controls/combobox/combobox_listener.h"
|
| #include "ui/views/controls/focusable_border.h"
|
| #include "ui/views/controls/menu/menu_runner.h"
|
| @@ -22,6 +25,7 @@
|
| #include "ui/views/controls/prefix_selector.h"
|
| #include "ui/views/ime/input_method.h"
|
| #include "ui/views/mouse_constants.h"
|
| +#include "ui/views/painter.h"
|
| #include "ui/views/widget/widget.h"
|
|
|
| namespace views {
|
| @@ -39,6 +43,8 @@ const int kMinComboboxWidth = 25;
|
| // Size of the combobox arrow margins
|
| const int kDisclosureArrowLeftPadding = 7;
|
| const int kDisclosureArrowRightPadding = 7;
|
| +const int kDisclosureArrowButtonLeftPadding = 11;
|
| +const int kDisclosureArrowButtonRightPadding = 12;
|
|
|
| // Define the id of the first item in the menu (since it needs to be > 0)
|
| const int kFirstMenuItemId = 1000;
|
| @@ -48,6 +54,22 @@ const SkColor kInvalidTextColor = SK_ColorWHITE;
|
| // Used to indicate that no item is currently selected by the user.
|
| const int kNoSelection = -1;
|
|
|
| +const int kBodyButtonImages[] = IMAGE_GRID(IDR_COMBOBOX_BUTTON);
|
| +const int kHoveredBodyButtonImages[] = IMAGE_GRID2(IDR_COMBOBOX_BUTTON, H);
|
| +const int kPressedBodyButtonImages[] = IMAGE_GRID2(IDR_COMBOBOX_BUTTON, P);
|
| +
|
| +#define MENU_IMAGE_GRID(x) { \
|
| + x ## _MENU_TOP, x ## _MENU_CENTER, x ## _MENU_BOTTOM, }
|
| +#define MENU_IMAGE_GRID2(x, y) { \
|
| + x ## _MENU_TOP_ ## y, x ## _MENU_CENTER_ ## y, x ## _MENU_BOTTOM_ ## y, }
|
| +
|
| +const int kMenuButtonImages[] = MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON);
|
| +const int kHoveredMenuButtonImages[] = MENU_IMAGE_GRID2(IDR_COMBOBOX_BUTTON, H);
|
| +const int kPressedMenuButtonImages[] = MENU_IMAGE_GRID2(IDR_COMBOBOX_BUTTON, P);
|
| +
|
| +#undef MENU_IMAGE_GRID
|
| +#undef MENU_IMAGE_GRID2
|
| +
|
| // The background to use for invalid comboboxes.
|
| class InvalidBackground : public Background {
|
| public:
|
| @@ -81,6 +103,132 @@ int GetAdjacentIndex(ui::ComboboxModel* model, int increment, int index) {
|
| return kNoSelection;
|
| }
|
|
|
| +// Returns the image resource ids of an array for the body button.
|
| +//
|
| +// TODO(hajimehoshi): This function should return the images for the 'disabled'
|
| +// status. (crbug/270052)
|
| +//
|
| +// TODO(hajimehoshi): Currently, |focused| is ignored. This should return the
|
| +// images for the 'focused' status. (crbug/270052)
|
| +const int* GetBodyButtonImageIds(bool focused, Button::ButtonState state) {
|
| + switch (state) {
|
| + case Button::STATE_DISABLED:
|
| + return kBodyButtonImages;
|
| + case Button::STATE_NORMAL:
|
| + return kBodyButtonImages;
|
| + case Button::STATE_HOVERED:
|
| + return kHoveredBodyButtonImages;
|
| + case Button::STATE_PRESSED:
|
| + return kPressedBodyButtonImages;
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +// Returns the image resource ids of an array for the menu button.
|
| +const int* GetMenuButtonImageIds(bool focused, Button::ButtonState state) {
|
| + switch (state) {
|
| + case Button::STATE_DISABLED:
|
| + return kMenuButtonImages;
|
| + case Button::STATE_NORMAL:
|
| + return kMenuButtonImages;
|
| + case Button::STATE_HOVERED:
|
| + return kHoveredMenuButtonImages;
|
| + case Button::STATE_PRESSED:
|
| + return kPressedMenuButtonImages;
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +// Returns the images for the buttons.
|
| +std::vector<const gfx::ImageSkia*> GetButtonImages(bool menu,
|
| + bool focused,
|
| + Button::ButtonState state) {
|
| + const int* ids;
|
| + size_t num_ids;
|
| + if (!menu) {
|
| + ids = GetBodyButtonImageIds(focused, state);
|
| + num_ids = 9;
|
| + } else {
|
| + ids = GetMenuButtonImageIds(focused, state);
|
| + num_ids = 3;
|
| + }
|
| + std::vector<const gfx::ImageSkia*> images;
|
| + images.reserve(num_ids);
|
| + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| + for (size_t i = 0; i < num_ids; i++) {
|
| + int id = ids[i];
|
| + images.push_back(rb.GetImageSkiaNamed(id));
|
| + }
|
| + return images;
|
| +}
|
| +
|
| +// Paints three images in a row at the given location.
|
| +void PaintTandemImages(gfx::Canvas* canvas,
|
| + const gfx::ImageSkia& top_image,
|
| + const gfx::ImageSkia& center_image,
|
| + const gfx::ImageSkia& bottom_image,
|
| + int x, int y, int width, int height) {
|
| + canvas->DrawImageInt(top_image,
|
| + 0, 0, top_image.width(), top_image.height(),
|
| + x, y, width, top_image.height(), false);
|
| + y += top_image.height();
|
| + int center_height = height - top_image.height() - bottom_image.height();
|
| + canvas->DrawImageInt(center_image,
|
| + 0, 0, center_image.width(), center_image.height(),
|
| + x, y, width, center_height, false);
|
| + y += center_height;
|
| + canvas->DrawImageInt(bottom_image,
|
| + 0, 0, bottom_image.width(), bottom_image.height(),
|
| + x, y, width, bottom_image.height(), false);
|
| +}
|
| +
|
| +// Paints the text button.
|
| +void PaintTextButton(
|
| + gfx::Canvas* canvas,
|
| + const std::vector<const gfx::ImageSkia*>& text_button_images,
|
| + int width, int height) {
|
| + int current_x = 0;
|
| + int current_width = text_button_images[0]->width();
|
| + PaintTandemImages(canvas,
|
| + *text_button_images[0],
|
| + *text_button_images[3],
|
| + *text_button_images[6],
|
| + current_x, 0, current_width, height);
|
| +
|
| + current_x += current_width;
|
| + current_width = width - text_button_images[0]->width() -
|
| + text_button_images[2]->width();
|
| + PaintTandemImages(canvas,
|
| + *text_button_images[1],
|
| + *text_button_images[4],
|
| + *text_button_images[7],
|
| + current_x, 0, current_width, height);
|
| +
|
| + current_x += current_width;
|
| + current_width = text_button_images[2]->width();
|
| + PaintTandemImages(canvas,
|
| + *text_button_images[2],
|
| + *text_button_images[5],
|
| + *text_button_images[8],
|
| + current_x, 0, current_width, height);
|
| +}
|
| +
|
| +// Paints the arrow button.
|
| +void PaintArrowButton(
|
| + gfx::Canvas* canvas,
|
| + const std::vector<const gfx::ImageSkia*>& arrow_button_images,
|
| + int x, int height) {
|
| + PaintTandemImages(canvas,
|
| + *arrow_button_images[0],
|
| + *arrow_button_images[1],
|
| + *arrow_button_images[2],
|
| + x, 0, arrow_button_images[0]->width(), height);
|
| +}
|
| +
|
| } // namespace
|
|
|
| // static
|
| @@ -91,17 +239,46 @@ const char Combobox::kViewClassName[] = "views/Combobox";
|
|
|
| Combobox::Combobox(ui::ComboboxModel* model)
|
| : model_(model),
|
| + style_(STYLE_NORMAL),
|
| listener_(NULL),
|
| selected_index_(model_->GetDefaultIndex()),
|
| invalid_(false),
|
| text_border_(new FocusableBorder()),
|
| disclosure_arrow_(ui::ResourceBundle::GetSharedInstance().GetImageNamed(
|
| IDR_MENU_DROPARROW).ToImageSkia()),
|
| - dropdown_open_(false) {
|
| + dropdown_open_(false),
|
| + drag_started_(false),
|
| + text_button_state_(Button::STATE_NORMAL),
|
| + arrow_button_state_(Button::STATE_NORMAL) {
|
| model_->AddObserver(this);
|
| UpdateFromModel();
|
| set_focusable(true);
|
| set_border(text_border_);
|
| +
|
| + // Initialize the button images.
|
| + Button::ButtonState button_states[] = {
|
| + Button::STATE_DISABLED,
|
| + Button::STATE_NORMAL,
|
| + Button::STATE_HOVERED,
|
| + Button::STATE_PRESSED,
|
| + };
|
| + for (int focused = 0; focused < 2; focused++) {
|
| + for (size_t state_index = 0; state_index < arraysize(button_states);
|
| + state_index++) {
|
| + Button::ButtonState state = button_states[state_index];
|
| + body_button_images_[focused][state] =
|
| + GetButtonImages(false, focused, state);
|
| + menu_button_images_[focused][state] =
|
| + GetButtonImages(true, focused, state);
|
| + }
|
| + }
|
| +
|
| + text_button_hover_animation_.reset(new gfx::SlideAnimation(this));
|
| + text_button_hover_animation_->SetSlideDuration(
|
| + CustomButton::kHoverFadeDurationMs);
|
| + arrow_button_hover_animation_.reset(new gfx::SlideAnimation(this));
|
| + arrow_button_hover_animation_->SetSlideDuration(
|
| + CustomButton::kHoverFadeDurationMs);
|
| }
|
|
|
| Combobox::~Combobox() {
|
| @@ -114,6 +291,22 @@ const gfx::Font& Combobox::GetFont() {
|
| return rb.GetFont(ui::ResourceBundle::BaseFont);
|
| }
|
|
|
| +void Combobox::SetStyle(Style style) {
|
| + if (style_ == style)
|
| + return;
|
| +
|
| + style_ = style;
|
| + switch (style) {
|
| + case STYLE_NORMAL:
|
| + text_border_->ResetInsets();
|
| + break;
|
| + case STYLE_BUTTONS:
|
| + text_border_->SetInsets(8, 13, 8, 13);
|
| + break;
|
| + }
|
| + PreferredSizeChanged();
|
| +}
|
| +
|
| void Combobox::ModelChanged() {
|
| selected_index_ = std::min(0, model_->GetItemCount());
|
| UpdateFromModel();
|
| @@ -201,9 +394,8 @@ gfx::Size Combobox::GetPreferredSize() {
|
| // the minimum width for the dropdown list.
|
| gfx::Insets insets = GetInsets();
|
| int total_width = std::max(kMinComboboxWidth, content_size_.width()) +
|
| - insets.width() + kDisclosureArrowLeftPadding +
|
| - disclosure_arrow_->width() + kDisclosureArrowRightPadding;
|
| -
|
| + insets.width() + GetDisclosureArrowLeftPadding() +
|
| + disclosure_arrow_->width() + GetDisclosureArrowRightPadding();
|
| return gfx::Size(total_width, content_size_.height() + insets.height());
|
| }
|
|
|
| @@ -225,17 +417,64 @@ bool Combobox::OnMousePressed(const ui::MouseEvent& mouse_event) {
|
| const base::TimeDelta delta = base::Time::Now() - closed_time_;
|
| if (mouse_event.IsLeftMouseButton() &&
|
| (delta.InMilliseconds() > kMinimumMsBetweenButtonClicks)) {
|
| - UpdateFromModel();
|
| - ShowDropDownMenu(ui::MENU_SOURCE_MOUSE);
|
| + if (InArrowButton(mouse_event.location())) {
|
| + UpdateFromModel();
|
| + ShowDropDownMenu(ui::MENU_SOURCE_MOUSE);
|
| + } else if (InTextButton(mouse_event.location())) {
|
| + SetButtonStates(Button::STATE_PRESSED, Button::STATE_NORMAL);
|
| + }
|
| }
|
| -
|
| return true;
|
| }
|
|
|
| bool Combobox::OnMouseDragged(const ui::MouseEvent& mouse_event) {
|
| + if (!drag_started_) {
|
| + drag_started_ = true;
|
| + drag_start_point_ = mouse_event.location();
|
| + }
|
| + bool on_text = InTextButton(mouse_event.location()) &&
|
| + InTextButton(drag_start_point_);
|
| + bool on_arrow = InArrowButton(mouse_event.location()) &&
|
| + InArrowButton(drag_start_point_);
|
| + SetButtonStates(on_text ? Button::STATE_PRESSED : Button::STATE_NORMAL,
|
| + on_arrow ? Button::STATE_PRESSED : Button::STATE_NORMAL);
|
| return true;
|
| }
|
|
|
| +void Combobox::OnMouseReleased(const ui::MouseEvent& mouse_event) {
|
| + bool on_text = InTextButton(mouse_event.location());
|
| + bool on_arrow = InArrowButton(mouse_event.location());
|
| + SetButtonStates(on_text ? Button::STATE_HOVERED : Button::STATE_NORMAL,
|
| + on_arrow ? Button::STATE_HOVERED : Button::STATE_NORMAL);
|
| + if (mouse_event.IsOnlyLeftMouseButton() &&
|
| + InTextButton(mouse_event.location())) {
|
| + HandleClickEvent();
|
| + }
|
| +}
|
| +
|
| +void Combobox::OnMouseCaptureLost() {
|
| + drag_started_ = false;
|
| + SetButtonStates(Button::STATE_NORMAL, Button::STATE_NORMAL);
|
| +}
|
| +
|
| +void Combobox::OnMouseEntered(const ui::MouseEvent& mouse_event) {
|
| + bool on_text = InTextButton(mouse_event.location());
|
| + bool on_arrow = InArrowButton(mouse_event.location());
|
| + SetButtonStates(on_text ? Button::STATE_HOVERED : Button::STATE_NORMAL,
|
| + on_arrow ? Button::STATE_HOVERED : Button::STATE_NORMAL);
|
| +}
|
| +
|
| +void Combobox::OnMouseExited(const ui::MouseEvent& mouse_event) {
|
| + SetButtonStates(Button::STATE_NORMAL, Button::STATE_NORMAL);
|
| +}
|
| +
|
| +void Combobox::OnMouseMoved(const ui::MouseEvent& mouse_event) {
|
| + bool on_text = InTextButton(mouse_event.location());
|
| + bool on_arrow = InArrowButton(mouse_event.location());
|
| + SetButtonStates(on_text ? Button::STATE_HOVERED : Button::STATE_NORMAL,
|
| + on_arrow ? Button::STATE_HOVERED : Button::STATE_NORMAL);
|
| +}
|
| +
|
| bool Combobox::OnKeyPressed(const ui::KeyEvent& e) {
|
| // TODO(oshima): handle IME.
|
| DCHECK_EQ(e.type(), ui::ET_KEY_PRESSED);
|
| @@ -280,6 +519,19 @@ bool Combobox::OnKeyPressed(const ui::KeyEvent& e) {
|
| new_index = GetAdjacentIndex(model(), -1, selected_index_);
|
| break;
|
|
|
| + // Click the button only when the button style mode.
|
| + case ui::VKEY_SPACE:
|
| + SetButtonStates(Button::STATE_PRESSED, Button::STATE_NORMAL);
|
| + // When pressing space, the click event will be raised after the key is
|
| + // released.
|
| + break;
|
| +
|
| + // Click the button only when the button style mode.
|
| + case ui::VKEY_RETURN:
|
| + SetButtonStates(Button::STATE_NORMAL, Button::STATE_NORMAL);
|
| + HandleClickEvent();
|
| + break;
|
| +
|
| default:
|
| return false;
|
| }
|
| @@ -297,13 +549,25 @@ bool Combobox::OnKeyPressed(const ui::KeyEvent& e) {
|
| }
|
|
|
| bool Combobox::OnKeyReleased(const ui::KeyEvent& e) {
|
| - return false; // crbug.com/127520
|
| + if (style_ != STYLE_BUTTONS)
|
| + return false; // crbug.com/127520
|
| +
|
| + if (e.key_code() == ui::VKEY_SPACE) {
|
| + SetButtonStates(Button::STATE_NORMAL, Button::STATE_NORMAL);
|
| + HandleClickEvent();
|
| + }
|
| + return false;
|
| }
|
|
|
| void Combobox::OnGestureEvent(ui::GestureEvent* gesture) {
|
| if (gesture->type() == ui::ET_GESTURE_TAP) {
|
| - UpdateFromModel();
|
| - ShowDropDownMenu(ui::MENU_SOURCE_TOUCH);
|
| + if (InArrowButton(gesture->location())) {
|
| + UpdateFromModel();
|
| + ShowDropDownMenu(ui::MENU_SOURCE_TOUCH);
|
| + } else if (InTextButton(gesture->location())) {
|
| + SetButtonStates(Button::STATE_PRESSED, Button::STATE_NORMAL);
|
| + HandleClickEvent();
|
| + }
|
| gesture->StopPropagation();
|
| return;
|
| }
|
| @@ -311,9 +575,19 @@ void Combobox::OnGestureEvent(ui::GestureEvent* gesture) {
|
| }
|
|
|
| void Combobox::OnPaint(gfx::Canvas* canvas) {
|
| - OnPaintBackground(canvas);
|
| - PaintText(canvas);
|
| - OnPaintBorder(canvas);
|
| + switch (style_) {
|
| + case STYLE_NORMAL: {
|
| + OnPaintBackground(canvas);
|
| + PaintText(canvas);
|
| + OnPaintBorder(canvas);
|
| + break;
|
| + }
|
| + case STYLE_BUTTONS: {
|
| + PaintButtons(canvas);
|
| + PaintText(canvas);
|
| + break;
|
| + }
|
| + }
|
| }
|
|
|
| void Combobox::OnFocus() {
|
| @@ -341,6 +615,10 @@ void Combobox::OnModelChanged() {
|
| ModelChanged();
|
| }
|
|
|
| +void Combobox::AnimationProgressed(const gfx::Animation* animation) {
|
| + SchedulePaint();
|
| +}
|
| +
|
| void Combobox::UpdateFromModel() {
|
| int max_width = 0;
|
| const gfx::Font& font = Combobox::GetFont();
|
| @@ -392,8 +670,8 @@ void Combobox::PaintText(gfx::Canvas* canvas) {
|
| selected_index_ = 0;
|
| string16 text = model()->GetItemAt(selected_index_);
|
|
|
| - int disclosure_arrow_offset = width() - disclosure_arrow_->width()
|
| - - kDisclosureArrowLeftPadding - kDisclosureArrowRightPadding;
|
| + int disclosure_arrow_offset = width() - disclosure_arrow_->width() -
|
| + GetDisclosureArrowLeftPadding() - GetDisclosureArrowRightPadding();
|
|
|
| const gfx::Font& font = Combobox::GetFont();
|
| int text_width = font.GetStringWidth(text);
|
| @@ -404,7 +682,8 @@ void Combobox::PaintText(gfx::Canvas* canvas) {
|
| AdjustBoundsForRTLUI(&text_bounds);
|
| canvas->DrawStringInt(text, font, text_color, text_bounds);
|
|
|
| - gfx::Rect arrow_bounds(disclosure_arrow_offset + kDisclosureArrowLeftPadding,
|
| + int arrow_x = disclosure_arrow_offset + GetDisclosureArrowLeftPadding();
|
| + gfx::Rect arrow_bounds(arrow_x,
|
| height() / 2 - disclosure_arrow_->height() / 2,
|
| disclosure_arrow_->width(),
|
| disclosure_arrow_->height());
|
| @@ -420,6 +699,59 @@ void Combobox::PaintText(gfx::Canvas* canvas) {
|
| canvas->Restore();
|
| }
|
|
|
| +void Combobox::PaintButtons(gfx::Canvas* canvas) {
|
| + canvas->Save();
|
| + if (base::i18n::IsRTL()) {
|
| + canvas->Translate(gfx::Vector2d(width(), 0));
|
| + canvas->Scale(-1, 1);
|
| + }
|
| +
|
| + bool focused = HasFocus() && IsAccessibilityFocusable();
|
| + const std::vector<const gfx::ImageSkia*>& text_button_images =
|
| + body_button_images_[focused][text_button_state_ == Button::STATE_HOVERED ?
|
| + Button::STATE_NORMAL : text_button_state_];
|
| + const std::vector<const gfx::ImageSkia*>& arrow_button_images =
|
| + menu_button_images_[focused][
|
| + arrow_button_state_ == Button::STATE_HOVERED ?
|
| + Button::STATE_NORMAL : arrow_button_state_];
|
| +
|
| + int text_button_width = width() - arrow_button_images[0]->width();
|
| + int text_button_hover_alpha =
|
| + static_cast<int>(text_button_hover_animation_->GetCurrentValue() * 255);
|
| + if (text_button_hover_alpha < 255) {
|
| + canvas->SaveLayerAlpha(255 - text_button_hover_alpha);
|
| + PaintTextButton(canvas, text_button_images, text_button_width, height());
|
| + canvas->Restore();
|
| + }
|
| + if (0 < text_button_hover_alpha) {
|
| + canvas->SaveLayerAlpha(text_button_hover_alpha);
|
| + const std::vector<const gfx::ImageSkia*>& text_button_hovered_images =
|
| + body_button_images_[focused][Button::STATE_HOVERED];
|
| + PaintTextButton(canvas, text_button_hovered_images,
|
| + text_button_width, height());
|
| + canvas->Restore();
|
| + }
|
| +
|
| + int arrow_button_x = text_button_width;
|
| + int arrow_button_hover_alpha =
|
| + static_cast<int>(arrow_button_hover_animation_->GetCurrentValue() * 255);
|
| + if (arrow_button_hover_alpha < 255) {
|
| + canvas->SaveLayerAlpha(255 - arrow_button_hover_alpha);
|
| + PaintArrowButton(canvas, arrow_button_images, arrow_button_x, height());
|
| + canvas->Restore();
|
| + }
|
| + if (0 < arrow_button_hover_alpha) {
|
| + canvas->SaveLayerAlpha(arrow_button_hover_alpha);
|
| + const std::vector<const gfx::ImageSkia*>& arrow_button_hovered_images =
|
| + menu_button_images_[focused][Button::STATE_HOVERED];
|
| + PaintArrowButton(canvas, arrow_button_hovered_images,
|
| + arrow_button_x, height());
|
| + canvas->Restore();
|
| + }
|
| +
|
| + canvas->Restore();
|
| +}
|
| +
|
| void Combobox::ShowDropDownMenu(ui::MenuSourceType source_type) {
|
| if (!dropdown_list_menu_runner_.get())
|
| UpdateFromModel();
|
| @@ -427,8 +759,8 @@ void Combobox::ShowDropDownMenu(ui::MenuSourceType source_type) {
|
| // Extend the menu to the width of the combobox.
|
| MenuItemView* menu = dropdown_list_menu_runner_->GetMenu();
|
| SubmenuView* submenu = menu->CreateSubmenu();
|
| - submenu->set_minimum_preferred_width(size().width() -
|
| - (kMenuBorderWidthLeft + kMenuBorderWidthRight));
|
| + submenu->set_minimum_preferred_width(
|
| + size().width() - (kMenuBorderWidthLeft + kMenuBorderWidthRight));
|
|
|
| gfx::Rect lb = GetLocalBounds();
|
| gfx::Point menu_position(lb.origin());
|
| @@ -441,15 +773,19 @@ void Combobox::ShowDropDownMenu(ui::MenuSourceType source_type) {
|
|
|
| View::ConvertPointToScreen(this, &menu_position);
|
| if (menu_position.x() < 0)
|
| - menu_position.set_x(0);
|
| + menu_position.set_x(0);
|
|
|
| gfx::Rect bounds(menu_position, lb.size());
|
|
|
| dropdown_open_ = true;
|
| + Button::ButtonState original_arrow_button_state = arrow_button_state_;
|
| + SetButtonStates(Button::STATE_NORMAL, Button::STATE_PRESSED);
|
| if (dropdown_list_menu_runner_->RunMenuAt(GetWidget(), NULL, bounds,
|
| MenuItemView::TOPLEFT, source_type, MenuRunner::COMBOBOX) ==
|
| - MenuRunner::MENU_DELETED)
|
| + MenuRunner::MENU_DELETED) {
|
| return;
|
| + }
|
| + SetButtonStates(Button::STATE_NORMAL, original_arrow_button_state);
|
| dropdown_open_ = false;
|
| closed_time_ = base::Time::Now();
|
|
|
| @@ -474,4 +810,88 @@ int Combobox::MenuCommandToIndex(int menu_command_id) const {
|
| return index;
|
| }
|
|
|
| +int Combobox::GetDisclosureArrowLeftPadding() const {
|
| + switch (style_) {
|
| + case STYLE_NORMAL:
|
| + return kDisclosureArrowLeftPadding;
|
| + case STYLE_BUTTONS:
|
| + return kDisclosureArrowButtonLeftPadding;
|
| + }
|
| + NOTREACHED();
|
| + return 0;
|
| +}
|
| +
|
| +int Combobox::GetDisclosureArrowRightPadding() const {
|
| + switch (style_) {
|
| + case STYLE_NORMAL:
|
| + return kDisclosureArrowRightPadding;
|
| + case STYLE_BUTTONS:
|
| + return kDisclosureArrowButtonRightPadding;
|
| + }
|
| + NOTREACHED();
|
| + return 0;
|
| +}
|
| +
|
| +void Combobox::HandleClickEvent() {
|
| + if (style_ != STYLE_BUTTONS)
|
| + return;
|
| +
|
| + if (listener_)
|
| + listener_->OnTextButtonClicked(this);
|
| +}
|
| +
|
| +void Combobox::SetButtonStates(Button::ButtonState text_button_state,
|
| + Button::ButtonState arrow_button_state) {
|
| + if (style_ != STYLE_BUTTONS)
|
| + return;
|
| +
|
| + AnimateStateTransition(text_button_hover_animation_.get(),
|
| + text_button_state_, text_button_state);
|
| + AnimateStateTransition(arrow_button_hover_animation_.get(),
|
| + arrow_button_state_, arrow_button_state);
|
| +
|
| + text_button_state_ = text_button_state;
|
| + arrow_button_state_ = arrow_button_state;
|
| + SchedulePaint();
|
| +}
|
| +
|
| +void Combobox::AnimateStateTransition(gfx::SlideAnimation* animation,
|
| + Button::ButtonState from,
|
| + Button::ButtonState to) {
|
| + if (from == Button::STATE_NORMAL && to == Button::STATE_HOVERED)
|
| + animation->Show();
|
| + else if (from == Button::STATE_HOVERED && to == Button::STATE_NORMAL)
|
| + animation->Hide();
|
| + else if (from != to)
|
| + animation->Reset(to == Button::STATE_HOVERED ? 1.0 : 0.0);
|
| +}
|
| +
|
| +bool Combobox::InTextButton(const gfx::Point& point) {
|
| + if (!HitTestPoint(point))
|
| + return false;
|
| +
|
| + if (style_ != STYLE_BUTTONS)
|
| + return false;
|
| +
|
| + int x = point.x();
|
| + const gfx::ImageSkia* menu_button_image =
|
| + menu_button_images_[false][Button::STATE_NORMAL][0];
|
| + return x < width() - menu_button_image->width();
|
| +}
|
| +
|
| +bool Combobox::InArrowButton(const gfx::Point& point) {
|
| + if (!HitTestPoint(point))
|
| + return false;
|
| +
|
| + // When |style_| is not the button style, whole of this control functions as a
|
| + // disclosure arrow button.
|
| + if (style_ != STYLE_BUTTONS)
|
| + return true;
|
| +
|
| + int x = point.x();
|
| + const gfx::ImageSkia* menu_button_image =
|
| + menu_button_images_[false][Button::STATE_NORMAL][0];
|
| + return width() - menu_button_image->width() <= x && x < width();
|
| +}
|
| +
|
| } // namespace views
|
|
|