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/views/controls/menu/menu_model_adapter.h"
7 #include "base/logging.h"
8 #include "ui/base/l10n/l10n_util.h"
9 #include "ui/base/models/menu_model.h"
10 #include "ui/gfx/image/image.h"
11 #include "ui/views/controls/menu/menu_item_view.h"
12 #include "ui/views/controls/menu/submenu_view.h"
13 #include "ui/views/views_delegate.h"
17 MenuModelAdapter::MenuModelAdapter(ui::MenuModel
* menu_model
)
18 : menu_model_(menu_model
),
19 triggerable_event_flags_(ui::EF_LEFT_MOUSE_BUTTON
|
20 ui::EF_RIGHT_MOUSE_BUTTON
) {
24 MenuModelAdapter::~MenuModelAdapter() {
27 void MenuModelAdapter::BuildMenu(MenuItemView
* menu
) {
31 if (menu
->HasSubmenu()) {
32 const int subitem_count
= menu
->GetSubmenu()->child_count();
33 for (int i
= 0; i
< subitem_count
; ++i
)
34 menu
->RemoveMenuItemAt(0);
37 // Leave entries in the map if the menu is being shown. This
38 // allows the map to find the menu model of submenus being closed
39 // so ui::MenuModel::MenuClosed() can be called.
40 if (!menu
->GetMenuController())
42 menu_map_
[menu
] = menu_model_
;
44 // Repopulate the menu.
45 BuildMenuImpl(menu
, menu_model_
);
46 menu
->ChildrenChanged();
49 MenuItemView
* MenuModelAdapter::CreateMenu() {
50 MenuItemView
* item
= new MenuItemView(this);
56 MenuItemView
* MenuModelAdapter::AddMenuItemFromModelAt(ui::MenuModel
* model
,
62 model
->GetIconAt(model_index
, &icon
);
63 base::string16 label
, sublabel
, minor_text
;
64 ui::MenuSeparatorType separator_style
= ui::NORMAL_SEPARATOR
;
65 MenuItemView::Type type
;
66 ui::MenuModel::ItemType menu_type
= model
->GetTypeAt(model_index
);
69 case ui::MenuModel::TYPE_COMMAND
:
70 type
= MenuItemView::NORMAL
;
71 label
= model
->GetLabelAt(model_index
);
72 sublabel
= model
->GetSublabelAt(model_index
);
73 minor_text
= model
->GetMinorTextAt(model_index
);
75 case ui::MenuModel::TYPE_CHECK
:
76 type
= MenuItemView::CHECKBOX
;
77 label
= model
->GetLabelAt(model_index
);
78 sublabel
= model
->GetSublabelAt(model_index
);
79 minor_text
= model
->GetMinorTextAt(model_index
);
81 case ui::MenuModel::TYPE_RADIO
:
82 type
= MenuItemView::RADIO
;
83 label
= model
->GetLabelAt(model_index
);
84 sublabel
= model
->GetSublabelAt(model_index
);
85 minor_text
= model
->GetMinorTextAt(model_index
);
87 case ui::MenuModel::TYPE_SEPARATOR
:
89 type
= MenuItemView::SEPARATOR
;
90 separator_style
= model
->GetSeparatorTypeAt(model_index
);
92 case ui::MenuModel::TYPE_SUBMENU
:
93 type
= MenuItemView::SUBMENU
;
94 label
= model
->GetLabelAt(model_index
);
95 sublabel
= model
->GetSublabelAt(model_index
);
96 minor_text
= model
->GetMinorTextAt(model_index
);
100 type
= MenuItemView::NORMAL
;
104 return menu
->AddMenuItemAt(
110 icon
.IsEmpty() ? gfx::ImageSkia() : *icon
.ToImageSkia(),
116 MenuItemView
* MenuModelAdapter::AppendMenuItemFromModel(ui::MenuModel
* model
,
120 const int menu_index
= menu
->HasSubmenu() ?
121 menu
->GetSubmenu()->child_count() : 0;
122 return AddMenuItemFromModelAt(model
, model_index
, menu
, menu_index
, item_id
);
126 MenuItemView
* MenuModelAdapter::AppendMenuItem(MenuItemView
* menu
,
127 ui::MenuModel
* model
,
129 return AppendMenuItemFromModel(model
, index
, menu
,
130 model
->GetCommandIdAt(index
));
133 // MenuModelAdapter, MenuDelegate implementation:
135 void MenuModelAdapter::ExecuteCommand(int id
) {
136 ui::MenuModel
* model
= menu_model_
;
138 if (ui::MenuModel::GetModelAndIndexForCommandId(id
, &model
, &index
)) {
139 model
->ActivatedAt(index
);
146 void MenuModelAdapter::ExecuteCommand(int id
, int mouse_event_flags
) {
147 ui::MenuModel
* model
= menu_model_
;
149 if (ui::MenuModel::GetModelAndIndexForCommandId(id
, &model
, &index
)) {
150 model
->ActivatedAt(index
, mouse_event_flags
);
157 bool MenuModelAdapter::IsTriggerableEvent(MenuItemView
* source
,
158 const ui::Event
& e
) {
159 return e
.type() == ui::ET_GESTURE_TAP
||
160 e
.type() == ui::ET_GESTURE_TAP_DOWN
||
161 (e
.IsMouseEvent() && (triggerable_event_flags_
& e
.flags()) != 0);
164 bool MenuModelAdapter::GetAccelerator(int id
,
165 ui::Accelerator
* accelerator
) const {
166 ui::MenuModel
* model
= menu_model_
;
168 if (ui::MenuModel::GetModelAndIndexForCommandId(id
, &model
, &index
))
169 return model
->GetAcceleratorAt(index
, accelerator
);
175 base::string16
MenuModelAdapter::GetLabel(int id
) const {
176 ui::MenuModel
* model
= menu_model_
;
178 if (ui::MenuModel::GetModelAndIndexForCommandId(id
, &model
, &index
))
179 return model
->GetLabelAt(index
);
182 return base::string16();
185 const gfx::FontList
* MenuModelAdapter::GetLabelFontList(int id
) const {
186 ui::MenuModel
* model
= menu_model_
;
188 if (ui::MenuModel::GetModelAndIndexForCommandId(id
, &model
, &index
)) {
189 const gfx::FontList
* font_list
= model
->GetLabelFontListAt(index
);
194 // This line may be reached for the empty menu item.
195 return MenuDelegate::GetLabelFontList(id
);
198 bool MenuModelAdapter::IsCommandEnabled(int id
) const {
199 ui::MenuModel
* model
= menu_model_
;
201 if (ui::MenuModel::GetModelAndIndexForCommandId(id
, &model
, &index
))
202 return model
->IsEnabledAt(index
);
208 bool MenuModelAdapter::IsItemChecked(int id
) const {
209 ui::MenuModel
* model
= menu_model_
;
211 if (ui::MenuModel::GetModelAndIndexForCommandId(id
, &model
, &index
))
212 return model
->IsItemCheckedAt(index
);
218 void MenuModelAdapter::SelectionChanged(MenuItemView
* menu
) {
219 // Ignore selection of the root menu.
220 if (menu
== menu
->GetRootMenuItem())
223 const int id
= menu
->GetCommand();
224 ui::MenuModel
* model
= menu_model_
;
226 if (ui::MenuModel::GetModelAndIndexForCommandId(id
, &model
, &index
)) {
227 model
->HighlightChangedTo(index
);
234 void MenuModelAdapter::WillShowMenu(MenuItemView
* menu
) {
235 // Look up the menu model for this menu.
236 const std::map
<MenuItemView
*, ui::MenuModel
*>::const_iterator map_iterator
=
237 menu_map_
.find(menu
);
238 if (map_iterator
!= menu_map_
.end()) {
239 map_iterator
->second
->MenuWillShow();
246 void MenuModelAdapter::WillHideMenu(MenuItemView
* menu
) {
247 // Look up the menu model for this menu.
248 const std::map
<MenuItemView
*, ui::MenuModel
*>::const_iterator map_iterator
=
249 menu_map_
.find(menu
);
250 if (map_iterator
!= menu_map_
.end()) {
251 map_iterator
->second
->MenuClosed();
258 // MenuModelAdapter, private:
260 void MenuModelAdapter::BuildMenuImpl(MenuItemView
* menu
, ui::MenuModel
* model
) {
263 bool has_icons
= model
->HasIcons();
264 const int item_count
= model
->GetItemCount();
265 for (int i
= 0; i
< item_count
; ++i
) {
266 MenuItemView
* item
= AppendMenuItem(menu
, model
, i
);
269 item
->SetVisible(model
->IsVisibleAt(i
));
271 if (model
->GetTypeAt(i
) == ui::MenuModel::TYPE_SUBMENU
) {
273 DCHECK_EQ(MenuItemView::SUBMENU
, item
->GetType());
274 ui::MenuModel
* submodel
= model
->GetSubmenuModelAt(i
);
276 BuildMenuImpl(item
, submodel
);
277 has_icons
= has_icons
|| item
->has_icons();
279 menu_map_
[item
] = submodel
;
283 menu
->set_has_icons(has_icons
);