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, 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 DISALLOW_COPY_AND_ASSIGN(SubmenuView); 206 }; 207 208 } // namespace views 209 210 #endif // UI_VIEWS_CONTROLS_MENU_SUBMENU_VIEW_H_ 211