Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(211)

Unified Diff: ui/views/controls/combobox/combobox.cc

Issue 851853002: It is time. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Trying to reup because the last upload failed. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/views/controls/combobox/combobox.h ('k') | ui/views/controls/combobox/combobox_listener.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/views/controls/combobox/combobox.cc
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc
deleted file mode 100644
index 22689c736ede2a9a98656b25deda80fbdeb0b8ee..0000000000000000000000000000000000000000
--- a/ui/views/controls/combobox/combobox.cc
+++ /dev/null
@@ -1,868 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#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 "ui/accessibility/ax_view_state.h"
-#include "ui/base/models/combobox_model.h"
-#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/gfx/text_utils.h"
-#include "ui/native_theme/common_theme.h"
-#include "ui/native_theme/native_theme.h"
-#include "ui/resources/grit/ui_resources.h"
-#include "ui/views/background.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_item_view.h"
-#include "ui/views/controls/menu/menu_runner.h"
-#include "ui/views/controls/menu/menu_runner_handler.h"
-#include "ui/views/controls/menu/submenu_view.h"
-#include "ui/views/controls/prefix_selector.h"
-#include "ui/views/controls/textfield/textfield.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 {
-
-namespace {
-
-// Menu border widths
-const int kMenuBorderWidthLeft = 1;
-const int kMenuBorderWidthTop = 1;
-const int kMenuBorderWidthRight = 1;
-
-// Limit how small a combobox can be.
-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;
-
-// 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);
-const int kFocusedBodyButtonImages[] = IMAGE_GRID(IDR_COMBOBOX_BUTTON_F);
-const int kFocusedHoveredBodyButtonImages[] =
- IMAGE_GRID(IDR_COMBOBOX_BUTTON_F_H);
-const int kFocusedPressedBodyButtonImages[] =
- IMAGE_GRID(IDR_COMBOBOX_BUTTON_F_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);
-const int kFocusedMenuButtonImages[] = MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_F);
-const int kFocusedHoveredMenuButtonImages[] =
- MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_F_H);
-const int kFocusedPressedMenuButtonImages[] =
- MENU_IMAGE_GRID(IDR_COMBOBOX_BUTTON_F_P);
-
-#undef MENU_IMAGE_GRID
-
-// 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() {}
-
- virtual bool OnMousePressed(const ui::MouseEvent& mouse_event) override {
- parent()->RequestFocus();
- return true;
- }
-
- 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.
-int GetAdjacentIndex(ui::ComboboxModel* model, int increment, int index) {
- DCHECK(increment == -1 || increment == 1);
-
- index += increment;
- while (index >= 0 && index < model->GetItemCount()) {
- if (!model->IsItemSeparatorAt(index) || !model->IsItemEnabledAt(index))
- return index;
- index += increment;
- }
- 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)
-const int* GetBodyButtonImageIds(bool focused,
- Button::ButtonState state,
- size_t* num) {
- DCHECK(num);
- *num = 9;
- switch (state) {
- case Button::STATE_DISABLED:
- return focused ? kFocusedBodyButtonImages : kBodyButtonImages;
- case Button::STATE_NORMAL:
- return focused ? kFocusedBodyButtonImages : kBodyButtonImages;
- case Button::STATE_HOVERED:
- return focused ?
- kFocusedHoveredBodyButtonImages : kHoveredBodyButtonImages;
- case Button::STATE_PRESSED:
- return focused ?
- kFocusedPressedBodyButtonImages : 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 focused ? kFocusedMenuButtonImages : kMenuButtonImages;
- case Button::STATE_NORMAL:
- return focused ? kFocusedMenuButtonImages : kMenuButtonImages;
- case Button::STATE_HOVERED:
- return focused ?
- kFocusedHoveredMenuButtonImages : kHoveredMenuButtonImages;
- case Button::STATE_PRESSED:
- return focused ?
- kFocusedPressedMenuButtonImages : 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
-const char Combobox::kViewClassName[] = "views/Combobox";
-
-////////////////////////////////////////////////////////////////////////////////
-// Combobox, public:
-
-Combobox::Combobox(ui::ComboboxModel* model)
- : model_(model),
- style_(STYLE_NORMAL),
- listener_(NULL),
- selected_index_(model_->GetDefaultIndex()),
- invalid_(false),
- menu_(NULL),
- dropdown_open_(false),
- text_button_(new TransparentButton(this)),
- arrow_button_(new TransparentButton(this)),
- weak_ptr_factory_(this) {
- model_->AddObserver(this);
- UpdateFromModel();
- SetFocusable(true);
- UpdateBorder();
-
- // Initialize the button images.
- Button::ButtonState button_states[] = {
- Button::STATE_DISABLED,
- Button::STATE_NORMAL,
- Button::STATE_HOVERED,
- Button::STATE_PRESSED,
- };
- for (int i = 0; i < 2; i++) {
- for (size_t state_index = 0; state_index < arraysize(button_states);
- state_index++) {
- Button::ButtonState state = button_states[state_index];
- size_t num;
- bool focused = !!i;
- 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_->SetFocusable(false);
- arrow_button_->SetFocusable(false);
- AddChildView(text_button_);
- AddChildView(arrow_button_);
-}
-
-Combobox::~Combobox() {
- model_->RemoveObserver(this);
-}
-
-// static
-const gfx::FontList& Combobox::GetFontList() {
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- return rb.GetFontList(ui::ResourceBundle::BaseFont);
-}
-
-void Combobox::SetStyle(Style style) {
- if (style_ == style)
- return;
-
- style_ = style;
- if (style_ == STYLE_ACTION)
- selected_index_ = 0;
-
- UpdateBorder();
- UpdateFromModel();
- PreferredSizeChanged();
-}
-
-void Combobox::ModelChanged() {
- selected_index_ = std::min(0, model_->GetItemCount());
- UpdateFromModel();
- PreferredSizeChanged();
-}
-
-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);
- return true;
- }
- }
- return false;
-}
-
-void Combobox::SetAccessibleName(const base::string16& name) {
- accessible_name_ = name;
-}
-
-void Combobox::SetInvalid(bool invalid) {
- if (invalid == invalid_)
- return;
-
- invalid_ = invalid;
-
- UpdateBorder();
- SchedulePaint();
-}
-
-ui::TextInputClient* Combobox::GetTextInputClient() {
- if (!selector_)
- selector_.reset(new PrefixSelector(this));
- return selector_.get();
-}
-
-void Combobox::Layout() {
- PrefixDelegate::Layout();
-
- gfx::Insets insets = GetInsets();
- int text_button_width = 0;
- int arrow_button_width = 0;
-
- switch (style_) {
- case STYLE_NORMAL: {
- arrow_button_width = width();
- break;
- }
- case STYLE_ACTION: {
- arrow_button_width = GetDisclosureArrowLeftPadding() +
- ArrowSize().width() +
- GetDisclosureArrowRightPadding();
- text_button_width = width() - arrow_button_width;
- break;
- }
- }
-
- int arrow_button_x = std::max(0, text_button_width);
- text_button_->SetBounds(0, 0, std::max(0, text_button_width), height());
- arrow_button_->SetBounds(arrow_button_x, 0, arrow_button_width, height());
-}
-
-bool Combobox::IsItemChecked(int id) const {
- return false;
-}
-
-bool Combobox::IsCommandEnabled(int id) const {
- return model()->IsItemEnabledAt(MenuCommandToIndex(id));
-}
-
-void Combobox::ExecuteCommand(int id) {
- selected_index_ = MenuCommandToIndex(id);
- OnPerformAction();
-}
-
-bool Combobox::GetAccelerator(int id, ui::Accelerator* accel) const {
- return false;
-}
-
-int Combobox::GetRowCount() {
- return model()->GetItemCount();
-}
-
-int Combobox::GetSelectedRow() {
- return selected_index_;
-}
-
-void Combobox::SetSelectedRow(int row) {
- int prev_index = selected_index_;
- SetSelectedIndex(row);
- if (selected_index_ != prev_index)
- OnPerformAction();
-}
-
-base::string16 Combobox::GetTextForRow(int row) {
- return model()->IsItemSeparatorAt(row) ? base::string16() :
- model()->GetItemAt(row);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Combobox, View overrides:
-
-gfx::Size Combobox::GetPreferredSize() const {
- // The preferred size will drive the local bounds which in turn is used to set
- // the minimum width for the dropdown list.
- gfx::Insets insets = GetInsets();
- insets += gfx::Insets(Textfield::kTextPadding,
- Textfield::kTextPadding,
- Textfield::kTextPadding,
- Textfield::kTextPadding);
- int total_width = std::max(kMinComboboxWidth, content_size_.width()) +
- insets.width() + GetDisclosureArrowLeftPadding() +
- ArrowSize().width() + GetDisclosureArrowRightPadding();
- return gfx::Size(total_width, content_size_.height() + insets.height());
-}
-
-const char* Combobox::GetClassName() const {
- return kViewClassName;
-}
-
-bool Combobox::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) {
- // Escape should close the drop down list when it is active, not host UI.
- if (e.key_code() != ui::VKEY_ESCAPE ||
- e.IsShiftDown() || e.IsControlDown() || e.IsAltDown()) {
- return false;
- }
- return dropdown_open_;
-}
-
-bool Combobox::OnKeyPressed(const ui::KeyEvent& e) {
- // TODO(oshima): handle IME.
- DCHECK_EQ(e.type(), ui::ET_KEY_PRESSED);
-
- DCHECK_GE(selected_index_, 0);
- DCHECK_LT(selected_index_, model()->GetItemCount());
- if (selected_index_ < 0 || selected_index_ > model()->GetItemCount())
- selected_index_ = 0;
-
- bool show_menu = false;
- int new_index = kNoSelection;
- switch (e.key_code()) {
- // Show the menu on F4 without modifiers.
- case ui::VKEY_F4:
- if (e.IsAltDown() || e.IsAltGrDown() || e.IsControlDown())
- return false;
- show_menu = true;
- break;
-
- // Move to the next item if any, or show the menu on Alt+Down like Windows.
- case ui::VKEY_DOWN:
- if (e.IsAltDown())
- show_menu = true;
- else
- new_index = GetAdjacentIndex(model(), 1, selected_index_);
- break;
-
- // Move to the end of the list.
- case ui::VKEY_END:
- case ui::VKEY_NEXT: // Page down.
- new_index = GetAdjacentIndex(model(), -1, model()->GetItemCount());
- break;
-
- // Move to the beginning of the list.
- case ui::VKEY_HOME:
- case ui::VKEY_PRIOR: // Page up.
- new_index = GetAdjacentIndex(model(), 1, -1);
- break;
-
- // Move to the previous item if any.
- case ui::VKEY_UP:
- new_index = GetAdjacentIndex(model(), -1, selected_index_);
- break;
-
- // Click the button only when the button style mode.
- case ui::VKEY_SPACE:
- if (style_ == STYLE_ACTION) {
- // When pressing space, the click event will be raised after the key is
- // released.
- text_button_->SetState(Button::STATE_PRESSED);
- } else {
- return false;
- }
- break;
-
- // Click the button only when the button style mode.
- case ui::VKEY_RETURN:
- if (style_ != STYLE_ACTION)
- return false;
- OnPerformAction();
- break;
-
- default:
- return false;
- }
-
- if (show_menu) {
- UpdateFromModel();
- ShowDropDownMenu(ui::MENU_SOURCE_KEYBOARD);
- } else if (new_index != selected_index_ && new_index != kNoSelection &&
- style_ != STYLE_ACTION) {
- DCHECK(!model()->IsItemSeparatorAt(new_index));
- selected_index_ = new_index;
- OnPerformAction();
- }
-
- return true;
-}
-
-bool Combobox::OnKeyReleased(const ui::KeyEvent& e) {
- if (style_ != STYLE_ACTION)
- return false; // crbug.com/127520
-
- if (e.key_code() == ui::VKEY_SPACE && style_ == STYLE_ACTION)
- OnPerformAction();
-
- return false;
-}
-
-void Combobox::OnPaint(gfx::Canvas* canvas) {
- switch (style_) {
- case STYLE_NORMAL: {
- OnPaintBackground(canvas);
- PaintText(canvas);
- OnPaintBorder(canvas);
- break;
- }
- case STYLE_ACTION: {
- PaintButtons(canvas);
- PaintText(canvas);
- break;
- }
- }
-}
-
-void Combobox::OnFocus() {
- GetInputMethod()->OnFocus();
- View::OnFocus();
- // Border renders differently when focused.
- SchedulePaint();
-}
-
-void Combobox::OnBlur() {
- GetInputMethod()->OnBlur();
- if (selector_)
- selector_->OnViewBlur();
- // Border renders differently when focused.
- SchedulePaint();
-}
-
-void Combobox::GetAccessibleState(ui::AXViewState* state) {
- state->role = ui::AX_ROLE_COMBO_BOX;
- state->name = accessible_name_;
- state->value = model_->GetItemAt(selected_index_);
- state->index = selected_index_;
- state->count = model_->GetItemCount();
-}
-
-void Combobox::OnComboboxModelChanged(ui::ComboboxModel* model) {
- DCHECK_EQ(model, model_);
- ModelChanged();
-}
-
-void Combobox::ButtonPressed(Button* sender, const ui::Event& event) {
- if (!enabled())
- return;
-
- RequestFocus();
-
- if (sender == text_button_) {
- OnPerformAction();
- } 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() {
- const gfx::FontList& font_list = Combobox::GetFontList();
-
- menu_ = new MenuItemView(this);
- // MenuRunner owns |menu_|.
- dropdown_list_menu_runner_.reset(new MenuRunner(menu_, MenuRunner::COMBOBOX));
-
- int num_items = model()->GetItemCount();
- int width = 0;
- bool text_item_appended = false;
- for (int i = 0; i < num_items; ++i) {
- // When STYLE_ACTION is used, the first item and the following separators
- // are not added to the dropdown menu. It is assumed that the first item is
- // always selected and rendered on the top of the action button.
- if (model()->IsItemSeparatorAt(i)) {
- if (text_item_appended || style_ != STYLE_ACTION)
- menu_->AppendSeparator();
- continue;
- }
-
- base::string16 text = model()->GetItemAt(i);
-
- // Inserting the Unicode formatting characters if necessary so that the
- // text is displayed correctly in right-to-left UIs.
- base::i18n::AdjustStringForLocaleDirection(&text);
-
- if (style_ != STYLE_ACTION || i > 0) {
- menu_->AppendMenuItem(i + kFirstMenuItemId, text, MenuItemView::NORMAL);
- text_item_appended = true;
- }
-
- if (style_ != STYLE_ACTION || i == selected_index_)
- width = std::max(width, gfx::GetStringWidth(text, font_list));
- }
-
- content_size_.SetSize(width, font_list.GetHeight());
-}
-
-void Combobox::UpdateBorder() {
- scoped_ptr<FocusableBorder> border(new FocusableBorder());
- if (style_ == STYLE_ACTION)
- border->SetInsets(5, 10, 5, 10);
- if (invalid_)
- border->SetColor(kWarningColor);
- SetBorder(border.Pass());
-}
-
-void Combobox::AdjustBoundsForRTLUI(gfx::Rect* rect) const {
- rect->set_x(GetMirroredXForRect(*rect));
-}
-
-void Combobox::PaintText(gfx::Canvas* canvas) {
- gfx::Insets insets = GetInsets();
- insets += gfx::Insets(0, Textfield::kTextPadding, 0, Textfield::kTextPadding);
-
- gfx::ScopedCanvas scoped_canvas(canvas);
- canvas->ClipRect(GetContentsBounds());
-
- int x = insets.left();
- int y = insets.top();
- int text_height = height() - insets.height();
- SkColor text_color = GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_LabelEnabledColor);
-
- DCHECK_GE(selected_index_, 0);
- DCHECK_LT(selected_index_, model()->GetItemCount());
- if (selected_index_ < 0 || selected_index_ > model()->GetItemCount())
- selected_index_ = 0;
- base::string16 text = model()->GetItemAt(selected_index_);
-
- gfx::Size arrow_size = ArrowSize();
- int disclosure_arrow_offset = width() - arrow_size.width() -
- GetDisclosureArrowLeftPadding() - GetDisclosureArrowRightPadding();
-
- const gfx::FontList& font_list = Combobox::GetFontList();
- int text_width = gfx::GetStringWidth(text, font_list);
- if ((text_width + insets.width()) > disclosure_arrow_offset)
- text_width = disclosure_arrow_offset - insets.width();
-
- gfx::Rect text_bounds(x, y, text_width, text_height);
- AdjustBoundsForRTLUI(&text_bounds);
- canvas->DrawStringRect(text, font_list, text_color, text_bounds);
-
- int arrow_x = disclosure_arrow_offset + GetDisclosureArrowLeftPadding();
- gfx::Rect arrow_bounds(arrow_x,
- height() / 2 - arrow_size.height() / 2,
- arrow_size.width(),
- arrow_size.height());
- AdjustBoundsForRTLUI(&arrow_bounds);
-
- // TODO(estade): hack alert! Remove this direct call into CommonTheme. For now
- // STYLE_ACTION isn't properly themed so we have to override the NativeTheme
- // behavior. See crbug.com/384071
- if (style_ == STYLE_ACTION) {
- ui::CommonThemePaintComboboxArrow(canvas->sk_canvas(), arrow_bounds);
- } else {
- ui::NativeTheme::ExtraParams ignored;
- GetNativeTheme()->Paint(canvas->sk_canvas(),
- ui::NativeTheme::kComboboxArrow,
- ui::NativeTheme::kNormal,
- arrow_bounds,
- ignored);
- }
-}
-
-void Combobox::PaintButtons(gfx::Canvas* canvas) {
- DCHECK(style_ == STYLE_ACTION);
-
- gfx::ScopedCanvas scoped_canvas(canvas);
- if (base::i18n::IsRTL()) {
- canvas->Translate(gfx::Vector2d(width(), 0));
- canvas->Scale(-1, 1);
- }
-
- 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_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_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) {
- if (!dropdown_list_menu_runner_.get())
- UpdateFromModel();
-
- // Extend the menu to the width of the combobox.
- SubmenuView* submenu = menu_->CreateSubmenu();
- submenu->set_minimum_preferred_width(
- size().width() - (kMenuBorderWidthLeft + kMenuBorderWidthRight));
-
- gfx::Rect lb = GetLocalBounds();
- gfx::Point menu_position(lb.origin());
-
- if (style_ == STYLE_NORMAL) {
- // Inset the menu's requested position so the border of the menu lines up
- // with the border of the combobox.
- menu_position.set_x(menu_position.x() + kMenuBorderWidthLeft);
- menu_position.set_y(menu_position.y() + kMenuBorderWidthTop);
- }
- lb.set_width(lb.width() - (kMenuBorderWidthLeft + kMenuBorderWidthRight));
-
- View::ConvertPointToScreen(this, &menu_position);
- if (menu_position.x() < 0)
- menu_position.set_x(0);
-
- gfx::Rect bounds(menu_position, lb.size());
-
- Button::ButtonState original_state = Button::STATE_NORMAL;
- if (arrow_button_) {
- original_state = arrow_button_->state();
- arrow_button_->SetState(Button::STATE_PRESSED);
- }
- dropdown_open_ = true;
- MenuAnchorPosition anchor_position =
- style_ == STYLE_ACTION ? MENU_ANCHOR_TOPRIGHT : MENU_ANCHOR_TOPLEFT;
- if (dropdown_list_menu_runner_->RunMenuAt(
- GetWidget(), NULL, bounds, anchor_position, source_type) ==
- 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
- // properly after the menu finishes running. If we don't do this, then
- // the first click to other parts of the UI is eaten.
- SetMouseHandler(NULL);
-}
-
-void Combobox::OnPerformAction() {
- NotifyAccessibilityEvent(ui::AX_EVENT_VALUE_CHANGED, false);
- SchedulePaint();
-
- // This combobox may be deleted by the listener.
- base::WeakPtr<Combobox> weak_ptr = weak_ptr_factory_.GetWeakPtr();
- if (listener_)
- listener_->OnPerformAction(this);
-
- if (weak_ptr && style_ == STYLE_ACTION)
- selected_index_ = 0;
-}
-
-int Combobox::MenuCommandToIndex(int menu_command_id) const {
- // (note that the id received is offset by kFirstMenuItemId)
- // Revert menu ID offset to map back to combobox model.
- int index = menu_command_id - kFirstMenuItemId;
- DCHECK_LT(index, model()->GetItemCount());
- return index;
-}
-
-int Combobox::GetDisclosureArrowLeftPadding() const {
- switch (style_) {
- case STYLE_NORMAL:
- return kDisclosureArrowLeftPadding;
- case STYLE_ACTION:
- return kDisclosureArrowButtonLeftPadding;
- }
- NOTREACHED();
- return 0;
-}
-
-int Combobox::GetDisclosureArrowRightPadding() const {
- switch (style_) {
- case STYLE_NORMAL:
- return kDisclosureArrowRightPadding;
- case STYLE_ACTION:
- return kDisclosureArrowButtonRightPadding;
- }
- NOTREACHED();
- return 0;
-}
-
-gfx::Size Combobox::ArrowSize() const {
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
- // TODO(estade): hack alert! This should always use GetNativeTheme(). For now
- // STYLE_ACTION isn't properly themed so we have to override the NativeTheme
- // behavior. See crbug.com/384071
- const ui::NativeTheme* native_theme_for_arrow = style_ == STYLE_ACTION ?
- ui::NativeTheme::instance() :
- GetNativeTheme();
-#else
- const ui::NativeTheme* native_theme_for_arrow = GetNativeTheme();
-#endif
-
- ui::NativeTheme::ExtraParams ignored;
- return native_theme_for_arrow->GetPartSize(ui::NativeTheme::kComboboxArrow,
- ui::NativeTheme::kNormal,
- ignored);
-}
-
-} // namespace views
« no previous file with comments | « ui/views/controls/combobox/combobox.h ('k') | ui/views/controls/combobox/combobox_listener.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698