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_MENU_RUNNER_H_
      6 #define UI_VIEWS_CONTROLS_MENU_MENU_RUNNER_H_
      7 
      8 #include "base/basictypes.h"
      9 #include "base/compiler_specific.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "ui/views/controls/menu/menu_item_view.h"
     12 
     13 namespace ui {
     14 class MenuModel;
     15 }
     16 
     17 namespace views {
     18 
     19 class MenuButton;
     20 class MenuModelAdapter;
     21 class Widget;
     22 
     23 namespace internal {
     24 class DisplayChangeListener;
     25 class MenuRunnerImpl;
     26 }
     27 
     28 // MenuRunner is responsible for showing (running) the menu and additionally
     29 // owning the MenuItemView. RunMenuAt() runs a nested message loop. It is safe
     30 // to delete MenuRunner at any point, but MenuRunner internally only deletes the
     31 // MenuItemView *after* the nested message loop completes. If MenuRunner is
     32 // deleted while the menu is showing the delegate of the menu is reset. This is
     33 // done to ensure delegates aren't notified after they may have been deleted.
     34 //
     35 // NOTE: while you can delete a MenuRunner at any point, the nested message loop
     36 // won't return immediately. This means if you delete the object that owns
     37 // the MenuRunner while the menu is running, your object is effectively still
     38 // on the stack. A return value of MENU_DELETED indicated this. In most cases
     39 // if RunMenuAt() returns MENU_DELETED, you should return immediately.
     40 //
     41 // Similarly you should avoid creating MenuRunner on the stack. Doing so means
     42 // MenuRunner may not be immediately destroyed if your object is destroyed,
     43 // resulting in possible callbacks to your now deleted object. Instead you
     44 // should define MenuRunner as a scoped_ptr in your class so that when your
     45 // object is destroyed MenuRunner initiates the proper cleanup and ensures your
     46 // object isn't accessed again.
     47 class VIEWS_EXPORT MenuRunner {
     48  public:
     49   enum RunTypes {
     50     // The menu has mnemonics.
     51     HAS_MNEMONICS = 1 << 0,
     52 
     53     // The menu is a nested context menu. For example, click a folder on the
     54     // bookmark bar, then right click an entry to get its context menu.
     55     IS_NESTED     = 1 << 1,
     56 
     57     // Used for showing a menu during a drop operation. This does NOT block the
     58     // caller, instead the delegate is notified when the menu closes via the
     59     // DropMenuClosed method.
     60     FOR_DROP      = 1 << 2,
     61 
     62     // The menu is a context menu (not necessarily nested), for example right
     63     // click on a link on a website in the browser.
     64     CONTEXT_MENU  = 1 << 3,
     65   };
     66 
     67   enum RunResult {
     68     // Indicates RunMenuAt is returning because the MenuRunner was deleted.
     69     MENU_DELETED,
     70 
     71     // Indicates RunMenuAt returned and MenuRunner was not deleted.
     72     NORMAL_EXIT
     73   };
     74 
     75   // Creates a new MenuRunner.
     76   explicit MenuRunner(ui::MenuModel* menu_model);
     77   explicit MenuRunner(MenuItemView* menu);
     78   ~MenuRunner();
     79 
     80   // Returns the menu.
     81   MenuItemView* GetMenu();
     82 
     83   // Takes ownership of |menu|, deleting it when MenuRunner is deleted. You
     84   // only need call this if you create additional menus from
     85   // MenuDelegate::GetSiblingMenu.
     86   void OwnMenu(MenuItemView* menu);
     87 
     88   // Runs the menu. |types| is a bitmask of RunTypes. If this returns
     89   // MENU_DELETED the method is returning because the MenuRunner was deleted.
     90   // Typically callers should NOT do any processing if this returns
     91   // MENU_DELETED.
     92   // If |anchor| uses a |BUBBLE_..| type, the bounds will get determined by
     93   // using |bounds| as the thing to point at in screen coordinates.
     94   RunResult RunMenuAt(Widget* parent,
     95                       MenuButton* button,
     96                       const gfx::Rect& bounds,
     97                       MenuItemView::AnchorPosition anchor,
     98                       ui::MenuSourceType source_type,
     99                       int32 types) WARN_UNUSED_RESULT;
    100 
    101   // Returns true if we're in a nested message loop running the menu.
    102   bool IsRunning() const;
    103 
    104   // Hides and cancels the menu. This does nothing if the menu is not open.
    105   void Cancel();
    106 
    107   // Returns the time from the event which closed the menu - or 0.
    108   base::TimeDelta closing_event_time() const;
    109 
    110  private:
    111   scoped_ptr<MenuModelAdapter> menu_model_adapter_;
    112 
    113   internal::MenuRunnerImpl* holder_;
    114 
    115   scoped_ptr<internal::DisplayChangeListener> display_change_listener_;
    116 
    117   DISALLOW_COPY_AND_ASSIGN(MenuRunner);
    118 };
    119 
    120 namespace internal {
    121 
    122 // DisplayChangeListener is intended to listen for changes in the display size
    123 // and cancel the menu. DisplayChangeListener is created when the menu is
    124 // shown.
    125 class DisplayChangeListener {
    126  public:
    127   virtual ~DisplayChangeListener() {}
    128 
    129   // Creates the platform specified DisplayChangeListener, or NULL if there
    130   // isn't one. Caller owns the returned value.
    131   static DisplayChangeListener* Create(Widget* parent,
    132                                        MenuRunner* runner);
    133 
    134  protected:
    135   DisplayChangeListener() {}
    136 };
    137 
    138 }
    139 
    140 }  // namespace views
    141 
    142 #endif  // UI_VIEWS_CONTROLS_MENU_MENU_RUNNER_H_
    143