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
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
|
// Copyright (c) 2006-2008 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 CHROME_VIEWS_MENU_H_
#define CHROME_VIEWS_MENU_H_
#include <windows.h>
#include <vector>
#include "base/basictypes.h"
#include "chrome/views/controller.h"
class SkBitmap;
namespace {
class MenuHostWindow;
}
namespace views {
class Accelerator;
}
///////////////////////////////////////////////////////////////////////////////
//
// Menu class
//
// A wrapper around a Win32 HMENU handle that provides convenient APIs for
// menu construction, display and subsequent command execution.
//
///////////////////////////////////////////////////////////////////////////////
class Menu {
friend class MenuHostWindow;
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 x/y is the recommended
// location to display the content menu at. In either case, x/y is in
// screen coordinates.
virtual void ShowContextMenu(Menu* source,
int id,
int x,
int y,
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. Will initialize kEmptyIcon if it hasn't been
// initialized.
const SkBitmap& GetEmptyIcon() const;
private:
// Will be initialized to an icon of 0 width and 0 height when first using.
// An empty icon means we don't need to draw it.
static const SkBitmap* kEmptyIcon;
};
// 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, HWND owner);
// Alternatively, a Menu object can be constructed wrapping an existing
// HMENU. This can be used to use the convenience methods to insert
// menu items and manage label string ownership. However this kind of
// Menu object cannot use the delegate.
explicit Menu(HMENU hmenu);
virtual ~Menu();
void set_delegate(Delegate* delegate) { delegate_ = delegate; }
// 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);
Menu* AddSubMenuWithIcon(int index,
int item_id,
const std::wstring& label,
const SkBitmap& icon);
// 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();
void AddSeparator(int index);
// 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);
void AddMenuItemWithIcon(int index,
int item_id,
const std::wstring& label,
const SkBitmap& icon);
// Enables or disables the item with the specified id.
void EnableMenuItemByID(int item_id, bool enabled);
void EnableMenuItemAt(int index, bool enabled);
// 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.
bool SetIcon(const SkBitmap& icon, int item_id);
// 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.
void RunMenuAt(int x, int y);
// Cancels the menu.
virtual void Cancel();
// Returns the number of menu items.
int ItemCount();
protected:
// The delegate that is being used to get information about the presentation.
Delegate* delegate_;
private:
// The data of menu items needed to display.
struct ItemData;
explicit Menu(Menu* parent);
void AddMenuItemInternal(int index,
int item_id,
const std::wstring& label,
const SkBitmap& icon,
HMENU submenu,
MenuItemType type);
// Sets menu information before displaying, including sub-menus.
void SetMenuInfo();
// Get all the state flags for the |fState| field of MENUITEMINFO for the
// item with the specified id. |delegate| is consulted if non-NULL about
// the state of the item in preference to |controller_|.
UINT GetStateFlagsForItemID(int item_id) const;
// Gets the Win32 TPM alignment flags for the specified AnchorPoint.
DWORD GetTPMAlignFlags() const;
// The Win32 Menu Handle we wrap
HMENU menu_;
// The window that would receive WM_COMMAND messages when the user selects
// an item from the menu.
HWND owner_;
// This list is used to store the default labels for the menu items.
// We may use contextual labels when RunMenu is called, so we must save
// a copy of default ones here.
std::vector<std::wstring> labels_;
// A flag to indicate whether this menu will be drawn by the Menu class.
// If it's true, all the menu items will be owner drawn. Otherwise,
// all the drawing will be done by Windows.
bool owner_draw_;
// How this popup menu should be aligned relative to the point it is run at.
AnchorPoint anchor_;
// This list is to store the string labels and icons to display. It's used
// when owner_draw_ is true. We give MENUITEMINFO pointers to these
// structures to specify what we'd like to draw. If owner_draw_ is false,
// we only give MENUITEMINFO pointers to the labels_.
// The label member of the ItemData structure comes from either labels_ or
// the GetContextualLabel.
std::vector<ItemData*> item_data_;
// Our sub-menus, if any.
std::vector<Menu*> submenus_;
// Whether the menu is visible.
bool is_menu_visible_;
DISALLOW_COPY_AND_ASSIGN(Menu);
};
#endif // CHROME_VIEWS_MENU_H_
|