Remove 'RemoveTrailingSeparators' function from SimpleMenuModel
[chromium-blink-merge.git] / ui / base / models / simple_menu_model.cc
blobcbbdd0de687071b383085f4d6ae628e2a27622f5
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.
5 #include "ui/base/models/simple_menu_model.h"
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "ui/base/l10n/l10n_util.h"
10 #include "ui/gfx/image/image.h"
12 namespace ui {
14 const int kSeparatorId = -1;
16 struct SimpleMenuModel::Item {
17 int command_id;
18 base::string16 label;
19 base::string16 sublabel;
20 base::string16 minor_text;
21 gfx::Image icon;
22 ItemType type;
23 int group_id;
24 MenuModel* submenu;
25 ButtonMenuItemModel* button_model;
26 MenuSeparatorType separator_type;
29 ////////////////////////////////////////////////////////////////////////////////
30 // SimpleMenuModel::Delegate, public:
32 bool SimpleMenuModel::Delegate::IsCommandIdVisible(int command_id) const {
33 return true;
36 bool SimpleMenuModel::Delegate::IsItemForCommandIdDynamic(
37 int command_id) const {
38 return false;
41 base::string16 SimpleMenuModel::Delegate::GetLabelForCommandId(
42 int command_id) const {
43 return base::string16();
46 base::string16 SimpleMenuModel::Delegate::GetSublabelForCommandId(
47 int command_id) const {
48 return base::string16();
51 base::string16 SimpleMenuModel::Delegate::GetMinorTextForCommandId(
52 int command_id) const {
53 return base::string16();
56 bool SimpleMenuModel::Delegate::GetIconForCommandId(
57 int command_id, gfx::Image* image_skia) const {
58 return false;
61 void SimpleMenuModel::Delegate::CommandIdHighlighted(int command_id) {
64 void SimpleMenuModel::Delegate::ExecuteCommand(
65 int command_id, int event_flags) {
66 ExecuteCommand(command_id, event_flags);
69 void SimpleMenuModel::Delegate::MenuWillShow(SimpleMenuModel* /*source*/) {
72 void SimpleMenuModel::Delegate::MenuClosed(SimpleMenuModel* /*source*/) {
75 ////////////////////////////////////////////////////////////////////////////////
76 // SimpleMenuModel, public:
78 SimpleMenuModel::SimpleMenuModel(Delegate* delegate)
79 : delegate_(delegate),
80 menu_model_delegate_(NULL),
81 method_factory_(this) {
84 SimpleMenuModel::~SimpleMenuModel() {
87 void SimpleMenuModel::AddItem(int command_id, const base::string16& label) {
88 Item item = { command_id, label, base::string16(), base::string16(),
89 gfx::Image(), TYPE_COMMAND, -1, NULL, NULL, NORMAL_SEPARATOR };
90 AppendItem(item);
93 void SimpleMenuModel::AddItemWithStringId(int command_id, int string_id) {
94 AddItem(command_id, l10n_util::GetStringUTF16(string_id));
97 void SimpleMenuModel::AddCheckItem(int command_id,
98 const base::string16& label) {
99 Item item = { command_id, label, base::string16(), base::string16(),
100 gfx::Image(), TYPE_CHECK, -1, NULL, NULL, NORMAL_SEPARATOR };
101 AppendItem(item);
104 void SimpleMenuModel::AddCheckItemWithStringId(int command_id, int string_id) {
105 AddCheckItem(command_id, l10n_util::GetStringUTF16(string_id));
108 void SimpleMenuModel::AddRadioItem(int command_id,
109 const base::string16& label,
110 int group_id) {
111 Item item = { command_id, label, base::string16(), base::string16(),
112 gfx::Image(), TYPE_RADIO, group_id, NULL, NULL,
113 NORMAL_SEPARATOR };
114 AppendItem(item);
117 void SimpleMenuModel::AddRadioItemWithStringId(int command_id, int string_id,
118 int group_id) {
119 AddRadioItem(command_id, l10n_util::GetStringUTF16(string_id), group_id);
122 void SimpleMenuModel::AddSeparator(MenuSeparatorType separator_type) {
123 if (items_.empty()) {
124 if (separator_type == NORMAL_SEPARATOR) {
125 return;
127 DCHECK_EQ(SPACING_SEPARATOR, separator_type);
128 } else if (items_.back().type == TYPE_SEPARATOR) {
129 DCHECK_EQ(NORMAL_SEPARATOR, separator_type);
130 DCHECK_EQ(NORMAL_SEPARATOR, items_.back().separator_type);
131 return;
133 #if !defined(USE_AURA)
134 if (separator_type == SPACING_SEPARATOR)
135 NOTIMPLEMENTED();
136 #endif
137 Item item = { kSeparatorId, base::string16(), base::string16(),
138 base::string16(), gfx::Image(), TYPE_SEPARATOR, -1, NULL, NULL,
139 separator_type };
140 AppendItem(item);
143 void SimpleMenuModel::AddButtonItem(int command_id,
144 ButtonMenuItemModel* model) {
145 Item item = { command_id, base::string16(), base::string16(),
146 base::string16(), gfx::Image(), TYPE_BUTTON_ITEM, -1, NULL,
147 model, NORMAL_SEPARATOR };
148 AppendItem(item);
151 void SimpleMenuModel::AddSubMenu(int command_id,
152 const base::string16& label,
153 MenuModel* model) {
154 Item item = { command_id, label, base::string16(), base::string16(),
155 gfx::Image(), TYPE_SUBMENU, -1, model, NULL, NORMAL_SEPARATOR };
156 AppendItem(item);
159 void SimpleMenuModel::AddSubMenuWithStringId(int command_id,
160 int string_id, MenuModel* model) {
161 AddSubMenu(command_id, l10n_util::GetStringUTF16(string_id), model);
164 void SimpleMenuModel::InsertItemAt(int index,
165 int command_id,
166 const base::string16& label) {
167 Item item = { command_id, label, base::string16(), base::string16(),
168 gfx::Image(), TYPE_COMMAND, -1, NULL, NULL, NORMAL_SEPARATOR };
169 InsertItemAtIndex(item, index);
172 void SimpleMenuModel::InsertItemWithStringIdAt(
173 int index, int command_id, int string_id) {
174 InsertItemAt(index, command_id, l10n_util::GetStringUTF16(string_id));
177 void SimpleMenuModel::InsertSeparatorAt(int index,
178 MenuSeparatorType separator_type) {
179 #if !defined(USE_AURA)
180 if (separator_type != NORMAL_SEPARATOR) {
181 NOTIMPLEMENTED();
183 #endif
184 Item item = { kSeparatorId, base::string16(), base::string16(),
185 base::string16(), gfx::Image(), TYPE_SEPARATOR, -1, NULL, NULL,
186 separator_type };
187 InsertItemAtIndex(item, index);
190 void SimpleMenuModel::InsertCheckItemAt(int index,
191 int command_id,
192 const base::string16& label) {
193 Item item = { command_id, label, base::string16(), base::string16(),
194 gfx::Image(), TYPE_CHECK, -1, NULL, NULL, NORMAL_SEPARATOR };
195 InsertItemAtIndex(item, index);
198 void SimpleMenuModel::InsertCheckItemWithStringIdAt(
199 int index, int command_id, int string_id) {
200 InsertCheckItemAt(index, command_id, l10n_util::GetStringUTF16(string_id));
203 void SimpleMenuModel::InsertRadioItemAt(int index,
204 int command_id,
205 const base::string16& label,
206 int group_id) {
207 Item item = { command_id, label, base::string16(), base::string16(),
208 gfx::Image(), TYPE_RADIO, group_id, NULL, NULL,
209 NORMAL_SEPARATOR };
210 InsertItemAtIndex(item, index);
213 void SimpleMenuModel::InsertRadioItemWithStringIdAt(
214 int index, int command_id, int string_id, int group_id) {
215 InsertRadioItemAt(
216 index, command_id, l10n_util::GetStringUTF16(string_id), group_id);
219 void SimpleMenuModel::InsertSubMenuAt(int index,
220 int command_id,
221 const base::string16& label,
222 MenuModel* model) {
223 Item item = { command_id, label, base::string16(), base::string16(),
224 gfx::Image(), TYPE_SUBMENU, -1, model, NULL,
225 NORMAL_SEPARATOR };
226 InsertItemAtIndex(item, index);
229 void SimpleMenuModel::InsertSubMenuWithStringIdAt(
230 int index, int command_id, int string_id, MenuModel* model) {
231 InsertSubMenuAt(index, command_id, l10n_util::GetStringUTF16(string_id),
232 model);
235 void SimpleMenuModel::RemoveItemAt(int index) {
236 items_.erase(items_.begin() + ValidateItemIndex(index));
237 MenuItemsChanged();
240 void SimpleMenuModel::SetIcon(int index, const gfx::Image& icon) {
241 items_[ValidateItemIndex(index)].icon = icon;
242 MenuItemsChanged();
245 void SimpleMenuModel::SetSublabel(int index, const base::string16& sublabel) {
246 items_[ValidateItemIndex(index)].sublabel = sublabel;
247 MenuItemsChanged();
250 void SimpleMenuModel::SetMinorText(int index,
251 const base::string16& minor_text) {
252 items_[ValidateItemIndex(index)].minor_text = minor_text;
255 void SimpleMenuModel::Clear() {
256 items_.clear();
257 MenuItemsChanged();
260 int SimpleMenuModel::GetIndexOfCommandId(int command_id) {
261 for (ItemVector::iterator i = items_.begin(); i != items_.end(); ++i) {
262 if (i->command_id == command_id)
263 return static_cast<int>(std::distance(items_.begin(), i));
265 return -1;
268 ////////////////////////////////////////////////////////////////////////////////
269 // SimpleMenuModel, MenuModel implementation:
271 bool SimpleMenuModel::HasIcons() const {
272 for (ItemVector::const_iterator i = items_.begin(); i != items_.end(); ++i) {
273 if (!i->icon.IsEmpty())
274 return true;
277 return false;
280 int SimpleMenuModel::GetItemCount() const {
281 return static_cast<int>(items_.size());
284 MenuModel::ItemType SimpleMenuModel::GetTypeAt(int index) const {
285 return items_[ValidateItemIndex(index)].type;
288 ui::MenuSeparatorType SimpleMenuModel::GetSeparatorTypeAt(int index) const {
289 return items_[ValidateItemIndex(index)].separator_type;
292 int SimpleMenuModel::GetCommandIdAt(int index) const {
293 return items_[ValidateItemIndex(index)].command_id;
296 base::string16 SimpleMenuModel::GetLabelAt(int index) const {
297 if (IsItemDynamicAt(index))
298 return delegate_->GetLabelForCommandId(GetCommandIdAt(index));
299 return items_[ValidateItemIndex(index)].label;
302 base::string16 SimpleMenuModel::GetSublabelAt(int index) const {
303 if (IsItemDynamicAt(index))
304 return delegate_->GetSublabelForCommandId(GetCommandIdAt(index));
305 return items_[ValidateItemIndex(index)].sublabel;
308 base::string16 SimpleMenuModel::GetMinorTextAt(int index) const {
309 if (IsItemDynamicAt(index))
310 return delegate_->GetMinorTextForCommandId(GetCommandIdAt(index));
311 return items_[ValidateItemIndex(index)].minor_text;
314 bool SimpleMenuModel::IsItemDynamicAt(int index) const {
315 if (delegate_)
316 return delegate_->IsItemForCommandIdDynamic(GetCommandIdAt(index));
317 return false;
320 bool SimpleMenuModel::GetAcceleratorAt(int index,
321 ui::Accelerator* accelerator) const {
322 if (delegate_) {
323 return delegate_->GetAcceleratorForCommandId(GetCommandIdAt(index),
324 accelerator);
326 return false;
329 bool SimpleMenuModel::IsItemCheckedAt(int index) const {
330 if (!delegate_)
331 return false;
332 MenuModel::ItemType item_type = GetTypeAt(index);
333 return (item_type == TYPE_CHECK || item_type == TYPE_RADIO) ?
334 delegate_->IsCommandIdChecked(GetCommandIdAt(index)) : false;
337 int SimpleMenuModel::GetGroupIdAt(int index) const {
338 return items_[ValidateItemIndex(index)].group_id;
341 bool SimpleMenuModel::GetIconAt(int index, gfx::Image* icon) {
342 if (IsItemDynamicAt(index))
343 return delegate_->GetIconForCommandId(GetCommandIdAt(index), icon);
345 ValidateItemIndex(index);
346 if (items_[index].icon.IsEmpty())
347 return false;
349 *icon = items_[index].icon;
350 return true;
353 ButtonMenuItemModel* SimpleMenuModel::GetButtonMenuItemAt(int index) const {
354 return items_[ValidateItemIndex(index)].button_model;
357 bool SimpleMenuModel::IsEnabledAt(int index) const {
358 int command_id = GetCommandIdAt(index);
359 if (!delegate_ || command_id == kSeparatorId || GetButtonMenuItemAt(index))
360 return true;
361 return delegate_->IsCommandIdEnabled(command_id);
364 bool SimpleMenuModel::IsVisibleAt(int index) const {
365 int command_id = GetCommandIdAt(index);
366 if (!delegate_ || command_id == kSeparatorId || GetButtonMenuItemAt(index))
367 return true;
368 return delegate_->IsCommandIdVisible(command_id);
371 void SimpleMenuModel::HighlightChangedTo(int index) {
372 if (delegate_)
373 delegate_->CommandIdHighlighted(GetCommandIdAt(index));
376 void SimpleMenuModel::ActivatedAt(int index) {
377 if (delegate_)
378 delegate_->ExecuteCommand(GetCommandIdAt(index), 0);
381 void SimpleMenuModel::ActivatedAt(int index, int event_flags) {
382 if (delegate_)
383 delegate_->ExecuteCommand(GetCommandIdAt(index), event_flags);
386 MenuModel* SimpleMenuModel::GetSubmenuModelAt(int index) const {
387 return items_[ValidateItemIndex(index)].submenu;
390 void SimpleMenuModel::MenuWillShow() {
391 if (delegate_)
392 delegate_->MenuWillShow(this);
395 void SimpleMenuModel::MenuClosed() {
396 // Due to how menus work on the different platforms, ActivatedAt will be
397 // called after this. It's more convenient for the delegate to be called
398 // afterwards though, so post a task.
399 base::MessageLoop::current()->PostTask(
400 FROM_HERE,
401 base::Bind(&SimpleMenuModel::OnMenuClosed, method_factory_.GetWeakPtr()));
404 void SimpleMenuModel::SetMenuModelDelegate(
405 ui::MenuModelDelegate* menu_model_delegate) {
406 menu_model_delegate_ = menu_model_delegate;
409 MenuModelDelegate* SimpleMenuModel::GetMenuModelDelegate() const {
410 return menu_model_delegate_;
413 void SimpleMenuModel::OnMenuClosed() {
414 if (delegate_)
415 delegate_->MenuClosed(this);
418 ////////////////////////////////////////////////////////////////////////////////
419 // SimpleMenuModel, Protected:
421 void SimpleMenuModel::MenuItemsChanged() {
424 ////////////////////////////////////////////////////////////////////////////////
425 // SimpleMenuModel, Private:
427 int SimpleMenuModel::ValidateItemIndex(int index) const {
428 CHECK_GE(index, 0);
429 CHECK_LT(static_cast<size_t>(index), items_.size());
430 return index;
433 void SimpleMenuModel::AppendItem(const Item& item) {
434 ValidateItem(item);
435 items_.push_back(item);
436 MenuItemsChanged();
439 void SimpleMenuModel::InsertItemAtIndex(const Item& item, int index) {
440 ValidateItem(item);
441 items_.insert(items_.begin() + index, item);
442 MenuItemsChanged();
445 void SimpleMenuModel::ValidateItem(const Item& item) {
446 #ifndef NDEBUG
447 if (item.type == TYPE_SEPARATOR) {
448 DCHECK_EQ(item.command_id, kSeparatorId);
449 } else {
450 DCHECK_GE(item.command_id, 0);
452 #endif // NDEBUG
455 } // namespace ui