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 15 namespace views { 16 17 class MenuHost; 18 class MenuItemView; 19 class 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. 36 class 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, 88 const gfx::Rect& bounds, 89 bool do_capture); 90 91 // Resets the bounds of the submenu to |bounds|. 92 void Reposition(const gfx::Rect& bounds); 93 94 // Closes the menu, destroying the host. 95 void Close(); 96 97 // Hides the hosting window. 98 // 99 // The hosting window is hidden first, then deleted (Close) when the menu is 100 // done running. This is done to avoid deletion ordering dependencies. In 101 // particular, during drag and drop (and when a modal dialog is shown as 102 // a result of choosing a context menu) it is possible that an event is 103 // being processed by the host, so that host is on the stack when we need to 104 // close the window. If we closed the window immediately (and deleted it), 105 // when control returned back to host we would crash as host was deleted. 106 void Hide(); 107 108 // If mouse capture was grabbed, it is released. Does nothing if mouse was 109 // not captured. 110 void ReleaseCapture(); 111 112 // Overriden from View to prevent tab from doing anything. 113 virtual bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) OVERRIDE; 114 115 // Returns the parent menu item we're showing children for. 116 MenuItemView* GetMenuItem() const; 117 118 // Set the drop item and position. 119 void SetDropMenuItem(MenuItemView* item, 120 MenuDelegate::DropPosition position); 121 122 // Returns whether the selection should be shown for the specified item. 123 // The selection is NOT shown during drag and drop when the drop is over 124 // the menu. 125 bool GetShowSelection(MenuItemView* item); 126 127 // Returns the container for the SubmenuView. 128 MenuScrollViewContainer* GetScrollViewContainer(); 129 130 // Invoked if the menu is prematurely destroyed. This can happen if the window 131 // closes while the menu is shown. If invoked the SubmenuView must drop all 132 // references to the MenuHost as the MenuHost is about to be deleted. 133 void MenuHostDestroyed(); 134 135 // Max width of minor text (accelerator or subtitle) in child menu items. This 136 // doesn't include children's children, only direct children. 137 int max_minor_text_width() const { return max_minor_text_width_; } 138 139 // Minimum width of menu in pixels (default 0). This becomes the smallest 140 // width returned by GetPreferredSize(). 141 void set_minimum_preferred_width(int minimum_preferred_width) { 142 minimum_preferred_width_ = minimum_preferred_width; 143 } 144 145 // Automatically resize menu if a subview's preferred size changes. 146 bool resize_open_menu() const { return resize_open_menu_; } 147 void set_resize_open_menu(bool resize_open_menu) { 148 resize_open_menu_ = resize_open_menu; 149 } 150 151 protected: 152 // Overridden from View: 153 virtual const char* GetClassName() const OVERRIDE; 154 155 // View method. Overridden to schedule a paint. We do this so that when 156 // scrolling occurs, everything is repainted correctly. 157 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE; 158 159 virtual void ChildPreferredSizeChanged(View* child) OVERRIDE; 160 161 private: 162 // Paints the drop indicator. This is only invoked if item is non-NULL and 163 // position is not DROP_NONE. 164 void PaintDropIndicator(gfx::Canvas* canvas, 165 MenuItemView* item, 166 MenuDelegate::DropPosition position); 167 168 void SchedulePaintForDropIndicator(MenuItemView* item, 169 MenuDelegate::DropPosition position); 170 171 // Calculates the location of th edrop indicator. 172 gfx::Rect CalculateDropIndicatorBounds(MenuItemView* item, 173 MenuDelegate::DropPosition position); 174 175 // Implementation of ScrollDelegate 176 virtual bool OnScroll(float dx, float dy) OVERRIDE; 177 178 // Parent menu item. 179 MenuItemView* parent_menu_item_; 180 181 // Widget subclass used to show the children. This is deleted when we invoke 182 // |DestroyMenuHost|, or |MenuHostDestroyed| is invoked back on us. 183 MenuHost* host_; 184 185 // If non-null, indicates a drop is in progress and drop_item is the item 186 // the drop is over. 187 MenuItemView* drop_item_; 188 189 // Position of the drop. 190 MenuDelegate::DropPosition drop_position_; 191 192 // Ancestor of the SubmenuView, lazily created. 193 MenuScrollViewContainer* scroll_view_container_; 194 195 // See description above getter. 196 int max_minor_text_width_; 197 198 // Minimum width returned in GetPreferredSize(). 199 int minimum_preferred_width_; 200 201 // Reposition open menu when contained views change size. 202 bool resize_open_menu_; 203 204 // The submenu's scroll animator 205 scoped_ptr<ScrollAnimator> scroll_animator_; 206 207 DISALLOW_COPY_AND_ASSIGN(SubmenuView); 208 }; 209 210 } // namespace views 211 212 #endif // UI_VIEWS_CONTROLS_MENU_SUBMENU_VIEW_H_ 213