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_H_
6#define UI_VIEWS_CONTROLS_MENU_MENU_H_
7
8#include <string>
9
10#include "base/basictypes.h"
11#include "base/strings/string16.h"
12#include "ui/gfx/native_widget_types.h"
13#include "ui/views/views_export.h"
14
15namespace gfx {
16class ImageSkia;
17class Point;
18}
19
20namespace ui {
21class Accelerator;
22}
23
24namespace views {
25
26class VIEWS_EXPORT Menu {
27 public:
28  /////////////////////////////////////////////////////////////////////////////
29  //
30  // Delegate Interface
31  //
32  //  Classes implement this interface to tell the menu system more about each
33  //  item as it is created.
34  //
35  /////////////////////////////////////////////////////////////////////////////
36  class VIEWS_EXPORT Delegate {
37   public:
38    virtual ~Delegate() {}
39
40    // Whether or not an item should be shown as checked.
41    virtual bool IsItemChecked(int id) const;
42
43    // Whether or not an item should be shown as the default (using bold).
44    // There can only be one default menu item.
45    virtual bool IsItemDefault(int id) const;
46
47    // The string shown for the menu item.
48    virtual base::string16 GetLabel(int id) const;
49
50    // The delegate needs to implement this function if it wants to display
51    // the shortcut text next to each menu item. If there is an accelerator
52    // for a given item id, the implementor must return it.
53    virtual bool GetAcceleratorInfo(int id, ui::Accelerator* accel);
54
55    // The icon shown for the menu item.
56    virtual const gfx::ImageSkia& GetIcon(int id) const;
57
58    // The number of items to show in the menu
59    virtual int GetItemCount() const;
60
61    // Whether or not an item is a separator.
62    virtual bool IsItemSeparator(int id) const;
63
64    // Shows the context menu with the specified id. This is invoked when the
65    // user does the appropriate gesture to show a context menu. The id
66    // identifies the id of the menu to show the context menu for.
67    // is_mouse_gesture is true if this is the result of a mouse gesture.
68    // If this is not the result of a mouse gesture |p| is the recommended
69    // location to display the content menu at. In either case, |p| is in
70    // screen coordinates.
71    virtual void ShowContextMenu(Menu* source,
72                                 int id,
73                                 const gfx::Point& p,
74                                 bool is_mouse_gesture) {
75    }
76
77    // Whether an item has an icon.
78    virtual bool HasIcon(int id) const;
79
80    // Notification that the menu is about to be popped up.
81    virtual void MenuWillShow() {
82    }
83
84    // Whether to create a right-to-left menu. The default implementation
85    // returns true if the locale's language is a right-to-left language (such
86    // as Hebrew) and false otherwise. This is generally the right behavior
87    // since there is no reason to show left-to-right menus for right-to-left
88    // locales. However, subclasses can override this behavior so that the menu
89    // is a right-to-left menu only if the view's layout is right-to-left
90    // (since the view can use a different layout than the locale's language
91    // layout).
92    virtual bool IsRightToLeftUILayout() const;
93
94    // Controller
95    virtual bool SupportsCommand(int id) const;
96    virtual bool IsCommandEnabled(int id) const;
97    virtual bool GetContextualLabel(int id, base::string16* out) const;
98    virtual void ExecuteCommand(int id) {
99    }
100
101   protected:
102    // Returns an empty icon.
103    const gfx::ImageSkia& GetEmptyIcon() const;
104  };
105
106  // How this popup should align itself relative to the point it is run at.
107  enum AnchorPoint {
108    TOPLEFT,
109    TOPRIGHT
110  };
111
112  // Different types of menu items
113  enum MenuItemType {
114    NORMAL,
115    CHECKBOX,
116    RADIO,
117    SEPARATOR
118  };
119
120  // Construct a Menu using the specified controller to determine command
121  // state.
122  // delegate     A Menu::Delegate implementation that provides more
123  //              information about the Menu presentation.
124  // anchor       An alignment hint for the popup menu.
125  // owner        The window that the menu is being brought up relative
126  //              to. Not actually used for anything but must not be
127  //              NULL.
128  Menu(Delegate* delegate, AnchorPoint anchor);
129  Menu();
130  virtual ~Menu();
131
132  static Menu* Create(Delegate* delegate,
133                      AnchorPoint anchor,
134                      gfx::NativeView parent);
135
136  // Creates a new menu with the contents of the system menu for the given
137  // parent window. The caller owns the returned pointer.
138  static Menu* GetSystemMenu(gfx::NativeWindow parent);
139
140  void set_delegate(Delegate* delegate) { delegate_ = delegate; }
141  Delegate* delegate() const { return delegate_; }
142
143  AnchorPoint anchor() const { return anchor_; }
144
145  // Adds an item to this menu.
146  // item_id    The id of the item, used to identify it in delegate callbacks
147  //            or (if delegate is NULL) to identify the command associated
148  //            with this item with the controller specified in the ctor. Note
149  //            that this value should not be 0 as this has a special meaning
150  //            ("NULL command, no item selected")
151  // label      The text label shown.
152  // type       The type of item.
153  void AppendMenuItem(int item_id,
154                      const base::string16& label,
155                      MenuItemType type);
156  void AddMenuItem(int index,
157                   int item_id,
158                   const base::string16& label,
159                   MenuItemType type);
160
161  // Append a submenu to this menu.
162  // The returned pointer is owned by this menu.
163  Menu* AppendSubMenu(int item_id,
164                      const base::string16& label);
165  Menu* AddSubMenu(int index, int item_id, const base::string16& label);
166
167  // Append a submenu with an icon to this menu
168  // The returned pointer is owned by this menu.
169  // Unless the icon is empty, calling this function forces the Menu class
170  // to draw the menu, instead of relying on Windows.
171  Menu* AppendSubMenuWithIcon(int item_id,
172                              const base::string16& label,
173                              const gfx::ImageSkia& icon);
174  virtual Menu* AddSubMenuWithIcon(int index,
175                                   int item_id,
176                                   const base::string16& label,
177                                   const gfx::ImageSkia& icon) = 0;
178
179  // This is a convenience for standard text label menu items where the label
180  // is provided with this call.
181  void AppendMenuItemWithLabel(int item_id, const base::string16& label);
182  void AddMenuItemWithLabel(int index,
183                            int item_id,
184                            const base::string16& label);
185
186  // This is a convenience for text label menu items where the label is
187  // provided by the delegate.
188  void AppendDelegateMenuItem(int item_id);
189  void AddDelegateMenuItem(int index, int item_id);
190
191  // Adds a separator to this menu
192  void AppendSeparator();
193  virtual void AddSeparator(int index) = 0;
194
195  // Appends a menu item with an icon. This is for the menu item which
196  // needs an icon. Calling this function forces the Menu class to draw
197  // the menu, instead of relying on Windows.
198  void AppendMenuItemWithIcon(int item_id,
199                              const base::string16& label,
200                              const gfx::ImageSkia& icon);
201  virtual void AddMenuItemWithIcon(int index,
202                                   int item_id,
203                                   const base::string16& label,
204                                   const gfx::ImageSkia& icon);
205
206  // Enables or disables the item with the specified id.
207  virtual void EnableMenuItemByID(int item_id, bool enabled) = 0;
208  virtual void EnableMenuItemAt(int index, bool enabled) = 0;
209
210  // Sets menu label at specified index.
211  virtual void SetMenuLabel(int item_id, const base::string16& label) = 0;
212
213  // Sets an icon for an item with a given item_id. Calling this function
214  // also forces the Menu class to draw the menu, instead of relying on Windows.
215  // Returns false if the item with |item_id| is not found.
216  virtual bool SetIcon(const gfx::ImageSkia& icon, int item_id) = 0;
217
218  // Shows the menu, blocks until the user dismisses the menu or selects an
219  // item, and executes the command for the selected item (if any).
220  // Warning: Blocking call. Will implicitly run a message loop.
221  virtual void RunMenuAt(int x, int y) = 0;
222
223  // Cancels the menu.
224  virtual void Cancel() = 0;
225
226  // Returns the number of menu items.
227  virtual int ItemCount() = 0;
228
229#if defined(OS_WIN)
230  // Returns the underlying menu handle
231  virtual HMENU GetMenuHandle() const = 0;
232#endif  // defined(OS_WIN)
233
234 protected:
235  explicit Menu(Menu* parent);
236
237  virtual void AddMenuItemInternal(int index,
238                                   int item_id,
239                                   const base::string16& label,
240                                   const gfx::ImageSkia& icon,
241                                   MenuItemType type) = 0;
242
243 private:
244  // The delegate that is being used to get information about the presentation.
245  Delegate* delegate_;
246
247  // How this popup menu should be aligned relative to the point it is run at.
248  AnchorPoint anchor_;
249
250  DISALLOW_COPY_AND_ASSIGN(Menu);
251};
252
253}  // namespace views
254
255#endif  // UI_VIEWS_CONTROLS_MENU_MENU_H_
256