summaryrefslogtreecommitdiffstats
path: root/views/controls/menu/menu.h
blob: c0c36c7ac0e73d005fe954ad2b74909360b2181d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTROLS_MENU_VIEWS_MENU_H_
#define CONTROLS_MENU_VIEWS_MENU_H_

#include "base/basictypes.h"
#include "gfx/native_widget_types.h"
#include "views/controls/menu/controller.h"

class SkBitmap;
namespace gfx {
class Point;
}

namespace views {

class Accelerator;

class Menu {
 public:
  /////////////////////////////////////////////////////////////////////////////
  //
  // Delegate Interface
  //
  //  Classes implement this interface to tell the menu system more about each
  //  item as it is created.
  //
  /////////////////////////////////////////////////////////////////////////////
  class Delegate : public Controller {
   public:
    virtual ~Delegate() { }

    // Whether or not an item should be shown as checked.
    virtual bool IsItemChecked(int id) const {
      return false;
    }

    // Whether or not an item should be shown as the default (using bold).
    // There can only be one default menu item.
    virtual bool IsItemDefault(int id) const {
      return false;
    }

    // The string shown for the menu item.
    virtual std::wstring GetLabel(int id) const {
      return std::wstring();
    }

    // The delegate needs to implement this function if it wants to display
    // the shortcut text next to each menu item. If there is an accelerator
    // for a given item id, the implementor must return it.
    virtual bool GetAcceleratorInfo(int id, views::Accelerator* accel) {
      return false;
    }

    // The icon shown for the menu item.
    virtual const SkBitmap& GetIcon(int id) const {
      return GetEmptyIcon();
    }

    // The number of items to show in the menu
    virtual int GetItemCount() const {
      return 0;
    }

    // Whether or not an item is a separator.
    virtual bool IsItemSeparator(int id) const {
      return false;
    }

    // Shows the context menu with the specified id. This is invoked when the
    // user does the appropriate gesture to show a context menu. The id
    // identifies the id of the menu to show the context menu for.
    // is_mouse_gesture is true if this is the result of a mouse gesture.
    // If this is not the result of a mouse gesture |p| is the recommended
    // location to display the content menu at. In either case, |p| is in
    // screen coordinates.
    virtual void ShowContextMenu(Menu* source,
                                 int id,
                                 const gfx::Point& p,
                                 bool is_mouse_gesture) {
    }

    // Whether an item has an icon.
    virtual bool HasIcon(int id) const {
      return false;
    }

    // Notification that the menu is about to be popped up.
    virtual void MenuWillShow() {
    }

    // Whether to create a right-to-left menu. The default implementation
    // returns true if the locale's language is a right-to-left language (such
    // as Hebrew) and false otherwise. This is generally the right behavior
    // since there is no reason to show left-to-right menus for right-to-left
    // locales. However, subclasses can override this behavior so that the menu
    // is a right-to-left menu only if the view's layout is right-to-left
    // (since the view can use a different layout than the locale's language
    // layout).
    virtual bool IsRightToLeftUILayout() const;

    // Controller
    virtual bool SupportsCommand(int id) const {
      return true;
    }
    virtual bool IsCommandEnabled(int id) const {
      return true;
    }
    virtual bool GetContextualLabel(int id, std::wstring* out) const {
      return false;
    }
    virtual void ExecuteCommand(int id) {
    }

   protected:
    // Returns an empty icon.
    const SkBitmap& GetEmptyIcon() const;
  };

  // This class is a helper that simply wraps a controller and forwards all
  // state and execution actions to it.  Use this when you're not defining your
  // own custom delegate, but just hooking a context menu to some existing
  // controller elsewhere.
  class BaseControllerDelegate : public Delegate {
   public:
    explicit BaseControllerDelegate(Controller* wrapped)
      : controller_(wrapped) {
    }

    // Overridden from Menu::Delegate
    virtual bool SupportsCommand(int id) const {
      return controller_->SupportsCommand(id);
    }
    virtual bool IsCommandEnabled(int id) const {
      return controller_->IsCommandEnabled(id);
    }
    virtual void ExecuteCommand(int id) {
      controller_->ExecuteCommand(id);
    }
    virtual bool GetContextualLabel(int id, std::wstring* out) const {
      return controller_->GetContextualLabel(id, out);
    }

   private:
    // The internal controller that we wrap to forward state and execution
    // actions to.
    Controller* controller_;

    DISALLOW_COPY_AND_ASSIGN(BaseControllerDelegate);
  };

  // How this popup should align itself relative to the point it is run at.
  enum AnchorPoint {
    TOPLEFT,
    TOPRIGHT
  };

  // Different types of menu items
  enum MenuItemType {
    NORMAL,
    CHECKBOX,
    RADIO,
    SEPARATOR
  };

