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