1 // Copyright 2013 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 CHROME_BROWSER_UI_VIEWS_TOOLBAR_APP_MENU_H_ 6 #define CHROME_BROWSER_UI_VIEWS_TOOLBAR_APP_MENU_H_ 7 8 #include <map> 9 #include <memory> 10 #include <utility> 11 12 #include "base/memory/weak_ptr.h" 13 #include "base/scoped_observer.h" 14 #include "base/time/time.h" 15 #include "base/timer/elapsed_timer.h" 16 #include "chrome/browser/ui/global_error/global_error_observer.h" 17 #include "chrome/browser/ui/global_error/global_error_service.h" 18 #include "components/bookmarks/browser/base_bookmark_model_observer.h" 19 #include "ui/base/models/menu_model.h" 20 #include "ui/views/controls/menu/menu_delegate.h" 21 22 class BookmarkMenuDelegate; 23 class Browser; 24 class ExtensionToolbarMenuView; 25 26 namespace views { 27 class MenuButtonController; 28 class MenuItemView; 29 class MenuRunner; 30 } 31 32 // AppMenu adapts the AppMenuModel to view's menu related classes. 33 class AppMenu : public views::MenuDelegate, 34 public bookmarks::BaseBookmarkModelObserver, 35 public GlobalErrorObserver, 36 public base::SupportsWeakPtr<AppMenu> { 37 public: 38 AppMenu(Browser* browser, int run_types, bool alert_reopen_tab_items); 39 AppMenu(const AppMenu&) = delete; 40 AppMenu& operator=(const AppMenu&) = delete; 41 ~AppMenu() override; 42 43 void Init(ui::MenuModel* model); 44 45 // Shows the menu relative to the specified controller's button. 46 void RunMenu(views::MenuButtonController* host); 47 48 // Closes the menu if it is open, otherwise does nothing. 49 void CloseMenu(); 50 51 // Whether the menu is currently visible to the user. 52 bool IsShowing() const; 53 for_drop()54 bool for_drop() const { 55 return (run_types_ & views::MenuRunner::FOR_DROP) != 0; 56 } 57 root_menu_item()58 views::MenuItemView* root_menu_item() { return root_; } 59 60 // MenuDelegate overrides: 61 void GetLabelStyle(int command_id, LabelStyle* style) const override; 62 base::string16 GetTooltipText(int command_id, 63 const gfx::Point& p) const override; 64 bool IsTriggerableEvent(views::MenuItemView* menu, 65 const ui::Event& e) override; 66 bool GetDropFormats(views::MenuItemView* menu, 67 int* formats, 68 std::set<ui::ClipboardFormatType>* format_types) override; 69 bool AreDropTypesRequired(views::MenuItemView* menu) override; 70 bool CanDrop(views::MenuItemView* menu, 71 const ui::OSExchangeData& data) override; 72 int GetDropOperation(views::MenuItemView* item, 73 const ui::DropTargetEvent& event, 74 DropPosition* position) override; 75 int OnPerformDrop(views::MenuItemView* menu, 76 DropPosition position, 77 const ui::DropTargetEvent& event) override; 78 bool ShowContextMenu(views::MenuItemView* source, 79 int command_id, 80 const gfx::Point& p, 81 ui::MenuSourceType source_type) override; 82 bool CanDrag(views::MenuItemView* menu) override; 83 void WriteDragData(views::MenuItemView* sender, 84 ui::OSExchangeData* data) override; 85 int GetDragOperations(views::MenuItemView* sender) override; 86 int GetMaxWidthForMenu(views::MenuItemView* menu) override; 87 bool IsItemChecked(int command_id) const override; 88 bool IsCommandEnabled(int command_id) const override; 89 void ExecuteCommand(int command_id, int mouse_event_flags) override; 90 bool GetAccelerator(int command_id, 91 ui::Accelerator* accelerator) const override; 92 void WillShowMenu(views::MenuItemView* menu) override; 93 void WillHideMenu(views::MenuItemView* menu) override; 94 bool ShouldCloseOnDragComplete() override; 95 void OnMenuClosed(views::MenuItemView* menu) override; 96 bool ShouldExecuteCommandWithoutClosingMenu(int command_id, 97 const ui::Event& event) override; 98 99 // bookmarks::BaseBookmarkModelObserver overrides: 100 void BookmarkModelChanged() override; 101 102 // GlobalErrorObserver: 103 void OnGlobalErrorsChanged() override; 104 extension_toolbar_for_testing()105 ExtensionToolbarMenuView* extension_toolbar_for_testing() { 106 return extension_toolbar_; 107 } 108 109 private: 110 class CutCopyPasteView; 111 class RecentTabsMenuModelDelegate; 112 class ZoomView; 113 114 typedef std::pair<ui::MenuModel*,int> Entry; 115 typedef std::map<int,Entry> CommandIDToEntry; 116 117 // Populates |parent| with all the child menus in |model|. Recursively invokes 118 // |PopulateMenu| for any submenu. 119 void PopulateMenu(views::MenuItemView* parent, 120 ui::MenuModel* model); 121 122 // Adds a new menu item to |parent| at |menu_index| to represent the item in 123 // |model| at |model_index|: 124 // - |menu_index|: position in |parent| to add the new item. 125 // - |model_index|: position in |model| to retrieve information about the 126 // new menu item. 127 // The returned item's MenuItemView::GetCommand() is the same as that of 128 // |model|->GetCommandIdAt(|model_index|). 129 views::MenuItemView* AddMenuItem(views::MenuItemView* parent, 130 int menu_index, 131 ui::MenuModel* model, 132 int model_index, 133 ui::MenuModel::ItemType menu_type); 134 135 // Invoked from the cut/copy/paste menus. Cancels the current active menu and 136 // activates the menu item in |model| at |index|. 137 void CancelAndEvaluate(ui::ButtonMenuItemModel* model, int index); 138 139 // Creates the bookmark menu if necessary. Does nothing if already created or 140 // the bookmark model isn't loaded. 141 void CreateBookmarkMenu(); 142 143 // Returns the index of the MenuModel/index pair representing the |command_id| 144 // in |command_id_to_entry_|. 145 int ModelIndexFromCommandId(int command_id) const; 146 147 // The views menu. Owned by |menu_runner_|. 148 views::MenuItemView* root_ = nullptr; 149 150 std::unique_ptr<views::MenuRunner> menu_runner_; 151 152 // Maps from the command ID in model to the model/index pair the item came 153 // from. 154 CommandIDToEntry command_id_to_entry_; 155 156 // Browser the menu is being shown for. 157 Browser* const browser_; 158 159 // |CancelAndEvaluate| sets |selected_menu_model_| and |selected_index_|. 160 // If |selected_menu_model_| is non-null after the menu completes 161 // ActivatedAt is invoked. This is done so that ActivatedAt isn't invoked 162 // while the message loop is nested. 163 ui::ButtonMenuItemModel* selected_menu_model_ = nullptr; 164 int selected_index_ = 0; 165 166 // Used for managing the bookmark menu items. 167 std::unique_ptr<BookmarkMenuDelegate> bookmark_menu_delegate_; 168 169 // Menu corresponding to IDC_BOOKMARKS_MENU. 170 views::MenuItemView* bookmark_menu_ = nullptr; 171 172 // Menu corresponding to IDC_FEEDBACK. 173 views::MenuItemView* feedback_menu_item_ = nullptr; 174 175 // Menu corresponding to IDC_TAKE_SCREENSHOT. 176 views::MenuItemView* screenshot_menu_item_ = nullptr; 177 178 // The view within the IDC_EXTENSIONS_OVERFLOW_MENU item (only present with 179 // the toolbar action redesign enabled). 180 ExtensionToolbarMenuView* extension_toolbar_ = nullptr; 181 182 // Used for managing "Recent tabs" menu items. 183 std::unique_ptr<RecentTabsMenuModelDelegate> recent_tabs_menu_model_delegate_; 184 185 ScopedObserver<GlobalErrorService, GlobalErrorObserver> 186 global_error_observer_{this}; 187 188 // The bit mask of views::MenuRunner::RunTypes. 189 const int run_types_; 190 191 // Whether to show items relating to reopening the last-closed tab as alerted. 192 const bool alert_reopen_tab_items_; 193 194 // Records the time from when menu opens to when the user selects a menu item. 195 base::ElapsedTimer menu_opened_timer_; 196 }; 197 198 #endif // CHROME_BROWSER_UI_VIEWS_TOOLBAR_APP_MENU_H_ 199