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