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