1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
|
// 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.
#ifndef UI_VIEWS_CONTROLS_MENU_SUBMENU_VIEW_H_
#define UI_VIEWS_CONTROLS_MENU_SUBMENU_VIEW_H_
#include <string>
#include "base/compiler_specific.h"
#include "ui/views/animation/scroll_animator.h"
#include "ui/views/controls/menu/menu_delegate.h"
#include "ui/views/controls/prefix_delegate.h"
#include "ui/views/controls/prefix_selector.h"
#include "ui/views/view.h"
namespace views {
class MenuHost;
class MenuItemView;
class MenuScrollViewContainer;
// SubmenuView is the parent of all menu items.
//
// SubmenuView has the following responsibilities:
// . It positions and sizes all child views (any type of View may be added,
// not just MenuItemViews).
// . Forwards the appropriate events to the MenuController. This allows the
// MenuController to update the selection as the user moves the mouse around.
// . Renders the drop indicator during a drop operation.
// . Shows and hides the window (a NativeWidget) when the menu is shown on
// screen.
//
// SubmenuView is itself contained in a MenuScrollViewContainer.
// MenuScrollViewContainer handles showing as much of the SubmenuView as the
// screen allows. If the SubmenuView is taller than the screen, scroll buttons
// are provided that allow the user to see all the menu items.
class VIEWS_EXPORT SubmenuView : public PrefixDelegate,
public ScrollDelegate {
public:
// The submenu's class name.
static const char kViewClassName[];
// Creates a SubmenuView for the specified menu item.
explicit SubmenuView(MenuItemView* parent);
~SubmenuView() override;
// Returns the number of child views that are MenuItemViews.
// MenuItemViews are identified by ID.
int GetMenuItemCount();
// Returns the MenuItemView at the specified index.
MenuItemView* GetMenuItemAt(int index);
// Positions and sizes the child views. This tiles the views vertically,
// giving each child the available width.
void Layout() override;
gfx::Size GetPreferredSize() const override;
// Override from View.
void GetAccessibleState(ui::AXViewState* state) override;
ui::TextInputClient* GetTextInputClient() override;
// Painting.
void PaintChildren(gfx::Canvas* canvas,
const views::CullSet& cull_view) override;
// Drag and drop methods. These are forwarded to the MenuController.
bool GetDropFormats(
int* formats,
std::set<OSExchangeData::CustomFormat>* custom_formats) override;
bool AreDropTypesRequired() override;
bool CanDrop(const OSExchangeData& data) override;
void OnDragEntered(const ui::DropTargetEvent& event) override;
int OnDragUpdated(const ui::DropTargetEvent& event) override;
void OnDragExited() override;
int OnPerformDrop(const ui::DropTargetEvent& event) override;
// Scrolls on menu item boundaries.
bool OnMouseWheel(const ui::MouseWheelEvent& e) override;
// Overridden from ui::EventHandler.
// Scrolls on menu item boundaries.
void OnGestureEvent(ui::GestureEvent* event) override;
// Overridden from PrefixDelegate.
int GetRowCount() override;
int GetSelectedRow() override;
void SetSelectedRow(int row) override;
base::string16 GetTextForRow(int row) override;
// Returns true if the menu is showing.
bool IsShowing();
// Shows the menu at the specified location. Coordinates are in screen
// coordinates. max_width gives the max width the view should be.
void ShowAt(Widget* parent, const gfx::Rect& bounds, bool do_capture);
// Resets the bounds of the submenu to |bounds|.
void Reposition(const gfx::Rect& bounds);
// Closes the menu, destroying the host.
void Close();
// Hides the hosting window.
//
// The hosting window is hidden first, then deleted (Close) when the menu is
// done running. This is done to avoid deletion ordering dependencies. In
// particular, during drag and drop (and when a modal dialog is shown as
// a result of choosing a context menu) it is possible that an event is
// being processed by the host, so that host is on the stack when we need to
// close the window. If we closed the window immediately (and deleted it),
// when control returned back to host we would crash as host was deleted.
void Hide();
// If mouse capture was grabbed, it is released. Does nothing if mouse was
// not captured.
void ReleaseCapture();
// Overriden from View to prevent tab from doing anything.
bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) override;
// Returns the parent menu item we're showing children for.
MenuItemView* GetMenuItem() const;
// Set the drop item and position.
void SetDropMenuItem(MenuItemView* item,
MenuDelegate::DropPosition position);
// Returns whether the selection should be shown for the specified item.
// The selection is NOT shown during drag and drop when the drop is over
// the menu.
bool GetShowSelection(MenuItemView* item);
// Returns the container for the SubmenuView.
MenuScrollViewContainer* GetScrollViewContainer();
// Invoked if the menu is prematurely destroyed. This can happen if the window
// closes while the menu is shown. If invoked the SubmenuView must drop all
// references to the MenuHost as the MenuHost is about to be deleted.
void MenuHostDestroyed();
// Max width of minor text (accelerator or subtitle) in child menu items. This
// doesn't include children's children, only direct children.
int max_minor_text_width() const { return max_minor_text_width_; }
// Minimum width of menu in pixels (default 0). This becomes the smallest
// width returned by GetPreferredSize().
void set_minimum_preferred_width(int minimum_preferred_width) {
minimum_preferred_width_ = minimum_preferred_width;
}
// Automatically resize menu if a subview's preferred size changes.
bool resize_open_menu() const { return resize_open_menu_; }
void set_resize_open_menu(bool resize_open_menu) {
resize_open_menu_ = resize_open_menu;
}
protected:
// Overridden from View:
const char* GetClassName() const override;
// View method. Overridden to schedule a paint. We do this so that when
// scrolling occurs, everything is repainted correctly.
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
void ChildPreferredSizeChanged(View* child) override;
private:
// Paints the drop indicator. This is only invoked if item is non-NULL and
// position is not DROP_NONE.
void PaintDropIndicator(gfx::Canvas* canvas,
MenuItemView* item,
MenuDelegate::DropPosition position);
void SchedulePaintForDropIndicator(MenuItemView* item,
MenuDelegate::DropPosition position);
// Calculates the location of th edrop indicator.
gfx::Rect CalculateDropIndicatorBounds(MenuItemView* item,
MenuDelegate::DropPosition position);
// Implementation of ScrollDelegate
bool OnScroll(float dx, float dy) override;
// Parent menu item.
MenuItemView* parent_menu_item_;
// Widget subclass used to show the children. This is deleted when we invoke
// |DestroyMenuHost|, or |MenuHostDestroyed| is invoked back on us.
MenuHost* host_;
// If non-null, indicates a drop is in progress and drop_item is the item
// the drop is over.
MenuItemView* drop_item_;
// Position of the drop.
MenuDelegate::DropPosition drop_position_;
// Ancestor of the SubmenuView, lazily created.
MenuScrollViewContainer* scroll_view_container_;
// See description above getter.
mutable int max_minor_text_width_;
// Minimum width returned in GetPreferredSize().
int minimum_preferred_width_;
// Reposition open menu when contained views change size.
bool resize_open_menu_;
// The submenu's scroll animator
scoped_ptr<ScrollAnimator> scroll_animator_;
// Difference between current position and cumulative deltas passed to
// OnScroll.
// TODO(tdresser): This should be removed when raw pixel scrolling for views
// is enabled. See crbug.com/329354.
float roundoff_error_;
PrefixSelector prefix_selector_;
DISALLOW_COPY_AND_ASSIGN(SubmenuView);
};
} // namespace views
#endif // UI_VIEWS_CONTROLS_MENU_SUBMENU_VIEW_H_
|