Chromium Code Reviews| Index: ui/views/controls/combobox/combobox.cc |
| diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc |
| index d726fe2032f5528c0a56925f9378ff27d2de58a9..35083d9e5db69ac9e3d1a60a5e86ddbc7c9e7fd7 100644 |
| --- a/ui/views/controls/combobox/combobox.cc |
| +++ b/ui/views/controls/combobox/combobox.cc |
| @@ -12,9 +12,14 @@ |
| #include "ui/base/resource/resource_bundle.h" |
| #include "ui/events/event.h" |
| #include "ui/events/keycodes/keyboard_codes.h" |
| +#include "ui/gfx/animation/throb_animation.h" |
| #include "ui/gfx/canvas.h" |
| +#include "ui/gfx/image/image.h" |
| +#include "ui/gfx/scoped_canvas.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/button/label_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 +27,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 +45,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 +56,19 @@ 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_GRID(IDR_COMBOBOX_BUTTON_H); |
| +const int kPressedBodyButtonImages[] = IMAGE_GRID(IDR_COMBOBOX_BUTTON_P); |
| + |
| +#define MENU_IMAGE_GRID(x) { \ |
| + x ## _MENU_TOP, x ## _MENU_CENTER, x ## _MENU_BOTTOM, } |
| + |
| +const int kMenuButtonImages[] = MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON); |
| +const int kHoveredMenuButtonImages[] = MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_H); |
| +const int kPressedMenuButtonImages[] = MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_P); |
| + |
| +#undef MENU_IMAGE_GRID |
| + |
| // The background to use for invalid comboboxes. |
| class InvalidBackground : public Background { |
| public: |
| @@ -66,6 +87,33 @@ class InvalidBackground : public Background { |
| DISALLOW_COPY_AND_ASSIGN(InvalidBackground); |
| }; |
| +// The transparent button which holds a button state but is not rendered. |
| +class TransparentButton : public CustomButton { |
| + public: |
| + TransparentButton(ButtonListener* listener) |
| + : CustomButton(listener) { |
| + SetAnimationDuration(LabelButton::kHoverAnimationDurationMs); |
| + } |
| + virtual ~TransparentButton() {} |
| + |
| + // CustomButton: |
| + virtual void StateChanged() OVERRIDE { |
| + parent()->SchedulePaintInRect(bounds()); |
| + } |
| + |
| + // gfx::AnimationDelegate: |
| + virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE { |
| + parent()->SchedulePaintInRect(bounds()); |
| + } |
| + |
| + double GetAnimationValue() const { |
| + return hover_animation_->GetCurrentValue(); |
| + } |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(TransparentButton); |
| +}; |
| + |
| // Returns the next or previous valid index (depending on |increment|'s value). |
| // Skips separator or disabled indices. Returns -1 if there is no valid adjacent |
| // index. |
| @@ -81,6 +129,102 @@ 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, |
| + size_t* num) { |
| + DCHECK(num); |
| + *num = 9; |
| + 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, |
| + size_t* num) { |
| + DCHECK(num); |
| + *num = 3; |
| + 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 menu buttons. |
| +std::vector<const gfx::ImageSkia*> GetMenuButtonImages( |
| + bool focused, |
| + Button::ButtonState state) { |
| + const int* ids; |
| + size_t num_ids; |
| + ids = GetMenuButtonImageIds(focused, state, &num_ids); |
| + 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++) |
| + images.push_back(rb.GetImageSkiaNamed(ids[i])); |
| + return images; |
| +} |
| + |
| +// Paints three images in a column at the given location. The center image is |
| +// stretched so as to fit the given height. |
| +void PaintImagesVertically(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 arrow button. |
| +void PaintArrowButton( |
| + gfx::Canvas* canvas, |
| + const std::vector<const gfx::ImageSkia*>& arrow_button_images, |
| + int x, int height) { |
| + PaintImagesVertically(canvas, |
| + *arrow_button_images[0], |
| + *arrow_button_images[1], |
| + *arrow_button_images[2], |
| + x, 0, arrow_button_images[0]->width(), height); |
| +} |
| + |
| } // namespace |
| // static |
| @@ -91,19 +235,48 @@ const char Combobox::kViewClassName[] = "views/Combobox"; |
| Combobox::Combobox(ui::ComboboxModel* model) |
| : model_(model), |
| + style_(STYLE_SHOW_DROP_DOWN_ON_CLICK), |
| 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), |
| + text_button_(new TransparentButton(this)), |
| + arrow_button_(new TransparentButton(this)) { |
| model_->AddObserver(this); |
| UpdateFromModel(); |
| set_focusable(true); |
| // |text_border_| draws focus. |
| set_focus_border(NULL); |
| 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]; |
| + size_t num; |
| + const int* ids = GetBodyButtonImageIds(focused, state, &num); |
| + body_button_painters_[focused][state].reset( |
| + Painter::CreateImageGridPainter(ids)); |
| + menu_button_images_[focused][state] = GetMenuButtonImages(focused, state); |
| + } |
| + } |
| + |
| + text_button_->SetVisible(true); |
| + arrow_button_->SetVisible(true); |
| + text_button_->set_focusable(false); |
| + arrow_button_->set_focusable(false); |
| + AddChildView(text_button_); |
| + AddChildView(arrow_button_); |
| } |
| Combobox::~Combobox() { |
| @@ -116,6 +289,28 @@ 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_SHOW_DROP_DOWN_ON_CLICK: { |
| + // Recreate a FocusableBorder to reset the insets of the border. |
| + // set_border with a new border will delete the existing border. |
| + text_border_ = new FocusableBorder(); |
| + set_border(text_border_); |
| + break; |
| + } |
| + case STYLE_NOTIFY_ON_CLICK: { |
| + text_border_->SetInsets(8, 13, 8, 13); |
|
sky
2013/12/05 16:46:32
What I'm saying is you should get rid of text_bord
hajimehoshi
2013/12/06 12:27:04
Done. (Added UpdateBorder)
|
| + break; |
| + } |
| + } |
| + |
| + PreferredSizeChanged(); |
| +} |
| + |
| void Combobox::ModelChanged() { |
| selected_index_ = std::min(0, model_->GetItemCount()); |
| UpdateFromModel(); |
| @@ -162,6 +357,31 @@ ui::TextInputClient* Combobox::GetTextInputClient() { |
| return selector_.get(); |
| } |
| +void Combobox::Layout() { |
| + PrefixDelegate::Layout(); |
| + |
| + gfx::Insets insets = GetInsets(); |
| + int height = content_size_.height() + insets.height(); |
|
sky
2013/12/05 16:46:32
Shouldn't you use height() here rather than calcul
hajimehoshi
2013/12/06 12:27:04
height() was enough. Done.
|
| + int text_button_width = 0; |
| + int arrow_button_width = 0; |
| + |
| + switch (style_) { |
| + case STYLE_SHOW_DROP_DOWN_ON_CLICK: { |
| + arrow_button_width = width(); |
| + break; |
| + } |
| + case STYLE_NOTIFY_ON_CLICK: { |
| + arrow_button_width = GetDisclosureArrowLeftPadding() + |
| + disclosure_arrow_->width() + GetDisclosureArrowRightPadding(); |
| + text_button_width = width() - arrow_button_width; |
| + break; |
| + } |
| + } |
| + |
| + int arrow_button_x = text_button_width; |
| + text_button_->SetBounds(0, 0, text_button_width, height); |
|
sky
2013/12/05 16:46:32
std::max(0, text_button_width)
hajimehoshi
2013/12/06 12:27:04
Done.
|
| + arrow_button_->SetBounds(arrow_button_x, 0, arrow_button_width, height); |
| +} |
| bool Combobox::IsItemChecked(int id) const { |
| return false; |
| @@ -207,9 +427,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()); |
| } |
| @@ -226,22 +445,6 @@ bool Combobox::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) { |
| return dropdown_open_; |
| } |
| -bool Combobox::OnMousePressed(const ui::MouseEvent& mouse_event) { |
| - RequestFocus(); |
| - const base::TimeDelta delta = base::Time::Now() - closed_time_; |
| - if (mouse_event.IsLeftMouseButton() && |
| - (delta.InMilliseconds() > kMinimumMsBetweenButtonClicks)) { |
| - UpdateFromModel(); |
| - ShowDropDownMenu(ui::MENU_SOURCE_MOUSE); |
| - } |
| - |
| - return true; |
| -} |
| - |
| -bool Combobox::OnMouseDragged(const ui::MouseEvent& mouse_event) { |
| - return true; |
| -} |
| - |
| bool Combobox::OnKeyPressed(const ui::KeyEvent& e) { |
| // TODO(oshima): handle IME. |
| DCHECK_EQ(e.type(), ui::ET_KEY_PRESSED); |
| @@ -286,6 +489,20 @@ 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: |
| + if (style_ == STYLE_NOTIFY_ON_CLICK) { |
| + // When pressing space, the click event will be raised after the key is |
| + // released. |
| + text_button_->SetState(Button::STATE_PRESSED); |
| + } |
| + break; |
| + |
| + // Click the button only when the button style mode. |
| + case ui::VKEY_RETURN: |
| + HandleClickEvent(); |
| + break; |
| + |
| default: |
| return false; |
| } |
| @@ -303,23 +520,29 @@ bool Combobox::OnKeyPressed(const ui::KeyEvent& e) { |
| } |
| bool Combobox::OnKeyReleased(const ui::KeyEvent& e) { |
| - return false; // crbug.com/127520 |
| -} |
| + if (style_ != STYLE_NOTIFY_ON_CLICK) |
| + return false; // crbug.com/127520 |
| -void Combobox::OnGestureEvent(ui::GestureEvent* gesture) { |
| - if (gesture->type() == ui::ET_GESTURE_TAP) { |
| - UpdateFromModel(); |
| - ShowDropDownMenu(ui::MENU_SOURCE_TOUCH); |
| - gesture->StopPropagation(); |
| - return; |
| - } |
| - View::OnGestureEvent(gesture); |
| + if (e.key_code() == ui::VKEY_SPACE) |
| + HandleClickEvent(); |
| + |
| + return false; |
| } |
| void Combobox::OnPaint(gfx::Canvas* canvas) { |
| - OnPaintBackground(canvas); |
| - PaintText(canvas); |
| - OnPaintBorder(canvas); |
| + switch (style_) { |
| + case STYLE_SHOW_DROP_DOWN_ON_CLICK: { |
| + OnPaintBackground(canvas); |
| + PaintText(canvas); |
| + OnPaintBorder(canvas); |
| + break; |
| + } |
| + case STYLE_NOTIFY_ON_CLICK: { |
| + PaintButtons(canvas); |
| + PaintText(canvas); |
| + break; |
| + } |
| + } |
| } |
| void Combobox::OnFocus() { |
| @@ -349,6 +572,28 @@ void Combobox::OnModelChanged() { |
| ModelChanged(); |
| } |
| +void Combobox::ButtonPressed(Button* sender, const ui::Event& event) { |
| + RequestFocus(); |
| + |
| + if (sender == text_button_) { |
| + HandleClickEvent(); |
| + } else { |
| + DCHECK_EQ(arrow_button_, sender); |
| + // TODO(hajimehoshi): Fix the problem that the arrow button blinks when |
| + // cliking this while the dropdown menu is opened. |
| + const base::TimeDelta delta = base::Time::Now() - closed_time_; |
| + if (delta.InMilliseconds() <= kMinimumMsBetweenButtonClicks) |
| + return; |
| + |
| + ui::MenuSourceType source_type = ui::MENU_SOURCE_MOUSE; |
| + if (event.IsKeyEvent()) |
| + source_type = ui::MENU_SOURCE_KEYBOARD; |
| + else if (event.IsGestureEvent() || event.IsTouchEvent()) |
| + source_type = ui::MENU_SOURCE_TOUCH; |
| + ShowDropDownMenu(source_type); |
| + } |
| +} |
| + |
| void Combobox::UpdateFromModel() { |
| int max_width = 0; |
| const gfx::Font& font = Combobox::GetFont(); |
| @@ -384,7 +629,7 @@ void Combobox::AdjustBoundsForRTLUI(gfx::Rect* rect) const { |
| void Combobox::PaintText(gfx::Canvas* canvas) { |
| gfx::Insets insets = GetInsets(); |
| - canvas->Save(); |
| + gfx::ScopedCanvas scoped_canvas(canvas); |
| canvas->ClipRect(GetContentsBounds()); |
| int x = insets.left(); |
| @@ -400,8 +645,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); |
| @@ -412,7 +657,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()); |
| @@ -424,8 +670,65 @@ void Combobox::PaintText(gfx::Canvas* canvas) { |
| paint.setXfermodeMode(SkXfermode::kDstOut_Mode); |
| canvas->DrawImageInt(*disclosure_arrow_, arrow_bounds.x(), arrow_bounds.y(), |
| paint); |
| +} |
| + |
| +void Combobox::PaintButtons(gfx::Canvas* canvas) { |
| + DCHECK(style_ == STYLE_NOTIFY_ON_CLICK); |
| + |
| + gfx::ScopedCanvas scoped_canvas(canvas); |
| + if (base::i18n::IsRTL()) { |
| + canvas->Translate(gfx::Vector2d(width(), 0)); |
| + canvas->Scale(-1, 1); |
| + } |
| - canvas->Restore(); |
| + bool focused = HasFocus(); |
| + 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(); |
|
sky
2013/12/05 16:46:32
Is there a reason you need this code here rather t
hajimehoshi
2013/12/06 12:27:04
Oh, I just didn't realize this... Thanks. I remove
|
| + int text_button_hover_alpha = |
| + text_button_->state() == Button::STATE_PRESSED ? 0 : |
| + static_cast<int>(static_cast<TransparentButton*>(text_button_)-> |
| + GetAnimationValue() * 255); |
| + if (text_button_hover_alpha < 255) { |
| + canvas->SaveLayerAlpha(255 - text_button_hover_alpha); |
| + Painter* text_button_painter = |
| + body_button_painters_[focused][ |
| + text_button_->state() == Button::STATE_HOVERED ? |
| + Button::STATE_NORMAL : text_button_->state()].get(); |
| + Painter::PaintPainterAt(canvas, text_button_painter, |
| + gfx::Rect(0, 0, text_button_width, height())); |
| + canvas->Restore(); |
| + } |
| + if (0 < text_button_hover_alpha) { |
| + canvas->SaveLayerAlpha(text_button_hover_alpha); |
| + Painter* text_button_hovered_painter = |
| + body_button_painters_[focused][Button::STATE_HOVERED].get(); |
| + Painter::PaintPainterAt(canvas, text_button_hovered_painter, |
| + gfx::Rect(0, 0, text_button_width, height())); |
| + canvas->Restore(); |
| + } |
| + |
| + int arrow_button_x = text_button_width; |
| + int arrow_button_hover_alpha = |
| + arrow_button_->state() == Button::STATE_PRESSED ? 0 : |
| + static_cast<int>(static_cast<TransparentButton*>(arrow_button_)-> |
| + GetAnimationValue() * 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(); |
| + } |
| } |
| void Combobox::ShowDropDownMenu(ui::MenuSourceType source_type) { |
| @@ -435,8 +738,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()); |
| @@ -449,16 +752,24 @@ 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()); |
| + Button::ButtonState original_state; |
| + if (arrow_button_) { |
| + original_state = arrow_button_->state(); |
| + arrow_button_->SetState(Button::STATE_PRESSED); |
| + } |
| dropdown_open_ = true; |
| if (dropdown_list_menu_runner_->RunMenuAt(GetWidget(), NULL, bounds, |
| MenuItemView::TOPLEFT, source_type, MenuRunner::COMBOBOX) == |
| - MenuRunner::MENU_DELETED) |
| + MenuRunner::MENU_DELETED) { |
| return; |
| + } |
| dropdown_open_ = false; |
| + if (arrow_button_) |
| + arrow_button_->SetState(original_state); |
| closed_time_ = base::Time::Now(); |
| // Need to explicitly clear mouse handler so that events get sent |
| @@ -482,4 +793,34 @@ int Combobox::MenuCommandToIndex(int menu_command_id) const { |
| return index; |
| } |
| +int Combobox::GetDisclosureArrowLeftPadding() const { |
| + switch (style_) { |
| + case STYLE_SHOW_DROP_DOWN_ON_CLICK: |
| + return kDisclosureArrowLeftPadding; |
| + case STYLE_NOTIFY_ON_CLICK: |
| + return kDisclosureArrowButtonLeftPadding; |
| + } |
| + NOTREACHED(); |
| + return 0; |
| +} |
| + |
| +int Combobox::GetDisclosureArrowRightPadding() const { |
| + switch (style_) { |
| + case STYLE_SHOW_DROP_DOWN_ON_CLICK: |
| + return kDisclosureArrowRightPadding; |
| + case STYLE_NOTIFY_ON_CLICK: |
| + return kDisclosureArrowButtonRightPadding; |
| + } |
| + NOTREACHED(); |
| + return 0; |
| +} |
| + |
| +void Combobox::HandleClickEvent() { |
| + if (style_ != STYLE_NOTIFY_ON_CLICK) |
| + return; |
| + |
| + if (listener_) |
| + listener_->OnComboboxTextButtonClicked(this); |
| +} |
| + |
| } // namespace views |