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,
     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