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