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/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.
    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().
    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.
    154   bool resize_open_menu() const { return 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