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_BASE_MODELS_SIMPLE_MENU_MODEL_H_
6#define UI_BASE_MODELS_SIMPLE_MENU_MODEL_H_
7
8#include <vector>
9
10#include "base/memory/weak_ptr.h"
11#include "base/strings/string16.h"
12#include "ui/base/models/menu_model.h"
13
14namespace gfx {
15class Image;
16}
17
18namespace ui {
19
20class ButtonMenuItemModel;
21
22// A simple MenuModel implementation with an imperative API for adding menu
23// items. This makes it easy to construct fixed menus. Menus populated by
24// dynamic data sources may be better off implementing MenuModel directly.
25// The breadth of MenuModel is not exposed through this API.
26class UI_BASE_EXPORT SimpleMenuModel : public MenuModel {
27 public:
28  class UI_BASE_EXPORT Delegate {
29   public:
30    virtual ~Delegate() {}
31
32    // Methods for determining the state of specific command ids.
33    virtual bool IsCommandIdChecked(int command_id) const = 0;
34    virtual bool IsCommandIdEnabled(int command_id) const = 0;
35    virtual bool IsCommandIdVisible(int command_id) const;
36
37    // Gets the accelerator for the specified command id. Returns true if the
38    // command id has a valid accelerator, false otherwise.
39    virtual bool GetAcceleratorForCommandId(
40        int command_id,
41        ui::Accelerator* accelerator) = 0;
42
43    // Some command ids have labels, sublabels, minor text and icons that change
44    // over time.
45    virtual bool IsItemForCommandIdDynamic(int command_id) const;
46    virtual base::string16 GetLabelForCommandId(int command_id) const;
47    virtual base::string16 GetSublabelForCommandId(int command_id) const;
48    virtual base::string16 GetMinorTextForCommandId(int command_id) const;
49    // Gets the icon for the item with the specified id, returning true if there
50    // is an icon, false otherwise.
51    virtual bool GetIconForCommandId(int command_id,
52                                     gfx::Image* icon) const;
53
54    // Notifies the delegate that the item with the specified command id was
55    // visually highlighted within the menu.
56    virtual void CommandIdHighlighted(int command_id);
57
58    // Performs the action associates with the specified command id.
59    // The passed |event_flags| are the flags from the event which issued this
60    // command and they can be examined to find modifier keys.
61    virtual void ExecuteCommand(int command_id, int event_flags) = 0;
62
63    // Notifies the delegate that the menu is about to show.
64    virtual void MenuWillShow(SimpleMenuModel* source);
65
66    // Notifies the delegate that the menu has closed.
67    virtual void MenuClosed(SimpleMenuModel* source);
68  };
69
70  // The Delegate can be NULL, though if it is items can't be checked or
71  // disabled.
72  explicit SimpleMenuModel(Delegate* delegate);
73  virtual ~SimpleMenuModel();
74
75  // Methods for adding items to the model.
76  void AddItem(int command_id, const base::string16& label);
77  void AddItemWithStringId(int command_id, int string_id);
78  void AddCheckItem(int command_id, const base::string16& label);
79  void AddCheckItemWithStringId(int command_id, int string_id);
80  void AddRadioItem(int command_id, const base::string16& label, int group_id);
81  void AddRadioItemWithStringId(int command_id, int string_id, int group_id);
82
83  // Adds a separator of the specified type to the model.
84  // - Adding a separator after another separator is always invalid if they
85  //   differ in type, but silently ignored if they are both NORMAL.
86  // - Adding a separator to an empty model is invalid, unless they are NORMAL
87  //   or SPACING. NORMAL separators are silently ignored if the model is empty.
88  void AddSeparator(MenuSeparatorType separator_type);
89
90  // Removes separators until the model's last entry is not a separator, or the
91  // model is empty.
92  void RemoveTrailingSeparators();
93
94  // These three methods take pointers to various sub-models. These models
95  // should be owned by the same owner of this SimpleMenuModel.
96  void AddButtonItem(int command_id, ButtonMenuItemModel* model);
97  void AddSubMenu(int command_id,
98                  const base::string16& label,
99                  MenuModel* model);
100  void AddSubMenuWithStringId(int command_id, int string_id, MenuModel* model);
101
102  // Methods for inserting items into the model.
103  void InsertItemAt(int index, int command_id, const base::string16& label);
104  void InsertItemWithStringIdAt(int index, int command_id, int string_id);
105  void InsertSeparatorAt(int index, MenuSeparatorType separator_type);
106  void InsertCheckItemAt(int index,
107                         int command_id,
108                         const base::string16& label);
109  void InsertCheckItemWithStringIdAt(int index, int command_id, int string_id);
110  void InsertRadioItemAt(int index,
111                         int command_id,
112                         const base::string16& label,
113                         int group_id);
114  void InsertRadioItemWithStringIdAt(
115      int index, int command_id, int string_id, int group_id);
116  void InsertSubMenuAt(int index,
117                       int command_id,
118                       const base::string16& label,
119                       MenuModel* model);
120  void InsertSubMenuWithStringIdAt(
121      int index, int command_id, int string_id, MenuModel* model);
122
123  // Remove item at specified index from the model.
124  void RemoveItemAt(int index);
125
126  // Sets the icon for the item at |index|.
127  void SetIcon(int index, const gfx::Image& icon);
128
129  // Sets the sublabel for the item at |index|.
130  void SetSublabel(int index, const base::string16& sublabel);
131
132  // Sets the minor text for the item at |index|.
133  void SetMinorText(int index, const base::string16& minor_text);
134
135  // Clears all items. Note that it does not free MenuModel of submenu.
136  void Clear();
137
138  // Returns the index of the item that has the given |command_id|. Returns
139  // -1 if not found.
140  int GetIndexOfCommandId(int command_id);
141
142  // Overridden from MenuModel:
143  virtual bool HasIcons() const OVERRIDE;
144  virtual int GetItemCount() const OVERRIDE;
145  virtual ItemType GetTypeAt(int index) const OVERRIDE;
146  virtual ui::MenuSeparatorType GetSeparatorTypeAt(int index) const OVERRIDE;
147  virtual int GetCommandIdAt(int index) const OVERRIDE;
148  virtual base::string16 GetLabelAt(int index) const OVERRIDE;
149  virtual base::string16 GetSublabelAt(int index) const OVERRIDE;
150  virtual base::string16 GetMinorTextAt(int index) const OVERRIDE;
151  virtual bool IsItemDynamicAt(int index) const OVERRIDE;
152  virtual bool GetAcceleratorAt(int index,
153                                ui::Accelerator* accelerator) const OVERRIDE;
154  virtual bool IsItemCheckedAt(int index) const OVERRIDE;
155  virtual int GetGroupIdAt(int index) const OVERRIDE;
156  virtual bool GetIconAt(int index, gfx::Image* icon) OVERRIDE;
157  virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt(
158      int index) const OVERRIDE;
159  virtual bool IsEnabledAt(int index) const OVERRIDE;
160  virtual bool IsVisibleAt(int index) const OVERRIDE;
161  virtual void HighlightChangedTo(int index) OVERRIDE;
162  virtual void ActivatedAt(int index) OVERRIDE;
163  virtual void ActivatedAt(int index, int event_flags) OVERRIDE;
164  virtual MenuModel* GetSubmenuModelAt(int index) const OVERRIDE;
165  virtual void MenuWillShow() OVERRIDE;
166  virtual void MenuClosed() OVERRIDE;
167  virtual void SetMenuModelDelegate(
168      ui::MenuModelDelegate* menu_model_delegate) OVERRIDE;
169  virtual MenuModelDelegate* GetMenuModelDelegate() const OVERRIDE;
170
171 protected:
172  void set_delegate(Delegate* delegate) { delegate_ = delegate; }
173  Delegate* delegate() { return delegate_; }
174
175  // One or more of the menu menu items associated with the model has changed.
176  // Do any handling if necessary.
177  virtual void MenuItemsChanged();
178
179 private:
180  struct Item;
181
182  typedef std::vector<Item> ItemVector;
183
184  // Returns |index|.
185  int ValidateItemIndex(int index) const;
186
187  // Functions for inserting items into |items_|.
188  void AppendItem(const Item& item);
189  void InsertItemAtIndex(const Item& item, int index);
190  void ValidateItem(const Item& item);
191
192  // Notify the delegate that the menu is closed.
193  void OnMenuClosed();
194
195  ItemVector items_;
196
197  Delegate* delegate_;
198
199  MenuModelDelegate* menu_model_delegate_;
200
201  base::WeakPtrFactory<SimpleMenuModel> method_factory_;
202
203  DISALLOW_COPY_AND_ASSIGN(SimpleMenuModel);
204};
205
206}  // namespace ui
207
208#endif  // UI_BASE_MODELS_SIMPLE_MENU_MODEL_H_
209