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 <string> 9 #include <vector> 10 11 #include "base/compiler_specific.h" 12 #include "base/macros.h" 13 #include "base/memory/weak_ptr.h" 14 #include "base/strings/string16.h" 15 #include "ui/base/accelerators/accelerator.h" 16 #include "ui/base/models/menu_model.h" 17 #include "ui/gfx/image/image.h" 18 19 namespace gfx { 20 struct VectorIcon; 21 } 22 23 namespace ui { 24 25 class ButtonMenuItemModel; 26 27 // A simple MenuModel implementation with an imperative API for adding menu 28 // items. This makes it easy to construct fixed menus. Menus populated by 29 // dynamic data sources may be better off implementing MenuModel directly. 30 // The breadth of MenuModel is not exposed through this API. 31 class UI_BASE_EXPORT SimpleMenuModel : public MenuModel { 32 public: 33 class UI_BASE_EXPORT Delegate : public AcceleratorProvider { 34 public: ~Delegate()35 ~Delegate() override {} 36 37 // Makes |command_id| appear toggled true if it's a "check" or "radio" type 38 // menu item. This has no effect for menu items with no boolean state. 39 virtual bool IsCommandIdChecked(int command_id) const; 40 41 // Delegate should return true if |command_id| should be enabled. 42 virtual bool IsCommandIdEnabled(int command_id) const; 43 44 // Delegate should return true if |command_id| should be visible. 45 virtual bool IsCommandIdVisible(int command_id) const; 46 47 // Some command ids have labels and icons that change over time. 48 virtual bool IsItemForCommandIdDynamic(int command_id) const; 49 virtual base::string16 GetLabelForCommandId(int command_id) const; 50 // Gets the icon for the item with the specified id, returning true if there 51 // is an icon, false otherwise. 52 virtual bool GetIconForCommandId(int command_id, 53 gfx::Image* icon) const; 54 55 // Returns the vector icon for the given command id, or null if there is 56 // none. Only used for dynamic menu items. 57 virtual const gfx::VectorIcon* GetVectorIconForCommandId( 58 int command_id) const; 59 60 // Performs the action associates with the specified command id. 61 // The passed |event_flags| are the flags from the event which issued this 62 // command and they can be examined to find modifier keys. 63 virtual void ExecuteCommand(int command_id, int event_flags) = 0; 64 65 // Notifies the delegate that the menu is about to show. 66 // Slight hack: Prefix with "On" to make sure this doesn't conflict with 67 // MenuModel::MenuWillShow(), since many classes derive from both 68 // SimpleMenuModel and SimpleMenuModel::Delegate. 69 virtual void OnMenuWillShow(SimpleMenuModel* source); 70 71 // Notifies the delegate that the menu has closed. 72 virtual void MenuClosed(SimpleMenuModel* source); 73 74 // AcceleratorProvider overrides: 75 // By default, returns false for all commands. Can be further overridden. 76 bool GetAcceleratorForCommandId( 77 int command_id, 78 ui::Accelerator* accelerator) const override; 79 }; 80 81 // The Delegate can be NULL, though if it is items can't be checked or 82 // disabled. 83 explicit SimpleMenuModel(Delegate* delegate); 84 ~SimpleMenuModel() override; 85 86 // Methods for adding items to the model. 87 void AddItem(int command_id, const base::string16& label); 88 void AddItemWithStringId(int command_id, int string_id); 89 void AddItemWithIcon(int command_id, 90 const base::string16& label, 91 const gfx::ImageSkia& icon); 92 void AddItemWithIcon(int command_id, 93 const base::string16& label, 94 const gfx::VectorIcon& icon); 95 void AddItemWithStringIdAndIcon(int command_id, 96 int string_id, 97 const gfx::ImageSkia& icon); 98 void AddItemWithStringIdAndIcon(int command_id, 99 int string_id, 100 const gfx::VectorIcon& icon); 101 void AddCheckItem(int command_id, const base::string16& label); 102 void AddCheckItemWithStringId(int command_id, int string_id); 103 void AddRadioItem(int command_id, const base::string16& label, int group_id); 104 void AddRadioItemWithStringId(int command_id, int string_id, int group_id); 105 void AddHighlightedItemWithIcon(int command_id, 106 const base::string16& label, 107 const gfx::ImageSkia& icon); 108 void AddTitle(const base::string16& label); 109 110 // Adds a separator of the specified type to the model. 111 // - Adding a separator after another separator is always invalid if they 112 // differ in type, but silently ignored if they are both NORMAL. 113 // - Adding a separator to an empty model is invalid, unless they are NORMAL 114 // or SPACING. NORMAL separators are silently ignored if the model is empty. 115 void AddSeparator(MenuSeparatorType separator_type); 116 117 // These methods take pointers to various sub-models. These models should be 118 // owned by the same owner of this SimpleMenuModel. 119 void AddButtonItem(int command_id, ButtonMenuItemModel* model); 120 void AddSubMenu(int command_id, 121 const base::string16& label, 122 MenuModel* model); 123 void AddSubMenuWithStringId(int command_id, int string_id, MenuModel* model); 124 void AddSubMenuWithStringIdAndIcon(int command_id, 125 int string_id, 126 MenuModel* model, 127 const gfx::ImageSkia& icon); 128 void AddSubMenuWithStringIdAndIcon(int command_id, 129 int string_id, 130 MenuModel* model, 131 const gfx::VectorIcon& icon); 132 void AddActionableSubMenu(int command_id, 133 const base::string16& label, 134 MenuModel* model); 135 void AddActionableSubmenuWithStringIdAndIcon(int command_id, 136 int string_id, 137 MenuModel* model, 138 const gfx::ImageSkia& icon); 139 void AddActionableSubmenuWithStringIdAndIcon(int command_id, 140 int string_id, 141 MenuModel* model, 142 const gfx::VectorIcon& icon); 143 144 // Methods for inserting items into the model. 145 void InsertItemAt(int index, int command_id, const base::string16& label); 146 void InsertItemWithStringIdAt(int index, int command_id, int string_id); 147 void InsertSeparatorAt(int index, MenuSeparatorType separator_type); 148 void InsertCheckItemAt(int index, 149 int command_id, 150 const base::string16& label); 151 void InsertCheckItemWithStringIdAt(int index, int command_id, int string_id); 152 void InsertRadioItemAt(int index, 153 int command_id, 154 const base::string16& label, 155 int group_id); 156 void InsertRadioItemWithStringIdAt( 157 int index, int command_id, int string_id, int group_id); 158 void InsertSubMenuAt(int index, 159 int command_id, 160 const base::string16& label, 161 MenuModel* model); 162 void InsertSubMenuWithStringIdAt( 163 int index, int command_id, int string_id, MenuModel* model); 164 165 // Remove item at specified index from the model. 166 void RemoveItemAt(int index); 167 168 // Sets the icon for the item at |index|. 169 void SetIcon(int index, const gfx::Image& icon); 170 171 // As above, but uses a VectorIcon. Only one of the two should be set. 172 void SetIcon(int index, const gfx::VectorIcon& icon); 173 174 // Sets the label for the item at |index|. 175 void SetLabel(int index, const base::string16& label); 176 177 // Sets the minor text for the item at |index|. 178 void SetMinorText(int index, const base::string16& minor_text); 179 180 // Sets the minor icon for the item at |index|. 181 void SetMinorIcon(int index, const gfx::VectorIcon& minor_icon); 182 183 // Sets whether the item at |index| is enabled. 184 void SetEnabledAt(int index, bool enabled); 185 186 // Sets whether the item at |index| is visible. 187 void SetVisibleAt(int index, bool visible); 188 189 // Clears all items. Note that it does not free MenuModel of submenu. 190 void Clear(); 191 192 // Returns the index of the item that has the given |command_id|. Returns 193 // -1 if not found. 194 int GetIndexOfCommandId(int command_id) const; 195 196 // Overridden from MenuModel: 197 bool HasIcons() const override; 198 int GetItemCount() const override; 199 ItemType GetTypeAt(int index) const override; 200 ui::MenuSeparatorType GetSeparatorTypeAt(int index) const override; 201 int GetCommandIdAt(int index) const override; 202 base::string16 GetLabelAt(int index) const override; 203 base::string16 GetMinorTextAt(int index) const override; 204 const gfx::VectorIcon* GetMinorIconAt(int index) const override; 205 bool IsItemDynamicAt(int index) const override; 206 bool GetAcceleratorAt(int index, ui::Accelerator* accelerator) const override; 207 bool IsItemCheckedAt(int index) const override; 208 int GetGroupIdAt(int index) const override; 209 bool GetIconAt(int index, gfx::Image* icon) const override; 210 const gfx::VectorIcon* GetVectorIconAt(int index) const override; 211 ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const override; 212 bool IsEnabledAt(int index) const override; 213 bool IsVisibleAt(int index) const override; 214 void ActivatedAt(int index) override; 215 void ActivatedAt(int index, int event_flags) override; 216 MenuModel* GetSubmenuModelAt(int index) const override; 217 void MenuWillShow() override; 218 void MenuWillClose() override; 219 220 protected: set_delegate(Delegate * delegate)221 void set_delegate(Delegate* delegate) { delegate_ = delegate; } delegate()222 Delegate* delegate() { return delegate_; } 223 224 // One or more of the menu menu items associated with the model has changed. 225 // Do any handling if necessary. 226 virtual void MenuItemsChanged(); 227 228 private: 229 struct Item { 230 Item(Item&&); 231 Item(int command_id, ItemType type, base::string16 label); 232 Item& operator=(Item&&); 233 ~Item(); 234 235 int command_id = 0; 236 ItemType type = TYPE_COMMAND; 237 base::string16 label; 238 base::string16 minor_text; 239 const gfx::VectorIcon* minor_icon = nullptr; 240 gfx::Image icon; 241 const gfx::VectorIcon* vector_icon = nullptr; 242 int group_id = -1; 243 MenuModel* submenu = nullptr; 244 ButtonMenuItemModel* button_model = nullptr; 245 MenuSeparatorType separator_type = NORMAL_SEPARATOR; 246 bool enabled = true; 247 bool visible = true; 248 }; 249 250 typedef std::vector<Item> ItemVector; 251 252 // Returns |index|. 253 int ValidateItemIndex(int index) const; 254 255 // Functions for inserting items into |items_|. 256 void AppendItem(Item item); 257 void InsertItemAtIndex(Item item, int index); 258 void ValidateItem(const Item& item); 259 260 // Notify the delegate that the menu is closed. 261 void OnMenuClosed(); 262 263 ItemVector items_; 264 265 Delegate* delegate_; 266 267 base::WeakPtrFactory<SimpleMenuModel> method_factory_{this}; 268 269 DISALLOW_COPY_AND_ASSIGN(SimpleMenuModel); 270 }; 271 272 } // namespace ui 273 274 #endif // UI_BASE_MODELS_SIMPLE_MENU_MODEL_H_ 275