| Index: ui/views/controls/menu/submenu_view.cc
|
| diff --git a/ui/views/controls/menu/submenu_view.cc b/ui/views/controls/menu/submenu_view.cc
|
| deleted file mode 100644
|
| index e3687403cfae51e17ce12f5243f309af8e52b4c6..0000000000000000000000000000000000000000
|
| --- a/ui/views/controls/menu/submenu_view.cc
|
| +++ /dev/null
|
| @@ -1,511 +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/menu/submenu_view.h"
|
| -
|
| -#include <algorithm>
|
| -
|
| -#include "base/compiler_specific.h"
|
| -#include "ui/accessibility/ax_view_state.h"
|
| -#include "ui/events/event.h"
|
| -#include "ui/gfx/canvas.h"
|
| -#include "ui/gfx/geometry/safe_integer_conversions.h"
|
| -#include "ui/views/controls/menu/menu_config.h"
|
| -#include "ui/views/controls/menu/menu_controller.h"
|
| -#include "ui/views/controls/menu/menu_host.h"
|
| -#include "ui/views/controls/menu/menu_item_view.h"
|
| -#include "ui/views/controls/menu/menu_scroll_view_container.h"
|
| -#include "ui/views/widget/root_view.h"
|
| -#include "ui/views/widget/widget.h"
|
| -
|
| -namespace {
|
| -
|
| -// Height of the drop indicator. This should be an even number.
|
| -const int kDropIndicatorHeight = 2;
|
| -
|
| -// Color of the drop indicator.
|
| -const SkColor kDropIndicatorColor = SK_ColorBLACK;
|
| -
|
| -} // namespace
|
| -
|
| -namespace views {
|
| -
|
| -// static
|
| -const char SubmenuView::kViewClassName[] = "SubmenuView";
|
| -
|
| -SubmenuView::SubmenuView(MenuItemView* parent)
|
| - : parent_menu_item_(parent),
|
| - host_(NULL),
|
| - drop_item_(NULL),
|
| - drop_position_(MenuDelegate::DROP_NONE),
|
| - scroll_view_container_(NULL),
|
| - max_minor_text_width_(0),
|
| - minimum_preferred_width_(0),
|
| - resize_open_menu_(false),
|
| - scroll_animator_(new ScrollAnimator(this)),
|
| - roundoff_error_(0),
|
| - prefix_selector_(this) {
|
| - DCHECK(parent);
|
| - // We'll delete ourselves, otherwise the ScrollView would delete us on close.
|
| - set_owned_by_client();
|
| -}
|
| -
|
| -SubmenuView::~SubmenuView() {
|
| - // The menu may not have been closed yet (it will be hidden, but not
|
| - // necessarily closed).
|
| - Close();
|
| -
|
| - delete scroll_view_container_;
|
| -}
|
| -
|
| -int SubmenuView::GetMenuItemCount() {
|
| - int count = 0;
|
| - for (int i = 0; i < child_count(); ++i) {
|
| - if (child_at(i)->id() == MenuItemView::kMenuItemViewID)
|
| - count++;
|
| - }
|
| - return count;
|
| -}
|
| -
|
| -MenuItemView* SubmenuView::GetMenuItemAt(int index) {
|
| - for (int i = 0, count = 0; i < child_count(); ++i) {
|
| - if (child_at(i)->id() == MenuItemView::kMenuItemViewID &&
|
| - count++ == index) {
|
| - return static_cast<MenuItemView*>(child_at(i));
|
| - }
|
| - }
|
| - NOTREACHED();
|
| - return NULL;
|
| -}
|
| -
|
| -void SubmenuView::ChildPreferredSizeChanged(View* child) {
|
| - if (!resize_open_menu_)
|
| - return;
|
| -
|
| - MenuItemView *item = GetMenuItem();
|
| - MenuController* controller = item->GetMenuController();
|
| -
|
| - if (controller) {
|
| - bool dir;
|
| - gfx::Rect bounds = controller->CalculateMenuBounds(item, false, &dir);
|
| - Reposition(bounds);
|
| - }
|
| -}
|
| -
|
| -void SubmenuView::Layout() {
|
| - // We're in a ScrollView, and need to set our width/height ourselves.
|
| - if (!parent())
|
| - return;
|
| -
|
| - // Use our current y, unless it means part of the menu isn't visible anymore.
|
| - int pref_height = GetPreferredSize().height();
|
| - int new_y;
|
| - if (pref_height > parent()->height())
|
| - new_y = std::max(parent()->height() - pref_height, y());
|
| - else
|
| - new_y = 0;
|
| - SetBounds(x(), new_y, parent()->width(), pref_height);
|
| -
|
| - gfx::Insets insets = GetInsets();
|
| - int x = insets.left();
|
| - int y = insets.top();
|
| - int menu_item_width = width() - insets.width();
|
| - for (int i = 0; i < child_count(); ++i) {
|
| - View* child = child_at(i);
|
| - if (child->visible()) {
|
| - int child_height = child->GetHeightForWidth(menu_item_width);
|
| - child->SetBounds(x, y, menu_item_width, child_height);
|
| - y += child_height;
|
| - }
|
| - }
|
| -}
|
| -
|
| -gfx::Size SubmenuView::GetPreferredSize() const {
|
| - if (!has_children())
|
| - return gfx::Size();
|
| -
|
| - max_minor_text_width_ = 0;
|
| - // The maximum width of items which contain maybe a label and multiple views.
|
| - int max_complex_width = 0;
|
| - // The max. width of items which contain a label and maybe an accelerator.
|
| - int max_simple_width = 0;
|
| -
|
| - // We perform the size calculation in two passes. In the first pass, we
|
| - // calculate the width of the menu. In the second, we calculate the height
|
| - // using that width. This allows views that have flexible widths to adjust
|
| - // accordingly.
|
| - for (int i = 0; i < child_count(); ++i) {
|
| - const View* child = child_at(i);
|
| - if (!child->visible())
|
| - continue;
|
| - if (child->id() == MenuItemView::kMenuItemViewID) {
|
| - const MenuItemView* menu = static_cast<const MenuItemView*>(child);
|
| - const MenuItemView::MenuItemDimensions& dimensions =
|
| - menu->GetDimensions();
|
| - max_simple_width = std::max(
|
| - max_simple_width, dimensions.standard_width);
|
| - max_minor_text_width_ =
|
| - std::max(max_minor_text_width_, dimensions.minor_text_width);
|
| - max_complex_width = std::max(max_complex_width,
|
| - dimensions.standard_width + dimensions.children_width);
|
| - } else {
|
| - max_complex_width = std::max(max_complex_width,
|
| - child->GetPreferredSize().width());
|
| - }
|
| - }
|
| - if (max_minor_text_width_ > 0) {
|
| - max_minor_text_width_ +=
|
| - GetMenuItem()->GetMenuConfig().label_to_minor_text_padding;
|
| - }
|
| - // Finish calculating our optimum width.
|
| - gfx::Insets insets = GetInsets();
|
| - int width = std::max(max_complex_width,
|
| - std::max(max_simple_width + max_minor_text_width_ +
|
| - insets.width(),
|
| - minimum_preferred_width_ - 2 * insets.width()));
|
| -
|
| - // Then, the height for that width.
|
| - int height = 0;
|
| - int menu_item_width = width - insets.width();
|
| - for (int i = 0; i < child_count(); ++i) {
|
| - const View* child = child_at(i);
|
| - height += child->visible() ? child->GetHeightForWidth(menu_item_width) : 0;
|
| - }
|
| -
|
| - return gfx::Size(width, height + insets.height());
|
| -}
|
| -
|
| -void SubmenuView::GetAccessibleState(ui::AXViewState* state) {
|
| - // Inherit most of the state from the parent menu item, except the role.
|
| - if (GetMenuItem())
|
| - GetMenuItem()->GetAccessibleState(state);
|
| - state->role = ui::AX_ROLE_MENU_LIST_POPUP;
|
| -}
|
| -
|
| -ui::TextInputClient* SubmenuView::GetTextInputClient() {
|
| - return &prefix_selector_;
|
| -}
|
| -
|
| -void SubmenuView::PaintChildren(gfx::Canvas* canvas,
|
| - const views::CullSet& cull_set) {
|
| - View::PaintChildren(canvas, cull_set);
|
| -
|
| - if (drop_item_ && drop_position_ != MenuDelegate::DROP_ON)
|
| - PaintDropIndicator(canvas, drop_item_, drop_position_);
|
| -}
|
| -
|
| -bool SubmenuView::GetDropFormats(
|
| - int* formats,
|
| - std::set<OSExchangeData::CustomFormat>* custom_formats) {
|
| - DCHECK(GetMenuItem()->GetMenuController());
|
| - return GetMenuItem()->GetMenuController()->GetDropFormats(this, formats,
|
| - custom_formats);
|
| -}
|
| -
|
| -bool SubmenuView::AreDropTypesRequired() {
|
| - DCHECK(GetMenuItem()->GetMenuController());
|
| - return GetMenuItem()->GetMenuController()->AreDropTypesRequired(this);
|
| -}
|
| -
|
| -bool SubmenuView::CanDrop(const OSExchangeData& data) {
|
| - DCHECK(GetMenuItem()->GetMenuController());
|
| - return GetMenuItem()->GetMenuController()->CanDrop(this, data);
|
| -}
|
| -
|
| -void SubmenuView::OnDragEntered(const ui::DropTargetEvent& event) {
|
| - DCHECK(GetMenuItem()->GetMenuController());
|
| - GetMenuItem()->GetMenuController()->OnDragEntered(this, event);
|
| -}
|
| -
|
| -int SubmenuView::OnDragUpdated(const ui::DropTargetEvent& event) {
|
| - DCHECK(GetMenuItem()->GetMenuController());
|
| - return GetMenuItem()->GetMenuController()->OnDragUpdated(this, event);
|
| -}
|
| -
|
| -void SubmenuView::OnDragExited() {
|
| - DCHECK(GetMenuItem()->GetMenuController());
|
| - GetMenuItem()->GetMenuController()->OnDragExited(this);
|
| -}
|
| -
|
| -int SubmenuView::OnPerformDrop(const ui::DropTargetEvent& event) {
|
| - DCHECK(GetMenuItem()->GetMenuController());
|
| - return GetMenuItem()->GetMenuController()->OnPerformDrop(this, event);
|
| -}
|
| -
|
| -bool SubmenuView::OnMouseWheel(const ui::MouseWheelEvent& e) {
|
| - gfx::Rect vis_bounds = GetVisibleBounds();
|
| - int menu_item_count = GetMenuItemCount();
|
| - if (vis_bounds.height() == height() || !menu_item_count) {
|
| - // All menu items are visible, nothing to scroll.
|
| - return true;
|
| - }
|
| -
|
| - // Find the index of the first menu item whose y-coordinate is >= visible
|
| - // y-coordinate.
|
| - int i = 0;
|
| - while ((i < menu_item_count) && (GetMenuItemAt(i)->y() < vis_bounds.y()))
|
| - ++i;
|
| - if (i == menu_item_count)
|
| - return true;
|
| - int first_vis_index = std::max(0,
|
| - (GetMenuItemAt(i)->y() == vis_bounds.y()) ? i : i - 1);
|
| -
|
| - // If the first item isn't entirely visible, make it visible, otherwise make
|
| - // the next/previous one entirely visible. If enough wasn't scrolled to show
|
| - // any new rows, then just scroll the amount so that smooth scrolling using
|
| - // the trackpad is possible.
|
| - int delta = abs(e.y_offset() / ui::MouseWheelEvent::kWheelDelta);
|
| - if (delta == 0)
|
| - return OnScroll(0, e.y_offset());
|
| - for (bool scroll_up = (e.y_offset() > 0); delta != 0; --delta) {
|
| - int scroll_target;
|
| - if (scroll_up) {
|
| - if (GetMenuItemAt(first_vis_index)->y() == vis_bounds.y()) {
|
| - if (first_vis_index == 0)
|
| - break;
|
| - first_vis_index--;
|
| - }
|
| - scroll_target = GetMenuItemAt(first_vis_index)->y();
|
| - } else {
|
| - if (first_vis_index + 1 == menu_item_count)
|
| - break;
|
| - scroll_target = GetMenuItemAt(first_vis_index + 1)->y();
|
| - if (GetMenuItemAt(first_vis_index)->y() == vis_bounds.y())
|
| - first_vis_index++;
|
| - }
|
| - ScrollRectToVisible(gfx::Rect(gfx::Point(0, scroll_target),
|
| - vis_bounds.size()));
|
| - vis_bounds = GetVisibleBounds();
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void SubmenuView::OnGestureEvent(ui::GestureEvent* event) {
|
| - bool handled = true;
|
| - switch (event->type()) {
|
| - case ui::ET_GESTURE_SCROLL_BEGIN:
|
| - scroll_animator_->Stop();
|
| - break;
|
| - case ui::ET_GESTURE_SCROLL_UPDATE:
|
| - handled = OnScroll(0, event->details().scroll_y());
|
| - break;
|
| - case ui::ET_GESTURE_SCROLL_END:
|
| - break;
|
| - case ui::ET_SCROLL_FLING_START:
|
| - if (event->details().velocity_y() != 0.0f)
|
| - scroll_animator_->Start(0, event->details().velocity_y());
|
| - break;
|
| - case ui::ET_GESTURE_TAP_DOWN:
|
| - case ui::ET_SCROLL_FLING_CANCEL:
|
| - if (scroll_animator_->is_scrolling())
|
| - scroll_animator_->Stop();
|
| - else
|
| - handled = false;
|
| - break;
|
| - default:
|
| - handled = false;
|
| - break;
|
| - }
|
| - if (handled)
|
| - event->SetHandled();
|
| -}
|
| -
|
| -int SubmenuView::GetRowCount() {
|
| - return GetMenuItemCount();
|
| -}
|
| -
|
| -int SubmenuView::GetSelectedRow() {
|
| - int row = 0;
|
| - for (int i = 0; i < child_count(); ++i) {
|
| - if (child_at(i)->id() != MenuItemView::kMenuItemViewID)
|
| - continue;
|
| -
|
| - if (static_cast<MenuItemView*>(child_at(i))->IsSelected())
|
| - return row;
|
| -
|
| - row++;
|
| - }
|
| -
|
| - return -1;
|
| -}
|
| -
|
| -void SubmenuView::SetSelectedRow(int row) {
|
| - GetMenuItem()->GetMenuController()->SetSelection(
|
| - GetMenuItemAt(row),
|
| - MenuController::SELECTION_DEFAULT);
|
| -}
|
| -
|
| -base::string16 SubmenuView::GetTextForRow(int row) {
|
| - return GetMenuItemAt(row)->title();
|
| -}
|
| -
|
| -bool SubmenuView::IsShowing() {
|
| - return host_ && host_->IsMenuHostVisible();
|
| -}
|
| -
|
| -void SubmenuView::ShowAt(Widget* parent,
|
| - const gfx::Rect& bounds,
|
| - bool do_capture) {
|
| - if (host_) {
|
| - host_->ShowMenuHost(do_capture);
|
| - } else {
|
| - host_ = new MenuHost(this);
|
| - // Force construction of the scroll view container.
|
| - GetScrollViewContainer();
|
| - // Force a layout since our preferred size may not have changed but our
|
| - // content may have.
|
| - InvalidateLayout();
|
| - host_->InitMenuHost(parent, bounds, scroll_view_container_, do_capture);
|
| - }
|
| -
|
| - GetScrollViewContainer()->NotifyAccessibilityEvent(
|
| - ui::AX_EVENT_MENU_START,
|
| - true);
|
| - NotifyAccessibilityEvent(
|
| - ui::AX_EVENT_MENU_POPUP_START,
|
| - true);
|
| -}
|
| -
|
| -void SubmenuView::Reposition(const gfx::Rect& bounds) {
|
| - if (host_)
|
| - host_->SetMenuHostBounds(bounds);
|
| -}
|
| -
|
| -void SubmenuView::Close() {
|
| - if (host_) {
|
| - NotifyAccessibilityEvent(ui::AX_EVENT_MENU_POPUP_END, true);
|
| - GetScrollViewContainer()->NotifyAccessibilityEvent(
|
| - ui::AX_EVENT_MENU_END, true);
|
| -
|
| - host_->DestroyMenuHost();
|
| - host_ = NULL;
|
| - }
|
| -}
|
| -
|
| -void SubmenuView::Hide() {
|
| - if (host_)
|
| - host_->HideMenuHost();
|
| - if (scroll_animator_->is_scrolling())
|
| - scroll_animator_->Stop();
|
| -}
|
| -
|
| -void SubmenuView::ReleaseCapture() {
|
| - if (host_)
|
| - host_->ReleaseMenuHostCapture();
|
| -}
|
| -
|
| -bool SubmenuView::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) {
|
| - return views::FocusManager::IsTabTraversalKeyEvent(e);
|
| -}
|
| -
|
| -MenuItemView* SubmenuView::GetMenuItem() const {
|
| - return parent_menu_item_;
|
| -}
|
| -
|
| -void SubmenuView::SetDropMenuItem(MenuItemView* item,
|
| - MenuDelegate::DropPosition position) {
|
| - if (drop_item_ == item && drop_position_ == position)
|
| - return;
|
| - SchedulePaintForDropIndicator(drop_item_, drop_position_);
|
| - drop_item_ = item;
|
| - drop_position_ = position;
|
| - SchedulePaintForDropIndicator(drop_item_, drop_position_);
|
| -}
|
| -
|
| -bool SubmenuView::GetShowSelection(MenuItemView* item) {
|
| - if (drop_item_ == NULL)
|
| - return true;
|
| - // Something is being dropped on one of this menus items. Show the
|
| - // selection if the drop is on the passed in item and the drop position is
|
| - // ON.
|
| - return (drop_item_ == item && drop_position_ == MenuDelegate::DROP_ON);
|
| -}
|
| -
|
| -MenuScrollViewContainer* SubmenuView::GetScrollViewContainer() {
|
| - if (!scroll_view_container_) {
|
| - scroll_view_container_ = new MenuScrollViewContainer(this);
|
| - // Otherwise MenuHost would delete us.
|
| - scroll_view_container_->set_owned_by_client();
|
| - }
|
| - return scroll_view_container_;
|
| -}
|
| -
|
| -void SubmenuView::MenuHostDestroyed() {
|
| - host_ = NULL;
|
| - GetMenuItem()->GetMenuController()->Cancel(MenuController::EXIT_DESTROYED);
|
| -}
|
| -
|
| -const char* SubmenuView::GetClassName() const {
|
| - return kViewClassName;
|
| -}
|
| -
|
| -void SubmenuView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
|
| - SchedulePaint();
|
| -}
|
| -
|
| -void SubmenuView::PaintDropIndicator(gfx::Canvas* canvas,
|
| - MenuItemView* item,
|
| - MenuDelegate::DropPosition position) {
|
| - if (position == MenuDelegate::DROP_NONE)
|
| - return;
|
| -
|
| - gfx::Rect bounds = CalculateDropIndicatorBounds(item, position);
|
| - canvas->FillRect(bounds, kDropIndicatorColor);
|
| -}
|
| -
|
| -void SubmenuView::SchedulePaintForDropIndicator(
|
| - MenuItemView* item,
|
| - MenuDelegate::DropPosition position) {
|
| - if (item == NULL)
|
| - return;
|
| -
|
| - if (position == MenuDelegate::DROP_ON) {
|
| - item->SchedulePaint();
|
| - } else if (position != MenuDelegate::DROP_NONE) {
|
| - SchedulePaintInRect(CalculateDropIndicatorBounds(item, position));
|
| - }
|
| -}
|
| -
|
| -gfx::Rect SubmenuView::CalculateDropIndicatorBounds(
|
| - MenuItemView* item,
|
| - MenuDelegate::DropPosition position) {
|
| - DCHECK(position != MenuDelegate::DROP_NONE);
|
| - gfx::Rect item_bounds = item->bounds();
|
| - switch (position) {
|
| - case MenuDelegate::DROP_BEFORE:
|
| - item_bounds.Offset(0, -kDropIndicatorHeight / 2);
|
| - item_bounds.set_height(kDropIndicatorHeight);
|
| - return item_bounds;
|
| -
|
| - case MenuDelegate::DROP_AFTER:
|
| - item_bounds.Offset(0, item_bounds.height() - kDropIndicatorHeight / 2);
|
| - item_bounds.set_height(kDropIndicatorHeight);
|
| - return item_bounds;
|
| -
|
| - default:
|
| - // Don't render anything for on.
|
| - return gfx::Rect();
|
| - }
|
| -}
|
| -
|
| -bool SubmenuView::OnScroll(float dx, float dy) {
|
| - const gfx::Rect& vis_bounds = GetVisibleBounds();
|
| - const gfx::Rect& full_bounds = bounds();
|
| - int x = vis_bounds.x();
|
| - float y_f = vis_bounds.y() - dy - roundoff_error_;
|
| - int y = gfx::ToRoundedInt(y_f);
|
| - roundoff_error_ = y - y_f;
|
| - // clamp y to [0, full_height - vis_height)
|
| - y = std::min(y, full_bounds.height() - vis_bounds.height() - 1);
|
| - y = std::max(y, 0);
|
| - gfx::Rect new_vis_bounds(x, y, vis_bounds.width(), vis_bounds.height());
|
| - if (new_vis_bounds != vis_bounds) {
|
| - ScrollRectToVisible(new_vis_bounds);
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -} // namespace views
|
|
|