Chromium Code Reviews| 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 "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
| 9 #include "grit/ui_resources.h" | 9 #include "grit/ui_resources.h" |
| 10 #include "ui/base/accessibility/accessible_view_state.h" | 10 #include "ui/base/accessibility/accessible_view_state.h" |
| 11 #include "ui/base/models/combobox_model.h" | 11 #include "ui/base/models/combobox_model.h" |
| 12 #include "ui/base/resource/resource_bundle.h" | 12 #include "ui/base/resource/resource_bundle.h" |
| 13 #include "ui/events/event.h" | 13 #include "ui/events/event.h" |
| 14 #include "ui/events/keycodes/keyboard_codes.h" | 14 #include "ui/events/keycodes/keyboard_codes.h" |
| 15 #include "ui/gfx/animation/throb_animation.h" | |
| 15 #include "ui/gfx/canvas.h" | 16 #include "ui/gfx/canvas.h" |
| 17 #include "ui/gfx/image/image.h" | |
| 18 #include "ui/gfx/scoped_canvas.h" | |
| 16 #include "ui/native_theme/native_theme.h" | 19 #include "ui/native_theme/native_theme.h" |
| 17 #include "ui/views/color_constants.h" | 20 #include "ui/views/color_constants.h" |
| 21 #include "ui/views/controls/button/custom_button.h" | |
| 22 #include "ui/views/controls/button/label_button.h" | |
| 18 #include "ui/views/controls/combobox/combobox_listener.h" | 23 #include "ui/views/controls/combobox/combobox_listener.h" |
| 19 #include "ui/views/controls/focusable_border.h" | 24 #include "ui/views/controls/focusable_border.h" |
| 20 #include "ui/views/controls/menu/menu_runner.h" | 25 #include "ui/views/controls/menu/menu_runner.h" |
| 21 #include "ui/views/controls/menu/submenu_view.h" | 26 #include "ui/views/controls/menu/submenu_view.h" |
| 22 #include "ui/views/controls/prefix_selector.h" | 27 #include "ui/views/controls/prefix_selector.h" |
| 23 #include "ui/views/ime/input_method.h" | 28 #include "ui/views/ime/input_method.h" |
| 24 #include "ui/views/mouse_constants.h" | 29 #include "ui/views/mouse_constants.h" |
| 30 #include "ui/views/painter.h" | |
| 25 #include "ui/views/widget/widget.h" | 31 #include "ui/views/widget/widget.h" |
| 26 | 32 |
| 27 namespace views { | 33 namespace views { |
| 28 | 34 |
| 29 namespace { | 35 namespace { |
| 30 | 36 |
| 31 // Menu border widths | 37 // Menu border widths |
| 32 const int kMenuBorderWidthLeft = 1; | 38 const int kMenuBorderWidthLeft = 1; |
| 33 const int kMenuBorderWidthTop = 1; | 39 const int kMenuBorderWidthTop = 1; |
| 34 const int kMenuBorderWidthRight = 1; | 40 const int kMenuBorderWidthRight = 1; |
| 35 | 41 |
| 36 // Limit how small a combobox can be. | 42 // Limit how small a combobox can be. |
| 37 const int kMinComboboxWidth = 25; | 43 const int kMinComboboxWidth = 25; |
| 38 | 44 |
| 39 // Size of the combobox arrow margins | 45 // Size of the combobox arrow margins |
| 40 const int kDisclosureArrowLeftPadding = 7; | 46 const int kDisclosureArrowLeftPadding = 7; |
| 41 const int kDisclosureArrowRightPadding = 7; | 47 const int kDisclosureArrowRightPadding = 7; |
| 48 const int kDisclosureArrowButtonLeftPadding = 11; | |
| 49 const int kDisclosureArrowButtonRightPadding = 12; | |
| 42 | 50 |
| 43 // Define the id of the first item in the menu (since it needs to be > 0) | 51 // Define the id of the first item in the menu (since it needs to be > 0) |
| 44 const int kFirstMenuItemId = 1000; | 52 const int kFirstMenuItemId = 1000; |
| 45 | 53 |
| 46 const SkColor kInvalidTextColor = SK_ColorWHITE; | 54 const SkColor kInvalidTextColor = SK_ColorWHITE; |
| 47 | 55 |
| 48 // Used to indicate that no item is currently selected by the user. | 56 // Used to indicate that no item is currently selected by the user. |
| 49 const int kNoSelection = -1; | 57 const int kNoSelection = -1; |
| 50 | 58 |
| 59 const int kBodyButtonImages[] = IMAGE_GRID(IDR_COMBOBOX_BUTTON); | |
| 60 const int kHoveredBodyButtonImages[] = IMAGE_GRID(IDR_COMBOBOX_BUTTON_H); | |
| 61 const int kPressedBodyButtonImages[] = IMAGE_GRID(IDR_COMBOBOX_BUTTON_P); | |
| 62 | |
| 63 #define MENU_IMAGE_GRID(x) { \ | |
| 64 x ## _MENU_TOP, x ## _MENU_CENTER, x ## _MENU_BOTTOM, } | |
| 65 | |
| 66 const int kMenuButtonImages[] = MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON); | |
| 67 const int kHoveredMenuButtonImages[] = MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_H); | |
| 68 const int kPressedMenuButtonImages[] = MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_P); | |
| 69 | |
| 70 #undef MENU_IMAGE_GRID | |
| 71 | |
| 51 // The background to use for invalid comboboxes. | 72 // The background to use for invalid comboboxes. |
| 52 class InvalidBackground : public Background { | 73 class InvalidBackground : public Background { |
| 53 public: | 74 public: |
| 54 InvalidBackground() {} | 75 InvalidBackground() {} |
| 55 virtual ~InvalidBackground() {} | 76 virtual ~InvalidBackground() {} |
| 56 | 77 |
| 57 // Overridden from Background: | 78 // Overridden from Background: |
| 58 virtual void Paint(gfx::Canvas* canvas, View* view) const OVERRIDE { | 79 virtual void Paint(gfx::Canvas* canvas, View* view) const OVERRIDE { |
| 59 gfx::Rect bounds(view->GetLocalBounds()); | 80 gfx::Rect bounds(view->GetLocalBounds()); |
| 60 // Inset by 2 to leave 1 empty pixel between background and border. | 81 // Inset by 2 to leave 1 empty pixel between background and border. |
| 61 bounds.Inset(2, 2, 2, 2); | 82 bounds.Inset(2, 2, 2, 2); |
| 62 canvas->FillRect(bounds, kWarningColor); | 83 canvas->FillRect(bounds, kWarningColor); |
| 63 } | 84 } |
| 64 | 85 |
| 65 private: | 86 private: |
| 66 DISALLOW_COPY_AND_ASSIGN(InvalidBackground); | 87 DISALLOW_COPY_AND_ASSIGN(InvalidBackground); |
| 67 }; | 88 }; |
| 68 | 89 |
| 90 // The transparent button which holds a button state but is not rendered. | |
| 91 class TransparentButton : public CustomButton { | |
| 92 public: | |
| 93 TransparentButton(ButtonListener* listener) | |
| 94 : CustomButton(listener) { | |
| 95 SetAnimationDuration(LabelButton::kHoverAnimationDurationMs); | |
| 96 } | |
| 97 virtual ~TransparentButton() {} | |
| 98 | |
| 99 // CustomButton: | |
| 100 virtual void StateChanged() OVERRIDE { | |
| 101 parent()->SchedulePaintInRect(bounds()); | |
| 102 } | |
| 103 | |
| 104 // gfx::AnimationDelegate: | |
| 105 virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE { | |
| 106 parent()->SchedulePaintInRect(bounds()); | |
| 107 } | |
| 108 | |
| 109 double GetAnimationValue() const { | |
| 110 return hover_animation_->GetCurrentValue(); | |
| 111 } | |
| 112 | |
| 113 private: | |
| 114 DISALLOW_COPY_AND_ASSIGN(TransparentButton); | |
| 115 }; | |
| 116 | |
| 69 // Returns the next or previous valid index (depending on |increment|'s value). | 117 // Returns the next or previous valid index (depending on |increment|'s value). |
| 70 // Skips separator or disabled indices. Returns -1 if there is no valid adjacent | 118 // Skips separator or disabled indices. Returns -1 if there is no valid adjacent |
| 71 // index. | 119 // index. |
| 72 int GetAdjacentIndex(ui::ComboboxModel* model, int increment, int index) { | 120 int GetAdjacentIndex(ui::ComboboxModel* model, int increment, int index) { |
| 73 DCHECK(increment == -1 || increment == 1); | 121 DCHECK(increment == -1 || increment == 1); |
| 74 | 122 |
| 75 index += increment; | 123 index += increment; |
| 76 while (index >= 0 && index < model->GetItemCount()) { | 124 while (index >= 0 && index < model->GetItemCount()) { |
| 77 if (!model->IsItemSeparatorAt(index) || !model->IsItemEnabledAt(index)) | 125 if (!model->IsItemSeparatorAt(index) || !model->IsItemEnabledAt(index)) |
| 78 return index; | 126 return index; |
| 79 index += increment; | 127 index += increment; |
| 80 } | 128 } |
| 81 return kNoSelection; | 129 return kNoSelection; |
| 82 } | 130 } |
| 83 | 131 |
| 132 // Returns the image resource ids of an array for the body button. | |
| 133 // | |
| 134 // TODO(hajimehoshi): This function should return the images for the 'disabled' | |
| 135 // status. (crbug/270052) | |
| 136 // | |
| 137 // TODO(hajimehoshi): Currently, |focused| is ignored. This should return the | |
| 138 // images for the 'focused' status. (crbug/270052) | |
| 139 const int* GetBodyButtonImageIds(bool focused, | |
| 140 Button::ButtonState state, | |
| 141 size_t* num) { | |
| 142 DCHECK(num); | |
| 143 *num = 9; | |
| 144 switch (state) { | |
| 145 case Button::STATE_DISABLED: | |
| 146 return kBodyButtonImages; | |
| 147 case Button::STATE_NORMAL: | |
| 148 return kBodyButtonImages; | |
| 149 case Button::STATE_HOVERED: | |
| 150 return kHoveredBodyButtonImages; | |
| 151 case Button::STATE_PRESSED: | |
| 152 return kPressedBodyButtonImages; | |
| 153 default: | |
| 154 NOTREACHED(); | |
| 155 } | |
| 156 return NULL; | |
| 157 } | |
| 158 | |
| 159 // Returns the image resource ids of an array for the menu button. | |
| 160 const int* GetMenuButtonImageIds(bool focused, | |
| 161 Button::ButtonState state, | |
| 162 size_t* num) { | |
| 163 DCHECK(num); | |
| 164 *num = 3; | |
| 165 switch (state) { | |
| 166 case Button::STATE_DISABLED: | |
| 167 return kMenuButtonImages; | |
| 168 case Button::STATE_NORMAL: | |
| 169 return kMenuButtonImages; | |
| 170 case Button::STATE_HOVERED: | |
| 171 return kHoveredMenuButtonImages; | |
| 172 case Button::STATE_PRESSED: | |
| 173 return kPressedMenuButtonImages; | |
| 174 default: | |
| 175 NOTREACHED(); | |
| 176 } | |
| 177 return NULL; | |
| 178 } | |
| 179 | |
| 180 // Returns the images for the menu buttons. | |
| 181 std::vector<const gfx::ImageSkia*> GetMenuButtonImages( | |
| 182 bool focused, | |
| 183 Button::ButtonState state) { | |
| 184 const int* ids; | |
| 185 size_t num_ids; | |
| 186 ids = GetMenuButtonImageIds(focused, state, &num_ids); | |
| 187 std::vector<const gfx::ImageSkia*> images; | |
| 188 images.reserve(num_ids); | |
| 189 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 190 for (size_t i = 0; i < num_ids; i++) | |
| 191 images.push_back(rb.GetImageSkiaNamed(ids[i])); | |
| 192 return images; | |
| 193 } | |
| 194 | |
| 195 // Paints three images in a column at the given location. The center image is | |
| 196 // stretched so as to fit the given height. | |
| 197 void PaintImagesVertically(gfx::Canvas* canvas, | |
| 198 const gfx::ImageSkia& top_image, | |
| 199 const gfx::ImageSkia& center_image, | |
| 200 const gfx::ImageSkia& bottom_image, | |
| 201 int x, int y, int width, int height) { | |
| 202 canvas->DrawImageInt(top_image, | |
| 203 0, 0, top_image.width(), top_image.height(), | |
| 204 x, y, width, top_image.height(), false); | |
| 205 y += top_image.height(); | |
| 206 int center_height = height - top_image.height() - bottom_image.height(); | |
| 207 canvas->DrawImageInt(center_image, | |
| 208 0, 0, center_image.width(), center_image.height(), | |
| 209 x, y, width, center_height, false); | |
| 210 y += center_height; | |
| 211 canvas->DrawImageInt(bottom_image, | |
| 212 0, 0, bottom_image.width(), bottom_image.height(), | |
| 213 x, y, width, bottom_image.height(), false); | |
| 214 } | |
| 215 | |
| 216 // Paints the arrow button. | |
| 217 void PaintArrowButton( | |
| 218 gfx::Canvas* canvas, | |
| 219 const std::vector<const gfx::ImageSkia*>& arrow_button_images, | |
| 220 int x, int height) { | |
| 221 PaintImagesVertically(canvas, | |
| 222 *arrow_button_images[0], | |
| 223 *arrow_button_images[1], | |
| 224 *arrow_button_images[2], | |
| 225 x, 0, arrow_button_images[0]->width(), height); | |
| 226 } | |
| 227 | |
| 84 } // namespace | 228 } // namespace |
| 85 | 229 |
| 86 // static | 230 // static |
| 87 const char Combobox::kViewClassName[] = "views/Combobox"; | 231 const char Combobox::kViewClassName[] = "views/Combobox"; |
| 88 | 232 |
| 89 //////////////////////////////////////////////////////////////////////////////// | 233 //////////////////////////////////////////////////////////////////////////////// |
| 90 // Combobox, public: | 234 // Combobox, public: |
| 91 | 235 |
| 92 Combobox::Combobox(ui::ComboboxModel* model) | 236 Combobox::Combobox(ui::ComboboxModel* model) |
| 93 : model_(model), | 237 : model_(model), |
| 238 style_(STYLE_SHOW_DROP_DOWN_ON_CLICK), | |
| 94 listener_(NULL), | 239 listener_(NULL), |
| 95 selected_index_(model_->GetDefaultIndex()), | 240 selected_index_(model_->GetDefaultIndex()), |
| 96 invalid_(false), | 241 invalid_(false), |
| 97 text_border_(new FocusableBorder()), | 242 text_border_(new FocusableBorder()), |
| 98 disclosure_arrow_(ui::ResourceBundle::GetSharedInstance().GetImageNamed( | 243 disclosure_arrow_(ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
| 99 IDR_MENU_DROPARROW).ToImageSkia()), | 244 IDR_MENU_DROPARROW).ToImageSkia()), |
| 100 dropdown_open_(false) { | 245 dropdown_open_(false), |
| 246 text_button_(new TransparentButton(this)), | |
| 247 arrow_button_(new TransparentButton(this)) { | |
| 101 model_->AddObserver(this); | 248 model_->AddObserver(this); |
| 102 UpdateFromModel(); | 249 UpdateFromModel(); |
| 103 set_focusable(true); | 250 set_focusable(true); |
| 104 // |text_border_| draws focus. | 251 // |text_border_| draws focus. |
| 105 set_focus_border(NULL); | 252 set_focus_border(NULL); |
| 106 set_border(text_border_); | 253 set_border(text_border_); |
| 254 | |
| 255 // Initialize the button images. | |
| 256 Button::ButtonState button_states[] = { | |
| 257 Button::STATE_DISABLED, | |
| 258 Button::STATE_NORMAL, | |
| 259 Button::STATE_HOVERED, | |
| 260 Button::STATE_PRESSED, | |
| 261 }; | |
| 262 for (int focused = 0; focused < 2; focused++) { | |
| 263 for (size_t state_index = 0; state_index < arraysize(button_states); | |
| 264 state_index++) { | |
| 265 Button::ButtonState state = button_states[state_index]; | |
| 266 size_t num; | |
| 267 const int* ids = GetBodyButtonImageIds(focused, state, &num); | |
| 268 body_button_painters_[focused][state].reset( | |
| 269 Painter::CreateImageGridPainter(ids)); | |
| 270 menu_button_images_[focused][state] = GetMenuButtonImages(focused, state); | |
| 271 } | |
| 272 } | |
| 273 | |
| 274 text_button_->SetVisible(true); | |
| 275 arrow_button_->SetVisible(true); | |
| 276 text_button_->set_focusable(false); | |
| 277 arrow_button_->set_focusable(false); | |
| 278 AddChildView(text_button_); | |
| 279 AddChildView(arrow_button_); | |
| 107 } | 280 } |
| 108 | 281 |
| 109 Combobox::~Combobox() { | 282 Combobox::~Combobox() { |
| 110 model_->RemoveObserver(this); | 283 model_->RemoveObserver(this); |
| 111 } | 284 } |
| 112 | 285 |
| 113 // static | 286 // static |
| 114 const gfx::Font& Combobox::GetFont() { | 287 const gfx::Font& Combobox::GetFont() { |
| 115 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 288 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 116 return rb.GetFont(ui::ResourceBundle::BaseFont); | 289 return rb.GetFont(ui::ResourceBundle::BaseFont); |
| 117 } | 290 } |
| 118 | 291 |
| 292 void Combobox::SetStyle(Style style) { | |
| 293 if (style_ == style) | |
| 294 return; | |
| 295 | |
| 296 style_ = style; | |
| 297 switch (style) { | |
| 298 case STYLE_SHOW_DROP_DOWN_ON_CLICK: { | |
| 299 // Recreate a FocusableBorder to reset the insets of the border. | |
| 300 // set_border with a new border will delete the existing border. | |
| 301 text_border_ = new FocusableBorder(); | |
| 302 set_border(text_border_); | |
| 303 break; | |
| 304 } | |
| 305 case STYLE_NOTIFY_ON_CLICK: { | |
| 306 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)
| |
| 307 break; | |
| 308 } | |
| 309 } | |
| 310 | |
| 311 PreferredSizeChanged(); | |
| 312 } | |
| 313 | |
| 119 void Combobox::ModelChanged() { | 314 void Combobox::ModelChanged() { |
| 120 selected_index_ = std::min(0, model_->GetItemCount()); | 315 selected_index_ = std::min(0, model_->GetItemCount()); |
| 121 UpdateFromModel(); | 316 UpdateFromModel(); |
| 122 PreferredSizeChanged(); | 317 PreferredSizeChanged(); |
| 123 } | 318 } |
| 124 | 319 |
| 125 void Combobox::SetSelectedIndex(int index) { | 320 void Combobox::SetSelectedIndex(int index) { |
| 126 selected_index_ = index; | 321 selected_index_ = index; |
| 127 SchedulePaint(); | 322 SchedulePaint(); |
| 128 } | 323 } |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 155 } | 350 } |
| 156 SchedulePaint(); | 351 SchedulePaint(); |
| 157 } | 352 } |
| 158 | 353 |
| 159 ui::TextInputClient* Combobox::GetTextInputClient() { | 354 ui::TextInputClient* Combobox::GetTextInputClient() { |
| 160 if (!selector_) | 355 if (!selector_) |
| 161 selector_.reset(new PrefixSelector(this)); | 356 selector_.reset(new PrefixSelector(this)); |
| 162 return selector_.get(); | 357 return selector_.get(); |
| 163 } | 358 } |
| 164 | 359 |
| 360 void Combobox::Layout() { | |
| 361 PrefixDelegate::Layout(); | |
| 362 | |
| 363 gfx::Insets insets = GetInsets(); | |
| 364 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.
| |
| 365 int text_button_width = 0; | |
| 366 int arrow_button_width = 0; | |
| 367 | |
| 368 switch (style_) { | |
| 369 case STYLE_SHOW_DROP_DOWN_ON_CLICK: { | |
| 370 arrow_button_width = width(); | |
| 371 break; | |
| 372 } | |
| 373 case STYLE_NOTIFY_ON_CLICK: { | |
| 374 arrow_button_width = GetDisclosureArrowLeftPadding() + | |
| 375 disclosure_arrow_->width() + GetDisclosureArrowRightPadding(); | |
| 376 text_button_width = width() - arrow_button_width; | |
| 377 break; | |
| 378 } | |
| 379 } | |
| 380 | |
| 381 int arrow_button_x = text_button_width; | |
| 382 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.
| |
| 383 arrow_button_->SetBounds(arrow_button_x, 0, arrow_button_width, height); | |
| 384 } | |
| 165 | 385 |
| 166 bool Combobox::IsItemChecked(int id) const { | 386 bool Combobox::IsItemChecked(int id) const { |
| 167 return false; | 387 return false; |
| 168 } | 388 } |
| 169 | 389 |
| 170 bool Combobox::IsCommandEnabled(int id) const { | 390 bool Combobox::IsCommandEnabled(int id) const { |
| 171 return model()->IsItemEnabledAt(MenuCommandToIndex(id)); | 391 return model()->IsItemEnabledAt(MenuCommandToIndex(id)); |
| 172 } | 392 } |
| 173 | 393 |
| 174 void Combobox::ExecuteCommand(int id) { | 394 void Combobox::ExecuteCommand(int id) { |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 200 // Combobox, View overrides: | 420 // Combobox, View overrides: |
| 201 | 421 |
| 202 gfx::Size Combobox::GetPreferredSize() { | 422 gfx::Size Combobox::GetPreferredSize() { |
| 203 if (content_size_.IsEmpty()) | 423 if (content_size_.IsEmpty()) |
| 204 UpdateFromModel(); | 424 UpdateFromModel(); |
| 205 | 425 |
| 206 // The preferred size will drive the local bounds which in turn is used to set | 426 // The preferred size will drive the local bounds which in turn is used to set |
| 207 // the minimum width for the dropdown list. | 427 // the minimum width for the dropdown list. |
| 208 gfx::Insets insets = GetInsets(); | 428 gfx::Insets insets = GetInsets(); |
| 209 int total_width = std::max(kMinComboboxWidth, content_size_.width()) + | 429 int total_width = std::max(kMinComboboxWidth, content_size_.width()) + |
| 210 insets.width() + kDisclosureArrowLeftPadding + | 430 insets.width() + GetDisclosureArrowLeftPadding() + |
| 211 disclosure_arrow_->width() + kDisclosureArrowRightPadding; | 431 disclosure_arrow_->width() + GetDisclosureArrowRightPadding(); |
| 212 | |
| 213 return gfx::Size(total_width, content_size_.height() + insets.height()); | 432 return gfx::Size(total_width, content_size_.height() + insets.height()); |
| 214 } | 433 } |
| 215 | 434 |
| 216 const char* Combobox::GetClassName() const { | 435 const char* Combobox::GetClassName() const { |
| 217 return kViewClassName; | 436 return kViewClassName; |
| 218 } | 437 } |
| 219 | 438 |
| 220 bool Combobox::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) { | 439 bool Combobox::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) { |
| 221 // Escape should close the drop down list when it is active, not host UI. | 440 // Escape should close the drop down list when it is active, not host UI. |
| 222 if (e.key_code() != ui::VKEY_ESCAPE || | 441 if (e.key_code() != ui::VKEY_ESCAPE || |
| 223 e.IsShiftDown() || e.IsControlDown() || e.IsAltDown()) { | 442 e.IsShiftDown() || e.IsControlDown() || e.IsAltDown()) { |
| 224 return false; | 443 return false; |
| 225 } | 444 } |
| 226 return dropdown_open_; | 445 return dropdown_open_; |
| 227 } | 446 } |
| 228 | 447 |
| 229 bool Combobox::OnMousePressed(const ui::MouseEvent& mouse_event) { | |
| 230 RequestFocus(); | |
| 231 const base::TimeDelta delta = base::Time::Now() - closed_time_; | |
| 232 if (mouse_event.IsLeftMouseButton() && | |
| 233 (delta.InMilliseconds() > kMinimumMsBetweenButtonClicks)) { | |
| 234 UpdateFromModel(); | |
| 235 ShowDropDownMenu(ui::MENU_SOURCE_MOUSE); | |
| 236 } | |
| 237 | |
| 238 return true; | |
| 239 } | |
| 240 | |
| 241 bool Combobox::OnMouseDragged(const ui::MouseEvent& mouse_event) { | |
| 242 return true; | |
| 243 } | |
| 244 | |
| 245 bool Combobox::OnKeyPressed(const ui::KeyEvent& e) { | 448 bool Combobox::OnKeyPressed(const ui::KeyEvent& e) { |
| 246 // TODO(oshima): handle IME. | 449 // TODO(oshima): handle IME. |
| 247 DCHECK_EQ(e.type(), ui::ET_KEY_PRESSED); | 450 DCHECK_EQ(e.type(), ui::ET_KEY_PRESSED); |
| 248 | 451 |
| 249 DCHECK_GE(selected_index_, 0); | 452 DCHECK_GE(selected_index_, 0); |
| 250 DCHECK_LT(selected_index_, model()->GetItemCount()); | 453 DCHECK_LT(selected_index_, model()->GetItemCount()); |
| 251 if (selected_index_ < 0 || selected_index_ > model()->GetItemCount()) | 454 if (selected_index_ < 0 || selected_index_ > model()->GetItemCount()) |
| 252 selected_index_ = 0; | 455 selected_index_ = 0; |
| 253 | 456 |
| 254 bool show_menu = false; | 457 bool show_menu = false; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 279 case ui::VKEY_HOME: | 482 case ui::VKEY_HOME: |
| 280 case ui::VKEY_PRIOR: // Page up. | 483 case ui::VKEY_PRIOR: // Page up. |
| 281 new_index = GetAdjacentIndex(model(), 1, -1); | 484 new_index = GetAdjacentIndex(model(), 1, -1); |
| 282 break; | 485 break; |
| 283 | 486 |
| 284 // Move to the previous item if any. | 487 // Move to the previous item if any. |
| 285 case ui::VKEY_UP: | 488 case ui::VKEY_UP: |
| 286 new_index = GetAdjacentIndex(model(), -1, selected_index_); | 489 new_index = GetAdjacentIndex(model(), -1, selected_index_); |
| 287 break; | 490 break; |
| 288 | 491 |
| 492 // Click the button only when the button style mode. | |
| 493 case ui::VKEY_SPACE: | |
| 494 if (style_ == STYLE_NOTIFY_ON_CLICK) { | |
| 495 // When pressing space, the click event will be raised after the key is | |
| 496 // released. | |
| 497 text_button_->SetState(Button::STATE_PRESSED); | |
| 498 } | |
| 499 break; | |
| 500 | |
| 501 // Click the button only when the button style mode. | |
| 502 case ui::VKEY_RETURN: | |
| 503 HandleClickEvent(); | |
| 504 break; | |
| 505 | |
| 289 default: | 506 default: |
| 290 return false; | 507 return false; |
| 291 } | 508 } |
| 292 | 509 |
| 293 if (show_menu) { | 510 if (show_menu) { |
| 294 UpdateFromModel(); | 511 UpdateFromModel(); |
| 295 ShowDropDownMenu(ui::MENU_SOURCE_KEYBOARD); | 512 ShowDropDownMenu(ui::MENU_SOURCE_KEYBOARD); |
| 296 } else if (new_index != selected_index_ && new_index != kNoSelection) { | 513 } else if (new_index != selected_index_ && new_index != kNoSelection) { |
| 297 DCHECK(!model()->IsItemSeparatorAt(new_index)); | 514 DCHECK(!model()->IsItemSeparatorAt(new_index)); |
| 298 selected_index_ = new_index; | 515 selected_index_ = new_index; |
| 299 OnSelectionChanged(); | 516 OnSelectionChanged(); |
| 300 } | 517 } |
| 301 | 518 |
| 302 return true; | 519 return true; |
| 303 } | 520 } |
| 304 | 521 |
| 305 bool Combobox::OnKeyReleased(const ui::KeyEvent& e) { | 522 bool Combobox::OnKeyReleased(const ui::KeyEvent& e) { |
| 306 return false; // crbug.com/127520 | 523 if (style_ != STYLE_NOTIFY_ON_CLICK) |
| 307 } | 524 return false; // crbug.com/127520 |
| 308 | 525 |
| 309 void Combobox::OnGestureEvent(ui::GestureEvent* gesture) { | 526 if (e.key_code() == ui::VKEY_SPACE) |
| 310 if (gesture->type() == ui::ET_GESTURE_TAP) { | 527 HandleClickEvent(); |
| 311 UpdateFromModel(); | 528 |
| 312 ShowDropDownMenu(ui::MENU_SOURCE_TOUCH); | 529 return false; |
| 313 gesture->StopPropagation(); | |
| 314 return; | |
| 315 } | |
| 316 View::OnGestureEvent(gesture); | |
| 317 } | 530 } |
| 318 | 531 |
| 319 void Combobox::OnPaint(gfx::Canvas* canvas) { | 532 void Combobox::OnPaint(gfx::Canvas* canvas) { |
| 320 OnPaintBackground(canvas); | 533 switch (style_) { |
| 321 PaintText(canvas); | 534 case STYLE_SHOW_DROP_DOWN_ON_CLICK: { |
| 322 OnPaintBorder(canvas); | 535 OnPaintBackground(canvas); |
| 536 PaintText(canvas); | |
| 537 OnPaintBorder(canvas); | |
| 538 break; | |
| 539 } | |
| 540 case STYLE_NOTIFY_ON_CLICK: { | |
| 541 PaintButtons(canvas); | |
| 542 PaintText(canvas); | |
| 543 break; | |
| 544 } | |
| 545 } | |
| 323 } | 546 } |
| 324 | 547 |
| 325 void Combobox::OnFocus() { | 548 void Combobox::OnFocus() { |
| 326 GetInputMethod()->OnFocus(); | 549 GetInputMethod()->OnFocus(); |
| 327 View::OnFocus(); | 550 View::OnFocus(); |
| 328 // Border renders differently when focused. | 551 // Border renders differently when focused. |
| 329 SchedulePaint(); | 552 SchedulePaint(); |
| 330 } | 553 } |
| 331 | 554 |
| 332 void Combobox::OnBlur() { | 555 void Combobox::OnBlur() { |
| 333 GetInputMethod()->OnBlur(); | 556 GetInputMethod()->OnBlur(); |
| 334 if (selector_) | 557 if (selector_) |
| 335 selector_->OnViewBlur(); | 558 selector_->OnViewBlur(); |
| 336 // Border renders differently when focused. | 559 // Border renders differently when focused. |
| 337 SchedulePaint(); | 560 SchedulePaint(); |
| 338 } | 561 } |
| 339 | 562 |
| 340 void Combobox::GetAccessibleState(ui::AccessibleViewState* state) { | 563 void Combobox::GetAccessibleState(ui::AccessibleViewState* state) { |
| 341 state->role = ui::AccessibilityTypes::ROLE_COMBOBOX; | 564 state->role = ui::AccessibilityTypes::ROLE_COMBOBOX; |
| 342 state->name = accessible_name_; | 565 state->name = accessible_name_; |
| 343 state->value = model_->GetItemAt(selected_index_); | 566 state->value = model_->GetItemAt(selected_index_); |
| 344 state->index = selected_index_; | 567 state->index = selected_index_; |
| 345 state->count = model_->GetItemCount(); | 568 state->count = model_->GetItemCount(); |
| 346 } | 569 } |
| 347 | 570 |
| 348 void Combobox::OnModelChanged() { | 571 void Combobox::OnModelChanged() { |
| 349 ModelChanged(); | 572 ModelChanged(); |
| 350 } | 573 } |
| 351 | 574 |
| 575 void Combobox::ButtonPressed(Button* sender, const ui::Event& event) { | |
| 576 RequestFocus(); | |
| 577 | |
| 578 if (sender == text_button_) { | |
| 579 HandleClickEvent(); | |
| 580 } else { | |
| 581 DCHECK_EQ(arrow_button_, sender); | |
| 582 // TODO(hajimehoshi): Fix the problem that the arrow button blinks when | |
| 583 // cliking this while the dropdown menu is opened. | |
| 584 const base::TimeDelta delta = base::Time::Now() - closed_time_; | |
| 585 if (delta.InMilliseconds() <= kMinimumMsBetweenButtonClicks) | |
| 586 return; | |
| 587 | |
| 588 ui::MenuSourceType source_type = ui::MENU_SOURCE_MOUSE; | |
| 589 if (event.IsKeyEvent()) | |
| 590 source_type = ui::MENU_SOURCE_KEYBOARD; | |
| 591 else if (event.IsGestureEvent() || event.IsTouchEvent()) | |
| 592 source_type = ui::MENU_SOURCE_TOUCH; | |
| 593 ShowDropDownMenu(source_type); | |
| 594 } | |
| 595 } | |
| 596 | |
| 352 void Combobox::UpdateFromModel() { | 597 void Combobox::UpdateFromModel() { |
| 353 int max_width = 0; | 598 int max_width = 0; |
| 354 const gfx::Font& font = Combobox::GetFont(); | 599 const gfx::Font& font = Combobox::GetFont(); |
| 355 | 600 |
| 356 MenuItemView* menu = new MenuItemView(this); | 601 MenuItemView* menu = new MenuItemView(this); |
| 357 // MenuRunner owns |menu|. | 602 // MenuRunner owns |menu|. |
| 358 dropdown_list_menu_runner_.reset(new MenuRunner(menu)); | 603 dropdown_list_menu_runner_.reset(new MenuRunner(menu)); |
| 359 | 604 |
| 360 int num_items = model()->GetItemCount(); | 605 int num_items = model()->GetItemCount(); |
| 361 for (int i = 0; i < num_items; ++i) { | 606 for (int i = 0; i < num_items; ++i) { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 377 content_size_.SetSize(max_width, font.GetHeight()); | 622 content_size_.SetSize(max_width, font.GetHeight()); |
| 378 } | 623 } |
| 379 | 624 |
| 380 void Combobox::AdjustBoundsForRTLUI(gfx::Rect* rect) const { | 625 void Combobox::AdjustBoundsForRTLUI(gfx::Rect* rect) const { |
| 381 rect->set_x(GetMirroredXForRect(*rect)); | 626 rect->set_x(GetMirroredXForRect(*rect)); |
| 382 } | 627 } |
| 383 | 628 |
| 384 void Combobox::PaintText(gfx::Canvas* canvas) { | 629 void Combobox::PaintText(gfx::Canvas* canvas) { |
| 385 gfx::Insets insets = GetInsets(); | 630 gfx::Insets insets = GetInsets(); |
| 386 | 631 |
| 387 canvas->Save(); | 632 gfx::ScopedCanvas scoped_canvas(canvas); |
| 388 canvas->ClipRect(GetContentsBounds()); | 633 canvas->ClipRect(GetContentsBounds()); |
| 389 | 634 |
| 390 int x = insets.left(); | 635 int x = insets.left(); |
| 391 int y = insets.top(); | 636 int y = insets.top(); |
| 392 int text_height = height() - insets.height(); | 637 int text_height = height() - insets.height(); |
| 393 SkColor text_color = invalid() ? kInvalidTextColor : | 638 SkColor text_color = invalid() ? kInvalidTextColor : |
| 394 GetNativeTheme()->GetSystemColor( | 639 GetNativeTheme()->GetSystemColor( |
| 395 ui::NativeTheme::kColorId_LabelEnabledColor); | 640 ui::NativeTheme::kColorId_LabelEnabledColor); |
| 396 | 641 |
| 397 DCHECK_GE(selected_index_, 0); | 642 DCHECK_GE(selected_index_, 0); |
| 398 DCHECK_LT(selected_index_, model()->GetItemCount()); | 643 DCHECK_LT(selected_index_, model()->GetItemCount()); |
| 399 if (selected_index_ < 0 || selected_index_ > model()->GetItemCount()) | 644 if (selected_index_ < 0 || selected_index_ > model()->GetItemCount()) |
| 400 selected_index_ = 0; | 645 selected_index_ = 0; |
| 401 string16 text = model()->GetItemAt(selected_index_); | 646 string16 text = model()->GetItemAt(selected_index_); |
| 402 | 647 |
| 403 int disclosure_arrow_offset = width() - disclosure_arrow_->width() | 648 int disclosure_arrow_offset = width() - disclosure_arrow_->width() - |
| 404 - kDisclosureArrowLeftPadding - kDisclosureArrowRightPadding; | 649 GetDisclosureArrowLeftPadding() - GetDisclosureArrowRightPadding(); |
| 405 | 650 |
| 406 const gfx::Font& font = Combobox::GetFont(); | 651 const gfx::Font& font = Combobox::GetFont(); |
| 407 int text_width = font.GetStringWidth(text); | 652 int text_width = font.GetStringWidth(text); |
| 408 if ((text_width + insets.width()) > disclosure_arrow_offset) | 653 if ((text_width + insets.width()) > disclosure_arrow_offset) |
| 409 text_width = disclosure_arrow_offset - insets.width(); | 654 text_width = disclosure_arrow_offset - insets.width(); |
| 410 | 655 |
| 411 gfx::Rect text_bounds(x, y, text_width, text_height); | 656 gfx::Rect text_bounds(x, y, text_width, text_height); |
| 412 AdjustBoundsForRTLUI(&text_bounds); | 657 AdjustBoundsForRTLUI(&text_bounds); |
| 413 canvas->DrawStringInt(text, font, text_color, text_bounds); | 658 canvas->DrawStringInt(text, font, text_color, text_bounds); |
| 414 | 659 |
| 415 gfx::Rect arrow_bounds(disclosure_arrow_offset + kDisclosureArrowLeftPadding, | 660 int arrow_x = disclosure_arrow_offset + GetDisclosureArrowLeftPadding(); |
| 661 gfx::Rect arrow_bounds(arrow_x, | |
| 416 height() / 2 - disclosure_arrow_->height() / 2, | 662 height() / 2 - disclosure_arrow_->height() / 2, |
| 417 disclosure_arrow_->width(), | 663 disclosure_arrow_->width(), |
| 418 disclosure_arrow_->height()); | 664 disclosure_arrow_->height()); |
| 419 AdjustBoundsForRTLUI(&arrow_bounds); | 665 AdjustBoundsForRTLUI(&arrow_bounds); |
| 420 | 666 |
| 421 SkPaint paint; | 667 SkPaint paint; |
| 422 // This makes the arrow subtractive. | 668 // This makes the arrow subtractive. |
| 423 if (invalid()) | 669 if (invalid()) |
| 424 paint.setXfermodeMode(SkXfermode::kDstOut_Mode); | 670 paint.setXfermodeMode(SkXfermode::kDstOut_Mode); |
| 425 canvas->DrawImageInt(*disclosure_arrow_, arrow_bounds.x(), arrow_bounds.y(), | 671 canvas->DrawImageInt(*disclosure_arrow_, arrow_bounds.x(), arrow_bounds.y(), |
| 426 paint); | 672 paint); |
| 673 } | |
| 427 | 674 |
| 428 canvas->Restore(); | 675 void Combobox::PaintButtons(gfx::Canvas* canvas) { |
| 676 DCHECK(style_ == STYLE_NOTIFY_ON_CLICK); | |
| 677 | |
| 678 gfx::ScopedCanvas scoped_canvas(canvas); | |
| 679 if (base::i18n::IsRTL()) { | |
| 680 canvas->Translate(gfx::Vector2d(width(), 0)); | |
| 681 canvas->Scale(-1, 1); | |
| 682 } | |
| 683 | |
| 684 bool focused = HasFocus(); | |
| 685 const std::vector<const gfx::ImageSkia*>& arrow_button_images = | |
| 686 menu_button_images_[focused][ | |
| 687 arrow_button_->state() == Button::STATE_HOVERED ? | |
| 688 Button::STATE_NORMAL : arrow_button_->state()]; | |
| 689 | |
| 690 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
| |
| 691 int text_button_hover_alpha = | |
| 692 text_button_->state() == Button::STATE_PRESSED ? 0 : | |
| 693 static_cast<int>(static_cast<TransparentButton*>(text_button_)-> | |
| 694 GetAnimationValue() * 255); | |
| 695 if (text_button_hover_alpha < 255) { | |
| 696 canvas->SaveLayerAlpha(255 - text_button_hover_alpha); | |
| 697 Painter* text_button_painter = | |
| 698 body_button_painters_[focused][ | |
| 699 text_button_->state() == Button::STATE_HOVERED ? | |
| 700 Button::STATE_NORMAL : text_button_->state()].get(); | |
| 701 Painter::PaintPainterAt(canvas, text_button_painter, | |
| 702 gfx::Rect(0, 0, text_button_width, height())); | |
| 703 canvas->Restore(); | |
| 704 } | |
| 705 if (0 < text_button_hover_alpha) { | |
| 706 canvas->SaveLayerAlpha(text_button_hover_alpha); | |
| 707 Painter* text_button_hovered_painter = | |
| 708 body_button_painters_[focused][Button::STATE_HOVERED].get(); | |
| 709 Painter::PaintPainterAt(canvas, text_button_hovered_painter, | |
| 710 gfx::Rect(0, 0, text_button_width, height())); | |
| 711 canvas->Restore(); | |
| 712 } | |
| 713 | |
| 714 int arrow_button_x = text_button_width; | |
| 715 int arrow_button_hover_alpha = | |
| 716 arrow_button_->state() == Button::STATE_PRESSED ? 0 : | |
| 717 static_cast<int>(static_cast<TransparentButton*>(arrow_button_)-> | |
| 718 GetAnimationValue() * 255); | |
| 719 if (arrow_button_hover_alpha < 255) { | |
| 720 canvas->SaveLayerAlpha(255 - arrow_button_hover_alpha); | |
| 721 PaintArrowButton(canvas, arrow_button_images, arrow_button_x, height()); | |
| 722 canvas->Restore(); | |
| 723 } | |
| 724 if (0 < arrow_button_hover_alpha) { | |
| 725 canvas->SaveLayerAlpha(arrow_button_hover_alpha); | |
| 726 const std::vector<const gfx::ImageSkia*>& arrow_button_hovered_images = | |
| 727 menu_button_images_[focused][Button::STATE_HOVERED]; | |
| 728 PaintArrowButton(canvas, arrow_button_hovered_images, | |
| 729 arrow_button_x, height()); | |
| 730 canvas->Restore(); | |
| 731 } | |
| 429 } | 732 } |
| 430 | 733 |
| 431 void Combobox::ShowDropDownMenu(ui::MenuSourceType source_type) { | 734 void Combobox::ShowDropDownMenu(ui::MenuSourceType source_type) { |
| 432 if (!dropdown_list_menu_runner_.get()) | 735 if (!dropdown_list_menu_runner_.get()) |
| 433 UpdateFromModel(); | 736 UpdateFromModel(); |
| 434 | 737 |
| 435 // Extend the menu to the width of the combobox. | 738 // Extend the menu to the width of the combobox. |
| 436 MenuItemView* menu = dropdown_list_menu_runner_->GetMenu(); | 739 MenuItemView* menu = dropdown_list_menu_runner_->GetMenu(); |
| 437 SubmenuView* submenu = menu->CreateSubmenu(); | 740 SubmenuView* submenu = menu->CreateSubmenu(); |
| 438 submenu->set_minimum_preferred_width(size().width() - | 741 submenu->set_minimum_preferred_width( |
| 439 (kMenuBorderWidthLeft + kMenuBorderWidthRight)); | 742 size().width() - (kMenuBorderWidthLeft + kMenuBorderWidthRight)); |
| 440 | 743 |
| 441 gfx::Rect lb = GetLocalBounds(); | 744 gfx::Rect lb = GetLocalBounds(); |
| 442 gfx::Point menu_position(lb.origin()); | 745 gfx::Point menu_position(lb.origin()); |
| 443 | 746 |
| 444 // Inset the menu's requested position so the border of the menu lines up | 747 // Inset the menu's requested position so the border of the menu lines up |
| 445 // with the border of the combobox. | 748 // with the border of the combobox. |
| 446 menu_position.set_x(menu_position.x() + kMenuBorderWidthLeft); | 749 menu_position.set_x(menu_position.x() + kMenuBorderWidthLeft); |
| 447 menu_position.set_y(menu_position.y() + kMenuBorderWidthTop); | 750 menu_position.set_y(menu_position.y() + kMenuBorderWidthTop); |
| 448 lb.set_width(lb.width() - (kMenuBorderWidthLeft + kMenuBorderWidthRight)); | 751 lb.set_width(lb.width() - (kMenuBorderWidthLeft + kMenuBorderWidthRight)); |
| 449 | 752 |
| 450 View::ConvertPointToScreen(this, &menu_position); | 753 View::ConvertPointToScreen(this, &menu_position); |
| 451 if (menu_position.x() < 0) | 754 if (menu_position.x() < 0) |
| 452 menu_position.set_x(0); | 755 menu_position.set_x(0); |
| 453 | 756 |
| 454 gfx::Rect bounds(menu_position, lb.size()); | 757 gfx::Rect bounds(menu_position, lb.size()); |
| 455 | 758 |
| 759 Button::ButtonState original_state; | |
| 760 if (arrow_button_) { | |
| 761 original_state = arrow_button_->state(); | |
| 762 arrow_button_->SetState(Button::STATE_PRESSED); | |
| 763 } | |
| 456 dropdown_open_ = true; | 764 dropdown_open_ = true; |
| 457 if (dropdown_list_menu_runner_->RunMenuAt(GetWidget(), NULL, bounds, | 765 if (dropdown_list_menu_runner_->RunMenuAt(GetWidget(), NULL, bounds, |
| 458 MenuItemView::TOPLEFT, source_type, MenuRunner::COMBOBOX) == | 766 MenuItemView::TOPLEFT, source_type, MenuRunner::COMBOBOX) == |
| 459 MenuRunner::MENU_DELETED) | 767 MenuRunner::MENU_DELETED) { |
| 460 return; | 768 return; |
| 769 } | |
| 461 dropdown_open_ = false; | 770 dropdown_open_ = false; |
| 771 if (arrow_button_) | |
| 772 arrow_button_->SetState(original_state); | |
| 462 closed_time_ = base::Time::Now(); | 773 closed_time_ = base::Time::Now(); |
| 463 | 774 |
| 464 // Need to explicitly clear mouse handler so that events get sent | 775 // Need to explicitly clear mouse handler so that events get sent |
| 465 // properly after the menu finishes running. If we don't do this, then | 776 // properly after the menu finishes running. If we don't do this, then |
| 466 // the first click to other parts of the UI is eaten. | 777 // the first click to other parts of the UI is eaten. |
| 467 SetMouseHandler(NULL); | 778 SetMouseHandler(NULL); |
| 468 } | 779 } |
| 469 | 780 |
| 470 void Combobox::OnSelectionChanged() { | 781 void Combobox::OnSelectionChanged() { |
| 471 if (listener_) | 782 if (listener_) |
| 472 listener_->OnSelectedIndexChanged(this); | 783 listener_->OnSelectedIndexChanged(this); |
| 473 NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_VALUE_CHANGED, false); | 784 NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_VALUE_CHANGED, false); |
| 474 SchedulePaint(); | 785 SchedulePaint(); |
| 475 } | 786 } |
| 476 | 787 |
| 477 int Combobox::MenuCommandToIndex(int menu_command_id) const { | 788 int Combobox::MenuCommandToIndex(int menu_command_id) const { |
| 478 // (note that the id received is offset by kFirstMenuItemId) | 789 // (note that the id received is offset by kFirstMenuItemId) |
| 479 // Revert menu ID offset to map back to combobox model. | 790 // Revert menu ID offset to map back to combobox model. |
| 480 int index = menu_command_id - kFirstMenuItemId; | 791 int index = menu_command_id - kFirstMenuItemId; |
| 481 DCHECK_LT(index, model()->GetItemCount()); | 792 DCHECK_LT(index, model()->GetItemCount()); |
| 482 return index; | 793 return index; |
| 483 } | 794 } |
| 484 | 795 |
| 796 int Combobox::GetDisclosureArrowLeftPadding() const { | |
| 797 switch (style_) { | |
| 798 case STYLE_SHOW_DROP_DOWN_ON_CLICK: | |
| 799 return kDisclosureArrowLeftPadding; | |
| 800 case STYLE_NOTIFY_ON_CLICK: | |
| 801 return kDisclosureArrowButtonLeftPadding; | |
| 802 } | |
| 803 NOTREACHED(); | |
| 804 return 0; | |
| 805 } | |
| 806 | |
| 807 int Combobox::GetDisclosureArrowRightPadding() const { | |
| 808 switch (style_) { | |
| 809 case STYLE_SHOW_DROP_DOWN_ON_CLICK: | |
| 810 return kDisclosureArrowRightPadding; | |
| 811 case STYLE_NOTIFY_ON_CLICK: | |
| 812 return kDisclosureArrowButtonRightPadding; | |
| 813 } | |
| 814 NOTREACHED(); | |
| 815 return 0; | |
| 816 } | |
| 817 | |
| 818 void Combobox::HandleClickEvent() { | |
| 819 if (style_ != STYLE_NOTIFY_ON_CLICK) | |
| 820 return; | |
| 821 | |
| 822 if (listener_) | |
| 823 listener_->OnComboboxTextButtonClicked(this); | |
| 824 } | |
| 825 | |
| 485 } // namespace views | 826 } // namespace views |
| OLD | NEW |