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