  // Construct a Menu using the specified controller to determine command
  // state.
  // delegate     A Menu::Delegate implementation that provides more
  //              information about the Menu presentation.
  // anchor       An alignment hint for the popup menu.
  // owner        The window that the menu is being brought up relative
  //              to. Not actually used for anything but must not be
  //              NULL.
  Menu(Delegate* delegate, AnchorPoint anchor);
  Menu();
  virtual ~Menu();

  static Menu* Create(Delegate* delegate,
                      AnchorPoint anchor,
                      gfx::NativeView parent);

  // Creates a new menu with the contents of the system menu for the given
  // parent window. The caller owns the returned pointer.
  static Menu* GetSystemMenu(gfx::NativeWindow parent);

  void set_delegate(Delegate* delegate) { delegate_ = delegate; }
  Delegate* delegate() const { return delegate_; }

  AnchorPoint anchor() const { return anchor_; }

  // Adds an item to this menu.
  // item_id    The id of the item, used to identify it in delegate callbacks
  //            or (if delegate is NULL) to identify the command associated
  //            with this item with the controller specified in the ctor. Note
  //            that this value should not be 0 as this has a special meaning
  //            ("NULL command, no item selected")
  // label      The text label shown.
  // type       The type of item.
  void AppendMenuItem(int item_id,
                      const std::wstring& label,
                      MenuItemType type);
  void AddMenuItem(int index,
                   int item_id,
                   const std::wstring& label,
                   MenuItemType type);

  // Append a submenu to this menu.
  // The returned pointer is owned by this menu.
  Menu* AppendSubMenu(int item_id,
                      const std::wstring& label);
  Menu* AddSubMenu(int index, int item_id, const std::wstring& label);

  // Append a submenu with an icon to this menu
  // The returned pointer is owned by this menu.
  // Unless the icon is empty, calling this function forces the Menu class
  // to draw the menu, instead of relying on Windows.
  Menu* AppendSubMenuWithIcon(int item_id,
                              const std::wstring& label,
                              const SkBitmap& icon);
  virtual Menu* AddSubMenuWithIcon(int index,
                                   int item_id,
                                   const std::wstring& label,
                                   const SkBitmap& icon) = 0;

  // This is a convenience for standard text label menu items where the label
  // is provided with this call.
  void AppendMenuItemWithLabel(int item_id, const std::wstring& label);
  void AddMenuItemWithLabel(int index, int item_id, const std::wstring& label);

  // This is a convenience for text label menu items where the label is
  // provided by the delegate.
  void AppendDelegateMenuItem(int item_id);
  void AddDelegateMenuItem(int index, int item_id);

  // Adds a separator to this menu
  void AppendSeparator();
  virtual void AddSeparator(int index) = 0;

  // Appends a menu item with an icon. This is for the menu item which
  // needs an icon. Calling this function forces the Menu class to draw
  // the menu, instead of relying on Windows.
  void AppendMenuItemWithIcon(int item_id,
                              const std::wstring& label,
                              const SkBitmap& icon);
  virtual void AddMenuItemWithIcon(int index,
                                   int item_id,
                                   const std::wstring& label,
                                   const SkBitmap& icon);

  // Enables or disables the item with the specified id.
  virtual void EnableMenuItemByID(int item_id, bool enabled) = 0;
  virtual void EnableMenuItemAt(int index, bool enabled) = 0;

  // Sets menu label at specified index.
  virtual void SetMenuLabel(int item_id, const std::wstring& label) = 0;

  // Sets an icon for an item with a given item_id. Calling this function
  // also forces the Menu class to draw the menu, instead of relying on Windows.
  // Returns false if the item with |item_id| is not found.
  virtual bool SetIcon(const SkBitmap& icon, int item_id) = 0;

  // Shows the menu, blocks until the user dismisses the menu or selects an
  // item, and executes the command for the selected item (if any).
  // Warning: Blocking call. Will implicitly run a message loop.
  virtual void RunMenuAt(int x, int y) = 0;

  // Cancels the menu.
  virtual void Cancel() = 0;

  // Returns the number of menu items.
  virtual int ItemCount() = 0;

#if defined(OS_WIN)
  // Returns the underlying menu handle
  virtual HMENU GetMenuHandle() const = 0;
#endif  // defined(OS_WIN)

 protected:
  explicit Menu(Menu* parent);

  virtual void AddMenuItemInternal(int index,
                                   int item_id,
                                   const std::wstring& label,
                                   const SkBitmap& icon,
                                   MenuItemType type) = 0;

 private:
  // The delegate that is being used to get information about the presentation.
  Delegate* delegate_;

  // How this popup menu should be aligned relative to the point it is run at.
  AnchorPoint anchor_;

  DISALLOW_COPY_AND_ASSIGN(Menu);
};

}  // namespace views

#endif  // CONTROLS_MENU_VIEWS_MENU_H_