 Chromium Code Reviews
 Chromium Code Reviews Issue 141523005:
  Combobox: Rename styles to STYLE_NORMAL and STYLE_ACTION and modify behaviors  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 141523005:
  Combobox: Rename styles to STYLE_NORMAL and STYLE_ACTION and modify behaviors  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| Index: ui/views/controls/combobox/combobox.cc | 
| diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc | 
| index bfbafa5ca3ae05ddaeb9c28a707fe048738d30be..5480c3b8858404136e86e80f6cbd7f5f4ac923dc 100644 | 
| --- a/ui/views/controls/combobox/combobox.cc | 
| +++ b/ui/views/controls/combobox/combobox.cc | 
| @@ -4,7 +4,9 @@ | 
| #include "ui/views/controls/combobox/combobox.h" | 
| +#include "base/bind.h" | 
| #include "base/logging.h" | 
| +#include "base/message_loop/message_loop_proxy.h" | 
| #include "base/strings/utf_string_conversions.h" | 
| #include "grit/ui_resources.h" | 
| #include "ui/base/accessibility/accessible_view_state.h" | 
| @@ -219,7 +221,7 @@ const char Combobox::kViewClassName[] = "views/Combobox"; | 
| Combobox::Combobox(ui::ComboboxModel* model) | 
| : model_(model), | 
| - style_(STYLE_SHOW_DROP_DOWN_ON_CLICK), | 
| + style_(STYLE_NORMAL), | 
| listener_(NULL), | 
| selected_index_(model_->GetDefaultIndex()), | 
| invalid_(false), | 
| @@ -227,7 +229,8 @@ Combobox::Combobox(ui::ComboboxModel* model) | 
| IDR_MENU_DROPARROW).ToImageSkia()), | 
| dropdown_open_(false), | 
| text_button_(new TransparentButton(this)), | 
| - arrow_button_(new TransparentButton(this)) { | 
| + arrow_button_(new TransparentButton(this)), | 
| + weak_ptr_factory_(this) { | 
| model_->AddObserver(this); | 
| UpdateFromModel(); | 
| SetFocusable(true); | 
| @@ -276,8 +279,11 @@ void Combobox::SetStyle(Style style) { | 
| return; | 
| style_ = style; | 
| + if (style_ == STYLE_ACTION) | 
| + selected_index_ = 0; | 
| UpdateBorder(); | 
| + UpdateFromModel(); | 
| PreferredSizeChanged(); | 
| } | 
| @@ -288,11 +294,17 @@ void Combobox::ModelChanged() { | 
| } | 
| void Combobox::SetSelectedIndex(int index) { | 
| + if (style_ == STYLE_ACTION) | 
| + return; | 
| + | 
| selected_index_ = index; | 
| SchedulePaint(); | 
| } | 
| bool Combobox::SelectValue(const base::string16& value) { | 
| + if (style_ == STYLE_ACTION) | 
| + return false; | 
| + | 
| for (int i = 0; i < model()->GetItemCount(); ++i) { | 
| if (value == model()->GetItemAt(i)) { | 
| SetSelectedIndex(i); | 
| @@ -330,11 +342,11 @@ void Combobox::Layout() { | 
| int arrow_button_width = 0; | 
| switch (style_) { | 
| - case STYLE_SHOW_DROP_DOWN_ON_CLICK: { | 
| + case STYLE_NORMAL: { | 
| arrow_button_width = width(); | 
| break; | 
| } | 
| - case STYLE_NOTIFY_ON_CLICK: { | 
| + case STYLE_ACTION: { | 
| arrow_button_width = GetDisclosureArrowLeftPadding() + | 
| disclosure_arrow_->width() + GetDisclosureArrowRightPadding(); | 
| text_button_width = width() - arrow_button_width; | 
| @@ -357,7 +369,7 @@ bool Combobox::IsCommandEnabled(int id) const { | 
| void Combobox::ExecuteCommand(int id) { | 
| selected_index_ = MenuCommandToIndex(id); | 
| - OnSelectionChanged(); | 
| + OnPerformAction(); | 
| } | 
| bool Combobox::GetAccelerator(int id, ui::Accelerator* accel) { | 
| @@ -456,7 +468,7 @@ bool Combobox::OnKeyPressed(const ui::KeyEvent& e) { | 
| // Click the button only when the button style mode. | 
| case ui::VKEY_SPACE: | 
| - if (style_ == STYLE_NOTIFY_ON_CLICK) { | 
| + if (style_ == STYLE_ACTION) { | 
| // When pressing space, the click event will be raised after the key is | 
| // released. | 
| text_button_->SetState(Button::STATE_PRESSED); | 
| @@ -467,9 +479,9 @@ bool Combobox::OnKeyPressed(const ui::KeyEvent& e) { | 
| // Click the button only when the button style mode. | 
| case ui::VKEY_RETURN: | 
| - if (style_ != STYLE_NOTIFY_ON_CLICK) | 
| + if (style_ != STYLE_ACTION) | 
| return false; | 
| - HandleClickEvent(); | 
| + OnPerformAction(); | 
| break; | 
| default: | 
| @@ -480,33 +492,35 @@ bool Combobox::OnKeyPressed(const ui::KeyEvent& e) { | 
| UpdateFromModel(); | 
| ShowDropDownMenu(ui::MENU_SOURCE_KEYBOARD); | 
| } else if (new_index != selected_index_ && new_index != kNoSelection) { | 
| - DCHECK(!model()->IsItemSeparatorAt(new_index)); | 
| - selected_index_ = new_index; | 
| - OnSelectionChanged(); | 
| + if (style_ != STYLE_ACTION) { | 
| 
sky
2014/02/03 16:58:19
nit: combine with if on 494.
 
hajimehoshi
2014/02/04 04:06:32
Done.
 | 
| + DCHECK(!model()->IsItemSeparatorAt(new_index)); | 
| + selected_index_ = new_index; | 
| + OnPerformAction(); | 
| + } | 
| } | 
| return true; | 
| } | 
| bool Combobox::OnKeyReleased(const ui::KeyEvent& e) { | 
| - if (style_ != STYLE_NOTIFY_ON_CLICK) | 
| + if (style_ != STYLE_ACTION) | 
| return false; // crbug.com/127520 | 
| - if (e.key_code() == ui::VKEY_SPACE) | 
| - HandleClickEvent(); | 
| + if (e.key_code() == ui::VKEY_SPACE && style_ == STYLE_ACTION) | 
| + OnPerformAction(); | 
| return false; | 
| } | 
| void Combobox::OnPaint(gfx::Canvas* canvas) { | 
| switch (style_) { | 
| - case STYLE_SHOW_DROP_DOWN_ON_CLICK: { | 
| + case STYLE_NORMAL: { | 
| OnPaintBackground(canvas); | 
| PaintText(canvas); | 
| OnPaintBorder(canvas); | 
| break; | 
| } | 
| - case STYLE_NOTIFY_ON_CLICK: { | 
| + case STYLE_ACTION: { | 
| PaintButtons(canvas); | 
| PaintText(canvas); | 
| break; | 
| @@ -546,7 +560,7 @@ void Combobox::ButtonPressed(Button* sender, const ui::Event& event) { | 
| RequestFocus(); | 
| if (sender == text_button_) { | 
| - HandleClickEvent(); | 
| + OnPerformAction(); | 
| } else { | 
| DCHECK_EQ(arrow_button_, sender); | 
| // TODO(hajimehoshi): Fix the problem that the arrow button blinks when | 
| @@ -565,7 +579,6 @@ void Combobox::ButtonPressed(Button* sender, const ui::Event& event) { | 
| } | 
| void Combobox::UpdateFromModel() { | 
| - int max_width = 0; | 
| const gfx::FontList& font_list = Combobox::GetFontList(); | 
| MenuItemView* menu = new MenuItemView(this); | 
| @@ -573,6 +586,7 @@ void Combobox::UpdateFromModel() { | 
| dropdown_list_menu_runner_.reset(new MenuRunner(menu)); | 
| int num_items = model()->GetItemCount(); | 
| + int width = 0; | 
| for (int i = 0; i < num_items; ++i) { | 
| if (model()->IsItemSeparatorAt(i)) { | 
| menu->AppendSeparator(); | 
| @@ -586,15 +600,17 @@ void Combobox::UpdateFromModel() { | 
| base::i18n::AdjustStringForLocaleDirection(&text); | 
| menu->AppendMenuItem(i + kFirstMenuItemId, text, MenuItemView::NORMAL); | 
| - max_width = std::max(max_width, gfx::GetStringWidth(text, font_list)); | 
| + | 
| + if (style_ != STYLE_ACTION || i == selected_index_) | 
| + width = std::max(width, gfx::GetStringWidth(text, font_list)); | 
| } | 
| - content_size_.SetSize(max_width, font_list.GetHeight()); | 
| + content_size_.SetSize(width, font_list.GetHeight()); | 
| } | 
| void Combobox::UpdateBorder() { | 
| scoped_ptr<FocusableBorder> border(new FocusableBorder()); | 
| - if (style_ == STYLE_NOTIFY_ON_CLICK) | 
| + if (style_ == STYLE_ACTION) | 
| border->SetInsets(8, 13, 8, 13); | 
| if (invalid_) | 
| border->SetColor(kWarningColor); | 
| @@ -646,7 +662,7 @@ void Combobox::PaintText(gfx::Canvas* canvas) { | 
| } | 
| void Combobox::PaintButtons(gfx::Canvas* canvas) { | 
| - DCHECK(style_ == STYLE_NOTIFY_ON_CLICK); | 
| + DCHECK(style_ == STYLE_ACTION); | 
| gfx::ScopedCanvas scoped_canvas(canvas); | 
| if (base::i18n::IsRTL()) { | 
| @@ -750,12 +766,28 @@ void Combobox::ShowDropDownMenu(ui::MenuSourceType source_type) { | 
| SetMouseHandler(NULL); | 
| } | 
| -void Combobox::OnSelectionChanged() { | 
| +void Combobox::OnPerformAction() { | 
| NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_VALUE_CHANGED, false); | 
| SchedulePaint(); | 
| + | 
| + // Because the combobox might die during processing at the lister, the | 
| + // cleaning up should be executed as a posted task with a weak ref pointer. | 
| + base::MessageLoop::current()->message_loop_proxy()->PostTaskAndReply( | 
| + FROM_HERE, | 
| + base::Bind(&Combobox::NotifyPerformAction, | 
| 
sky
2014/02/03 16:58:19
You should not delay the notification. Instead bef
 
hajimehoshi
2014/02/04 04:06:32
Done.
 | 
| + weak_ptr_factory_.GetWeakPtr()), | 
| + base::Bind(&Combobox::AfterPerformAction, | 
| + weak_ptr_factory_.GetWeakPtr())); | 
| +} | 
| + | 
| +void Combobox::NotifyPerformAction() { | 
| if (listener_) | 
| - listener_->OnSelectedIndexChanged(this); | 
| - // |this| may now be deleted. | 
| + listener_->OnPerformAction(this); | 
| +} | 
| + | 
| +void Combobox::AfterPerformAction() { | 
| + if (style_ == STYLE_ACTION) | 
| + selected_index_ = 0; | 
| } | 
| int Combobox::MenuCommandToIndex(int menu_command_id) const { | 
| @@ -768,9 +800,9 @@ int Combobox::MenuCommandToIndex(int menu_command_id) const { | 
| int Combobox::GetDisclosureArrowLeftPadding() const { | 
| switch (style_) { | 
| - case STYLE_SHOW_DROP_DOWN_ON_CLICK: | 
| + case STYLE_NORMAL: | 
| return kDisclosureArrowLeftPadding; | 
| - case STYLE_NOTIFY_ON_CLICK: | 
| + case STYLE_ACTION: | 
| return kDisclosureArrowButtonLeftPadding; | 
| } | 
| NOTREACHED(); | 
| @@ -779,21 +811,13 @@ int Combobox::GetDisclosureArrowLeftPadding() const { | 
| int Combobox::GetDisclosureArrowRightPadding() const { | 
| switch (style_) { | 
| - case STYLE_SHOW_DROP_DOWN_ON_CLICK: | 
| + case STYLE_NORMAL: | 
| return kDisclosureArrowRightPadding; | 
| - case STYLE_NOTIFY_ON_CLICK: | 
| + case STYLE_ACTION: | 
| return kDisclosureArrowButtonRightPadding; | 
| } | 
| NOTREACHED(); | 
| return 0; | 
| } | 
| -void Combobox::HandleClickEvent() { | 
| - if (style_ != STYLE_NOTIFY_ON_CLICK) | 
| - return; | 
| - | 
| - if (listener_) | 
| - listener_->OnComboboxTextButtonClicked(this); | 
| -} | 
| - | 
| } // namespace views |