Home | History | Annotate | Download | only in menu
      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