| OLD | NEW |
| (Empty) |
| 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 #include "ui/views/controls/menu/menu_model_adapter.h" | |
| 6 | |
| 7 #include "base/logging.h" | |
| 8 #include "ui/base/models/menu_model.h" | |
| 9 #include "ui/gfx/image/image.h" | |
| 10 #include "ui/views/controls/menu/menu_item_view.h" | |
| 11 #include "ui/views/controls/menu/submenu_view.h" | |
| 12 #include "ui/views/views_delegate.h" | |
| 13 | |
| 14 namespace views { | |
| 15 | |
| 16 MenuModelAdapter::MenuModelAdapter(ui::MenuModel* menu_model) | |
| 17 : menu_model_(menu_model), | |
| 18 triggerable_event_flags_(ui::EF_LEFT_MOUSE_BUTTON | | |
| 19 ui::EF_RIGHT_MOUSE_BUTTON) { | |
| 20 DCHECK(menu_model); | |
| 21 } | |
| 22 | |
| 23 MenuModelAdapter::~MenuModelAdapter() { | |
| 24 } | |
| 25 | |
| 26 void MenuModelAdapter::BuildMenu(MenuItemView* menu) { | |
| 27 DCHECK(menu); | |
| 28 | |
| 29 // Clear the menu. | |
| 30 if (menu->HasSubmenu()) { | |
| 31 const int subitem_count = menu->GetSubmenu()->child_count(); | |
| 32 for (int i = 0; i < subitem_count; ++i) | |
| 33 menu->RemoveMenuItemAt(0); | |
| 34 } | |
| 35 | |
| 36 // Leave entries in the map if the menu is being shown. This | |
| 37 // allows the map to find the menu model of submenus being closed | |
| 38 // so ui::MenuModel::MenuClosed() can be called. | |
| 39 if (!menu->GetMenuController()) | |
| 40 menu_map_.clear(); | |
| 41 menu_map_[menu] = menu_model_; | |
| 42 | |
| 43 // Repopulate the menu. | |
| 44 BuildMenuImpl(menu, menu_model_); | |
| 45 menu->ChildrenChanged(); | |
| 46 } | |
| 47 | |
| 48 MenuItemView* MenuModelAdapter::CreateMenu() { | |
| 49 MenuItemView* item = new MenuItemView(this); | |
| 50 BuildMenu(item); | |
| 51 return item; | |
| 52 } | |
| 53 | |
| 54 // Static. | |
| 55 MenuItemView* MenuModelAdapter::AddMenuItemFromModelAt(ui::MenuModel* model, | |
| 56 int model_index, | |
| 57 MenuItemView* menu, | |
| 58 int menu_index, | |
| 59 int item_id) { | |
| 60 gfx::Image icon; | |
| 61 model->GetIconAt(model_index, &icon); | |
| 62 base::string16 label, sublabel, minor_text; | |
| 63 ui::MenuSeparatorType separator_style = ui::NORMAL_SEPARATOR; | |
| 64 MenuItemView::Type type; | |
| 65 ui::MenuModel::ItemType menu_type = model->GetTypeAt(model_index); | |
| 66 | |
| 67 switch (menu_type) { | |
| 68 case ui::MenuModel::TYPE_COMMAND: | |
| 69 type = MenuItemView::NORMAL; | |
| 70 label = model->GetLabelAt(model_index); | |
| 71 sublabel = model->GetSublabelAt(model_index); | |
| 72 minor_text = model->GetMinorTextAt(model_index); | |
| 73 break; | |
| 74 case ui::MenuModel::TYPE_CHECK: | |
| 75 type = MenuItemView::CHECKBOX; | |
| 76 label = model->GetLabelAt(model_index); | |
| 77 sublabel = model->GetSublabelAt(model_index); | |
| 78 minor_text = model->GetMinorTextAt(model_index); | |
| 79 break; | |
| 80 case ui::MenuModel::TYPE_RADIO: | |
| 81 type = MenuItemView::RADIO; | |
| 82 label = model->GetLabelAt(model_index); | |
| 83 sublabel = model->GetSublabelAt(model_index); | |
| 84 minor_text = model->GetMinorTextAt(model_index); | |
| 85 break; | |
| 86 case ui::MenuModel::TYPE_SEPARATOR: | |
| 87 icon = gfx::Image(); | |
| 88 type = MenuItemView::SEPARATOR; | |
| 89 separator_style = model->GetSeparatorTypeAt(model_index); | |
| 90 break; | |
| 91 case ui::MenuModel::TYPE_SUBMENU: | |
| 92 type = MenuItemView::SUBMENU; | |
| 93 label = model->GetLabelAt(model_index); | |
| 94 sublabel = model->GetSublabelAt(model_index); | |
| 95 minor_text = model->GetMinorTextAt(model_index); | |
| 96 break; | |
| 97 default: | |
| 98 NOTREACHED(); | |
| 99 type = MenuItemView::NORMAL; | |
| 100 break; | |
| 101 } | |
| 102 | |
| 103 return menu->AddMenuItemAt( | |
| 104 menu_index, | |
| 105 item_id, | |
| 106 label, | |
| 107 sublabel, | |
| 108 minor_text, | |
| 109 icon.IsEmpty() ? gfx::ImageSkia() : *icon.ToImageSkia(), | |
| 110 type, | |
| 111 separator_style); | |
| 112 } | |
| 113 | |
| 114 // Static. | |
| 115 MenuItemView* MenuModelAdapter::AppendMenuItemFromModel(ui::MenuModel* model, | |
| 116 int model_index, | |
| 117 MenuItemView* menu, | |
| 118 int item_id) { | |
| 119 const int menu_index = menu->HasSubmenu() ? | |
| 120 menu->GetSubmenu()->child_count() : 0; | |
| 121 return AddMenuItemFromModelAt(model, model_index, menu, menu_index, item_id); | |
| 122 } | |
| 123 | |
| 124 | |
| 125 MenuItemView* MenuModelAdapter::AppendMenuItem(MenuItemView* menu, | |
| 126 ui::MenuModel* model, | |
| 127 int index) { | |
| 128 return AppendMenuItemFromModel(model, index, menu, | |
| 129 model->GetCommandIdAt(index)); | |
| 130 } | |
| 131 | |
| 132 // MenuModelAdapter, MenuDelegate implementation: | |
| 133 | |
| 134 void MenuModelAdapter::ExecuteCommand(int id) { | |
| 135 ui::MenuModel* model = menu_model_; | |
| 136 int index = 0; | |
| 137 if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) { | |
| 138 model->ActivatedAt(index); | |
| 139 return; | |
| 140 } | |
| 141 | |
| 142 NOTREACHED(); | |
| 143 } | |
| 144 | |
| 145 void MenuModelAdapter::ExecuteCommand(int id, int mouse_event_flags) { | |
| 146 ui::MenuModel* model = menu_model_; | |
| 147 int index = 0; | |
| 148 if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) { | |
| 149 model->ActivatedAt(index, mouse_event_flags); | |
| 150 return; | |
| 151 } | |
| 152 | |
| 153 NOTREACHED(); | |
| 154 } | |
| 155 | |
| 156 bool MenuModelAdapter::IsTriggerableEvent(MenuItemView* source, | |
| 157 const ui::Event& e) { | |
| 158 return e.type() == ui::ET_GESTURE_TAP || | |
| 159 e.type() == ui::ET_GESTURE_TAP_DOWN || | |
| 160 (e.IsMouseEvent() && (triggerable_event_flags_ & e.flags()) != 0); | |
| 161 } | |
| 162 | |
| 163 bool MenuModelAdapter::GetAccelerator(int id, | |
| 164 ui::Accelerator* accelerator) const { | |
| 165 ui::MenuModel* model = menu_model_; | |
| 166 int index = 0; | |
| 167 if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) | |
| 168 return model->GetAcceleratorAt(index, accelerator); | |
| 169 | |
| 170 NOTREACHED(); | |
| 171 return false; | |
| 172 } | |
| 173 | |
| 174 base::string16 MenuModelAdapter::GetLabel(int id) const { | |
| 175 ui::MenuModel* model = menu_model_; | |
| 176 int index = 0; | |
| 177 if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) | |
| 178 return model->GetLabelAt(index); | |
| 179 | |
| 180 NOTREACHED(); | |
| 181 return base::string16(); | |
| 182 } | |
| 183 | |
| 184 const gfx::FontList* MenuModelAdapter::GetLabelFontList(int id) const { | |
| 185 ui::MenuModel* model = menu_model_; | |
| 186 int index = 0; | |
| 187 if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) { | |
| 188 const gfx::FontList* font_list = model->GetLabelFontListAt(index); | |
| 189 if (font_list) | |
| 190 return font_list; | |
| 191 } | |
| 192 | |
| 193 // This line may be reached for the empty menu item. | |
| 194 return MenuDelegate::GetLabelFontList(id); | |
| 195 } | |
| 196 | |
| 197 bool MenuModelAdapter::IsCommandEnabled(int id) const { | |
| 198 ui::MenuModel* model = menu_model_; | |
| 199 int index = 0; | |
| 200 if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) | |
| 201 return model->IsEnabledAt(index); | |
| 202 | |
| 203 NOTREACHED(); | |
| 204 return false; | |
| 205 } | |
| 206 | |
| 207 bool MenuModelAdapter::IsCommandVisible(int id) const { | |
| 208 ui::MenuModel* model = menu_model_; | |
| 209 int index = 0; | |
| 210 if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) | |
| 211 return model->IsVisibleAt(index); | |
| 212 | |
| 213 NOTREACHED(); | |
| 214 return false; | |
| 215 } | |
| 216 | |
| 217 bool MenuModelAdapter::IsItemChecked(int id) const { | |
| 218 ui::MenuModel* model = menu_model_; | |
| 219 int index = 0; | |
| 220 if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) | |
| 221 return model->IsItemCheckedAt(index); | |
| 222 | |
| 223 NOTREACHED(); | |
| 224 return false; | |
| 225 } | |
| 226 | |
| 227 void MenuModelAdapter::SelectionChanged(MenuItemView* menu) { | |
| 228 // Ignore selection of the root menu. | |
| 229 if (menu == menu->GetRootMenuItem()) | |
| 230 return; | |
| 231 | |
| 232 const int id = menu->GetCommand(); | |
| 233 ui::MenuModel* model = menu_model_; | |
| 234 int index = 0; | |
| 235 if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) { | |
| 236 model->HighlightChangedTo(index); | |
| 237 return; | |
| 238 } | |
| 239 | |
| 240 NOTREACHED(); | |
| 241 } | |
| 242 | |
| 243 void MenuModelAdapter::WillShowMenu(MenuItemView* menu) { | |
| 244 // Look up the menu model for this menu. | |
| 245 const std::map<MenuItemView*, ui::MenuModel*>::const_iterator map_iterator = | |
| 246 menu_map_.find(menu); | |
| 247 if (map_iterator != menu_map_.end()) { | |
| 248 map_iterator->second->MenuWillShow(); | |
| 249 return; | |
| 250 } | |
| 251 | |
| 252 NOTREACHED(); | |
| 253 } | |
| 254 | |
| 255 void MenuModelAdapter::WillHideMenu(MenuItemView* menu) { | |
| 256 // Look up the menu model for this menu. | |
| 257 const std::map<MenuItemView*, ui::MenuModel*>::const_iterator map_iterator = | |
| 258 menu_map_.find(menu); | |
| 259 if (map_iterator != menu_map_.end()) { | |
| 260 map_iterator->second->MenuClosed(); | |
| 261 return; | |
| 262 } | |
| 263 | |
| 264 NOTREACHED(); | |
| 265 } | |
| 266 | |
| 267 // MenuModelAdapter, private: | |
| 268 | |
| 269 void MenuModelAdapter::BuildMenuImpl(MenuItemView* menu, ui::MenuModel* model) { | |
| 270 DCHECK(menu); | |
| 271 DCHECK(model); | |
| 272 bool has_icons = model->HasIcons(); | |
| 273 const int item_count = model->GetItemCount(); | |
| 274 for (int i = 0; i < item_count; ++i) { | |
| 275 MenuItemView* item = AppendMenuItem(menu, model, i); | |
| 276 | |
| 277 if (model->GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU) { | |
| 278 DCHECK(item); | |
| 279 DCHECK_EQ(MenuItemView::SUBMENU, item->GetType()); | |
| 280 ui::MenuModel* submodel = model->GetSubmenuModelAt(i); | |
| 281 DCHECK(submodel); | |
| 282 BuildMenuImpl(item, submodel); | |
| 283 has_icons = has_icons || item->has_icons(); | |
| 284 | |
| 285 menu_map_[item] = submodel; | |
| 286 } | |
| 287 } | |
| 288 | |
| 289 menu->set_has_icons(has_icons); | |
| 290 } | |
| 291 | |
| 292 } // namespace views | |
| OLD | NEW |