Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(215)

Side by Side Diff: ui/views/controls/menu/menu_item_view.h

Issue 851853002: It is time. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Trying to reup because the last upload failed. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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_ITEM_VIEW_H_
6 #define UI_VIEWS_CONTROLS_MENU_MENU_ITEM_VIEW_H_
7
8 #include <string>
9 #include <vector>
10
11 #include "base/compiler_specific.h"
12 #include "base/logging.h"
13 #include "base/strings/string16.h"
14 #include "build/build_config.h"
15 #include "ui/base/models/menu_separator_types.h"
16 #include "ui/gfx/image/image_skia.h"
17 #include "ui/views/controls/menu/menu_config.h"
18 #include "ui/views/controls/menu/menu_types.h"
19 #include "ui/views/view.h"
20
21 #if defined(OS_WIN)
22 #include <windows.h>
23
24 #include "ui/native_theme/native_theme.h"
25 #endif
26
27 namespace gfx {
28 class FontList;
29 }
30
31 namespace views {
32
33 namespace internal {
34 class MenuRunnerImpl;
35 }
36
37 class MenuController;
38 class MenuDelegate;
39 class SubmenuView;
40
41 // MenuItemView --------------------------------------------------------------
42
43 // MenuItemView represents a single menu item with a label and optional icon.
44 // Each MenuItemView may also contain a submenu, which in turn may contain
45 // any number of child MenuItemViews.
46 //
47 // To use a menu create an initial MenuItemView using the constructor that
48 // takes a MenuDelegate, then create any number of child menu items by way
49 // of the various AddXXX methods.
50 //
51 // MenuItemView is itself a View, which means you can add Views to each
52 // MenuItemView. This is normally NOT want you want, rather add other child
53 // Views to the submenu of the MenuItemView. Any child views of the MenuItemView
54 // that are focusable can be navigated to by way of the up/down arrow and can be
55 // activated by way of space/return keys. Activating a focusable child results
56 // in |AcceleratorPressed| being invoked. Note, that as menus try not to steal
57 // focus from the hosting window child views do not actually get focus. Instead
58 // |SetHotTracked| is used as the user navigates around.
59 //
60 // To show the menu use MenuRunner. See MenuRunner for details on how to run
61 // (show) the menu as well as for details on the life time of the menu.
62
63 class VIEWS_EXPORT MenuItemView : public View {
64 public:
65 friend class MenuController;
66
67 // The menu item view's class name.
68 static const char kViewClassName[];
69
70 // ID used to identify menu items.
71 static const int kMenuItemViewID;
72
73 // ID used to identify empty menu items.
74 static const int kEmptyMenuItemViewID;
75
76 // Different types of menu items. EMPTY is a special type for empty
77 // menus that is only used internally.
78 enum Type {
79 NORMAL,
80 SUBMENU,
81 CHECKBOX,
82 RADIO,
83 SEPARATOR,
84 EMPTY
85 };
86
87 // Where the menu should be drawn, above or below the bounds (when
88 // the bounds is non-empty). POSITION_BEST_FIT (default) positions
89 // the menu below the bounds unless the menu does not fit on the
90 // screen and the re is more space above.
91 enum MenuPosition {
92 POSITION_BEST_FIT,
93 POSITION_ABOVE_BOUNDS,
94 POSITION_BELOW_BOUNDS
95 };
96
97 // The data structure which is used for the menu size
98 struct MenuItemDimensions {
99 MenuItemDimensions()
100 : standard_width(0),
101 children_width(0),
102 minor_text_width(0),
103 height(0) {}
104
105 // Width of everything except the accelerator and children views.
106 int standard_width;
107 // The width of all contained views of the item.
108 int children_width;
109 // The amount of space needed to accommodate the subtext.
110 int minor_text_width;
111 // The height of the menu item.
112 int height;
113 };
114
115 // Constructor for use with the top level menu item. This menu is never
116 // shown to the user, rather its use as the parent for all menu items.
117 explicit MenuItemView(MenuDelegate* delegate);
118
119 // Overridden from View:
120 virtual bool GetTooltipText(const gfx::Point& p,
121 base::string16* tooltip) const override;
122 virtual void GetAccessibleState(ui::AXViewState* state) override;
123
124 // Returns the preferred height of menu items. This is only valid when the
125 // menu is about to be shown.
126 static int pref_menu_height() { return pref_menu_height_; }
127
128 // X-coordinate of where the label starts.
129 static int label_start() { return label_start_; }
130
131 // Returns if a given |anchor| is a bubble or not.
132 static bool IsBubble(MenuAnchorPosition anchor);
133
134 // Returns the accessible name to be used with screen readers. Mnemonics are
135 // removed and the menu item accelerator text is appended.
136 static base::string16 GetAccessibleNameForMenuItem(
137 const base::string16& item_text, const base::string16& accelerator_text);
138
139 // Hides and cancels the menu. This does nothing if the menu is not open.
140 void Cancel();
141
142 // Add an item to the menu at a specified index. ChildrenChanged() should
143 // called after adding menu items if the menu may be active.
144 MenuItemView* AddMenuItemAt(int index,
145 int item_id,
146 const base::string16& label,
147 const base::string16& sublabel,
148 const base::string16& minor_text,
149 const gfx::ImageSkia& icon,
150 Type type,
151 ui::MenuSeparatorType separator_style);
152
153 // Remove an item from the menu at a specified index. The removed MenuItemView
154 // is deleted when ChildrenChanged() is invoked.
155 void RemoveMenuItemAt(int index);
156
157 // Appends an item to this menu.
158 // item_id The id of the item, used to identify it in delegate callbacks
159 // or (if delegate is NULL) to identify the command associated
160 // with this item with the controller specified in the ctor. Note
161 // that this value should not be 0 as this has a special meaning
162 // ("NULL command, no item selected")
163 // label The text label shown.
164 // type The type of item.
165 MenuItemView* AppendMenuItem(int item_id,
166 const base::string16& label,
167 Type type);
168
169 // Append a submenu to this menu.
170 // The returned pointer is owned by this menu.
171 MenuItemView* AppendSubMenu(int item_id,
172 const base::string16& label);
173
174 // Append a submenu with an icon to this menu.
175 // The returned pointer is owned by this menu.
176 MenuItemView* AppendSubMenuWithIcon(int item_id,
177 const base::string16& label,
178 const gfx::ImageSkia& icon);
179
180 // This is a convenience for standard text label menu items where the label
181 // is provided with this call.
182 MenuItemView* AppendMenuItemWithLabel(int item_id,
183 const base::string16& label);
184
185 // This is a convenience for text label menu items where the label is
186 // provided by the delegate.
187 MenuItemView* AppendDelegateMenuItem(int item_id);
188
189 // Adds a separator to this menu
190 void AppendSeparator();
191
192 // Appends a menu item with an icon. This is for the menu item which
193 // needs an icon. Calling this function forces the Menu class to draw
194 // the menu, instead of relying on Windows.
195 MenuItemView* AppendMenuItemWithIcon(int item_id,
196 const base::string16& label,
197 const gfx::ImageSkia& icon);
198
199 // All the AppendXXX methods funnel into this.
200 MenuItemView* AppendMenuItemImpl(int item_id,
201 const base::string16& label,
202 const base::string16& sublabel,
203 const base::string16& minor_text,
204 const gfx::ImageSkia& icon,
205 Type type,
206 ui::MenuSeparatorType separator_style);
207
208 // Returns the view that contains child menu items. If the submenu has
209 // not been creates, this creates it.
210 virtual SubmenuView* CreateSubmenu();
211
212 // Returns true if this menu item has a submenu.
213 virtual bool HasSubmenu() const;
214
215 // Returns the view containing child menu items.
216 virtual SubmenuView* GetSubmenu() const;
217
218 // Returns the parent menu item.
219 MenuItemView* GetParentMenuItem() { return parent_menu_item_; }
220 const MenuItemView* GetParentMenuItem() const { return parent_menu_item_; }
221
222 // Sets/Gets the title.
223 void SetTitle(const base::string16& title);
224 const base::string16& title() const { return title_; }
225
226 // Sets the subtitle.
227 void SetSubtitle(const base::string16& subtitle);
228
229 // Sets the minor text.
230 void SetMinorText(const base::string16& minor_text);
231
232 // Returns the type of this menu.
233 const Type& GetType() const { return type_; }
234
235 // Sets whether this item is selected. This is invoked as the user moves
236 // the mouse around the menu while open.
237 void SetSelected(bool selected);
238
239 // Returns true if the item is selected.
240 bool IsSelected() const { return selected_; }
241
242 // Sets the |tooltip| for a menu item view with |item_id| identifier.
243 void SetTooltip(const base::string16& tooltip, int item_id);
244
245 // Sets the icon for the descendant identified by item_id.
246 void SetIcon(const gfx::ImageSkia& icon, int item_id);
247
248 // Sets the icon of this menu item.
249 void SetIcon(const gfx::ImageSkia& icon);
250
251 // Sets the view used to render the icon. This clobbers any icon set via
252 // SetIcon(). MenuItemView takes ownership of |icon_view|.
253 void SetIconView(View* icon_view);
254 View* icon_view() { return icon_view_; }
255
256 // Sets the command id of this menu item.
257 void SetCommand(int command) { command_ = command; }
258
259 // Returns the command id of this item.
260 int GetCommand() const { return command_; }
261
262 // Paints the menu item.
263 virtual void OnPaint(gfx::Canvas* canvas) override;
264
265 // Returns the preferred size of this item.
266 virtual gfx::Size GetPreferredSize() const override;
267
268 // Gets the preferred height for the given |width|. This is only different
269 // from GetPreferredSize().width() if the item has a child view with flexible
270 // dimensions.
271 virtual int GetHeightForWidth(int width) const override;
272
273 // Return the preferred dimensions of the item in pixel.
274 const MenuItemDimensions& GetDimensions() const;
275
276 // Returns the object responsible for controlling showing the menu.
277 MenuController* GetMenuController();
278 const MenuController* GetMenuController() const;
279
280 // Returns the delegate. This returns the delegate of the root menu item.
281 MenuDelegate* GetDelegate();
282 const MenuDelegate* GetDelegate() const;
283 void set_delegate(MenuDelegate* delegate) { delegate_ = delegate; }
284
285 // Returns the root parent, or this if this has no parent.
286 MenuItemView* GetRootMenuItem();
287 const MenuItemView* GetRootMenuItem() const;
288
289 // Returns the mnemonic for this MenuItemView, or 0 if this MenuItemView
290 // doesn't have a mnemonic.
291 base::char16 GetMnemonic();
292
293 // Do we have icons? This only has effect on the top menu. Turning this on
294 // makes the menus slightly wider and taller.
295 void set_has_icons(bool has_icons) {
296 has_icons_ = has_icons;
297 }
298 bool has_icons() const { return has_icons_; }
299
300 // Returns the descendant with the specified command.
301 MenuItemView* GetMenuItemByID(int id);
302
303 // Invoke if you remove/add children to the menu while it's showing. This
304 // recalculates the bounds.
305 void ChildrenChanged();
306
307 // Sizes any child views.
308 virtual void Layout() override;
309
310 // Returns true if the menu has mnemonics. This only useful on the root menu
311 // item.
312 bool has_mnemonics() const { return has_mnemonics_; }
313
314 // Set top and bottom margins in pixels. If no margin is set or a
315 // negative margin is specified then MenuConfig values are used.
316 void SetMargins(int top_margin, int bottom_margin);
317
318 // Suppress the right margin if this is set to false.
319 void set_use_right_margin(bool use_right_margin) {
320 use_right_margin_ = use_right_margin;
321 }
322
323 // Returns a reference to MenuConfig to be used with this menu.
324 const MenuConfig& GetMenuConfig() const;
325
326 protected:
327 // Creates a MenuItemView. This is used by the various AddXXX methods.
328 MenuItemView(MenuItemView* parent, int command, Type type);
329
330 // MenuRunner owns MenuItemView and should be the only one deleting it.
331 virtual ~MenuItemView();
332
333 virtual void ChildPreferredSizeChanged(View* child) override;
334
335 virtual const char* GetClassName() const override;
336
337 // Returns the preferred size (and padding) of any children.
338 virtual gfx::Size GetChildPreferredSize() const;
339
340 // Returns the various margins.
341 int GetTopMargin() const;
342 int GetBottomMargin() const;
343
344 private:
345 friend class internal::MenuRunnerImpl; // For access to ~MenuItemView.
346
347 enum PaintButtonMode { PB_NORMAL, PB_FOR_DRAG };
348
349 // Calculates all sizes that we can from the OS.
350 //
351 // This is invoked prior to Running a menu.
352 void UpdateMenuPartSizes();
353
354 // Called by the two constructors to initialize this menu item.
355 void Init(MenuItemView* parent,
356 int command,
357 MenuItemView::Type type,
358 MenuDelegate* delegate);
359
360 // The RunXXX methods call into this to set up the necessary state before
361 // running. |is_first_menu| is true if no menus are currently showing.
362 void PrepareForRun(bool is_first_menu,
363 bool has_mnemonics,
364 bool show_mnemonics);
365
366 // Returns the flags passed to DrawStringRect.
367 int GetDrawStringFlags();
368
369 // Returns the font list to use for menu text.
370 const gfx::FontList& GetFontList() const;
371
372 // If this menu item has no children a child is added showing it has no
373 // children. Otherwise AddEmtpyMenus is recursively invoked on child menu
374 // items that have children.
375 void AddEmptyMenus();
376
377 // Undoes the work of AddEmptyMenus.
378 void RemoveEmptyMenus();
379
380 // Given bounds within our View, this helper routine mirrors the bounds if
381 // necessary.
382 void AdjustBoundsForRTLUI(gfx::Rect* rect) const;
383
384 // Actual paint implementation. If mode is PB_FOR_DRAG, portions of the menu
385 // are not rendered.
386 void PaintButton(gfx::Canvas* canvas, PaintButtonMode mode);
387
388 // Paints the right-side text.
389 void PaintMinorText(gfx::Canvas* canvas, bool render_selection);
390
391 // Destroys the window used to display this menu and recursively destroys
392 // the windows used to display all descendants.
393 void DestroyAllMenuHosts();
394
395 // Returns the text that should be displayed on the end (right) of the menu
396 // item. This will be the accelerator (if one exists), otherwise |subtitle_|.
397 base::string16 GetMinorText() const;
398
399 // Calculates and returns the MenuItemDimensions.
400 MenuItemDimensions CalculateDimensions() const;
401
402 // Get the horizontal position at which to draw the menu item's label.
403 int GetLabelStartForThisItem() const;
404
405 // Used by MenuController to cache the menu position in use by the
406 // active menu.
407 MenuPosition actual_menu_position() const { return actual_menu_position_; }
408 void set_actual_menu_position(MenuPosition actual_menu_position) {
409 actual_menu_position_ = actual_menu_position;
410 }
411
412 void set_controller(MenuController* controller) { controller_ = controller; }
413
414 // Returns true if this MenuItemView contains a single child
415 // that is responsible for rendering the content.
416 bool IsContainer() const;
417
418 // Returns number of child views excluding icon_view.
419 int NonIconChildViewsCount() const;
420
421 // Returns the max icon width; recurses over submenus.
422 int GetMaxIconViewWidth() const;
423
424 // Returns true if the menu has items with a checkbox or a radio button.
425 bool HasChecksOrRadioButtons() const;
426
427 void invalidate_dimensions() { dimensions_.height = 0; }
428 bool is_dimensions_valid() const { return dimensions_.height > 0; }
429
430 // The delegate. This is only valid for the root menu item. You shouldn't
431 // use this directly, instead use GetDelegate() which walks the tree as
432 // as necessary.
433 MenuDelegate* delegate_;
434
435 // The controller for the run operation, or NULL if the menu isn't showing.
436 MenuController* controller_;
437
438 // Used to detect when Cancel was invoked.
439 bool canceled_;
440
441 // Our parent.
442 MenuItemView* parent_menu_item_;
443
444 // Type of menu. NOTE: MenuItemView doesn't itself represent SEPARATOR,
445 // that is handled by an entirely different view class.
446 Type type_;
447
448 // Whether we're selected.
449 bool selected_;
450
451 // Command id.
452 int command_;
453
454 // Submenu, created via CreateSubmenu.
455 SubmenuView* submenu_;
456
457 // Title.
458 base::string16 title_;
459
460 // Subtitle/sublabel.
461 base::string16 subtitle_;
462
463 // Minor text.
464 base::string16 minor_text_;
465
466 // Does the title have a mnemonic? Only useful on the root menu item.
467 bool has_mnemonics_;
468
469 // Should we show the mnemonic? Mnemonics are shown if this is true or
470 // MenuConfig says mnemonics should be shown. Only used on the root menu item.
471 bool show_mnemonics_;
472
473 // Set if menu has icons or icon_views (applies to root menu item only).
474 bool has_icons_;
475
476 // Pointer to a view with a menu icon.
477 View* icon_view_;
478
479 // The tooltip to show on hover for this menu item.
480 base::string16 tooltip_;
481
482 // Width of a menu icon area.
483 static int icon_area_width_;
484
485 // X-coordinate of where the label starts.
486 static int label_start_;
487
488 // Margins between the right of the item and the label.
489 static int item_right_margin_;
490
491 // Preferred height of menu items. Reset every time a menu is run.
492 static int pref_menu_height_;
493
494 // Cached dimensions. This is cached as text sizing calculations are quite
495 // costly.
496 mutable MenuItemDimensions dimensions_;
497
498 // Removed items to be deleted in ChildrenChanged().
499 std::vector<View*> removed_items_;
500
501 // Margins in pixels.
502 int top_margin_;
503 int bottom_margin_;
504
505 // Horizontal icon margins in pixels, which can differ between MenuItems.
506 // These values will be set in the layout process.
507 mutable int left_icon_margin_;
508 mutable int right_icon_margin_;
509
510 // |menu_position_| is the requested position with respect to the bounds.
511 // |actual_menu_position_| is used by the controller to cache the
512 // position of the menu being shown.
513 MenuPosition requested_menu_position_;
514 MenuPosition actual_menu_position_;
515
516 // If set to false, the right margin will be removed for menu lines
517 // containing other elements.
518 bool use_right_margin_;
519
520 DISALLOW_COPY_AND_ASSIGN(MenuItemView);
521 };
522
523 } // namespace views
524
525 #endif // UI_VIEWS_CONTROLS_MENU_MENU_ITEM_VIEW_H_
OLDNEW
« no previous file with comments | « ui/views/controls/menu/menu_insertion_delegate_win.h ('k') | ui/views/controls/menu/menu_item_view.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698