1 // Copyright (c) 2011 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 // C++ controller for the bookmark menu; one per AppController (which 6 // means there is only one). When bookmarks are changed, this class 7 // takes care of updating Cocoa bookmark menus. This is not named 8 // BookmarkMenuController to help avoid confusion between languages. 9 // This class needs to be C++, not ObjC, since it derives from 10 // BookmarkModelObserver. 11 // 12 // Most Chromium Cocoa menu items are static from a nib (e.g. New 13 // Tab), but may be enabled/disabled under certain circumstances 14 // (e.g. Cut and Paste). In addition, most Cocoa menu items have 15 // firstResponder: as a target. Unusually, bookmark menu items are 16 // created dynamically. They also have a target of 17 // BookmarkMenuCocoaController instead of firstResponder. 18 // See BookmarkMenuBridge::AddNodeToMenu()). 19 20 #ifndef CHROME_BROWSER_UI_COCOA_BOOKMARKS_BOOKMARK_MENU_BRIDGE_H_ 21 #define CHROME_BROWSER_UI_COCOA_BOOKMARKS_BOOKMARK_MENU_BRIDGE_H_ 22 23 #include <map> 24 25 #include "base/mac/scoped_nsobject.h" 26 #import "chrome/browser/ui/cocoa/main_menu_item.h" 27 #include "components/bookmarks/browser/bookmark_model_observer.h" 28 29 class BookmarkNode; 30 class Profile; 31 @class NSImage; 32 @class NSMenu; 33 @class NSMenuItem; 34 @class BookmarkMenuCocoaController; 35 36 class BookmarkMenuBridge : public BookmarkModelObserver, 37 public MainMenuItem { 38 public: 39 BookmarkMenuBridge(Profile* profile, NSMenu* menu); 40 virtual ~BookmarkMenuBridge(); 41 42 // BookmarkModelObserver: 43 virtual void BookmarkModelLoaded(BookmarkModel* model, 44 bool ids_reassigned) OVERRIDE; 45 virtual void BookmarkModelBeingDeleted(BookmarkModel* model) OVERRIDE; 46 virtual void BookmarkNodeMoved(BookmarkModel* model, 47 const BookmarkNode* old_parent, 48 int old_index, 49 const BookmarkNode* new_parent, 50 int new_index) OVERRIDE; 51 virtual void BookmarkNodeAdded(BookmarkModel* model, 52 const BookmarkNode* parent, 53 int index) OVERRIDE; 54 virtual void BookmarkNodeRemoved(BookmarkModel* model, 55 const BookmarkNode* parent, 56 int old_index, 57 const BookmarkNode* node, 58 const std::set<GURL>& removed_urls) OVERRIDE; 59 virtual void BookmarkAllUserNodesRemoved( 60 BookmarkModel* model, 61 const std::set<GURL>& removed_urls) OVERRIDE; 62 virtual void BookmarkNodeChanged(BookmarkModel* model, 63 const BookmarkNode* node) OVERRIDE; 64 virtual void BookmarkNodeFaviconChanged(BookmarkModel* model, 65 const BookmarkNode* node) OVERRIDE; 66 virtual void BookmarkNodeChildrenReordered(BookmarkModel* model, 67 const BookmarkNode* node) OVERRIDE; 68 69 // MainMenuItem: 70 virtual void ResetMenu() OVERRIDE; 71 virtual void BuildMenu() OVERRIDE; 72 73 // Rebuilds the main bookmark menu, if it has been marked invalid. 74 void UpdateMenu(NSMenu* bookmark_menu); 75 76 // Rebuilds a bookmark menu that's a submenu of another menu. 77 void UpdateSubMenu(NSMenu* bookmark_menu); 78 79 // I wish I had a "friend @class" construct. 80 BookmarkModel* GetBookmarkModel(); 81 Profile* GetProfile(); 82 83 protected: 84 // Rebuilds the bookmark content of supplied menu. 85 void UpdateMenuInternal(NSMenu* bookmark_menu, bool is_submenu); 86 87 // Clear all bookmarks from the given bookmark menu. 88 void ClearBookmarkMenu(NSMenu* menu); 89 90 // Mark the bookmark menu as being invalid. 91 void InvalidateMenu() { menuIsValid_ = false; } 92 93 // Helper for adding the node as a submenu to the menu with the |node|'s title 94 // and the given |image| as its icon. 95 // If |add_extra_items| is true, also adds extra menu items at bottom of 96 // menu, such as "Open All Bookmarks". 97 void AddNodeAsSubmenu(NSMenu* menu, 98 const BookmarkNode* node, 99 NSImage* image, 100 bool add_extra_items); 101 102 // Helper for recursively adding items to our bookmark menu. 103 // All children of |node| will be added to |menu|. 104 // If |add_extra_items| is true, also adds extra menu items at bottom of 105 // menu, such as "Open All Bookmarks". 106 // TODO(jrg): add a counter to enforce maximum nodes added 107 void AddNodeToMenu(const BookmarkNode* node, NSMenu* menu, 108 bool add_extra_items); 109 110 // Helper for adding an item to our bookmark menu. An item which has a 111 // localized title specified by |message_id| will be added to |menu|. 112 // The item is also bound to |node| by tag. |command_id| selects the action. 113 void AddItemToMenu(int command_id, 114 int message_id, 115 const BookmarkNode* node, 116 NSMenu* menu, 117 bool enabled); 118 119 // This configures an NSMenuItem with all the data from a BookmarkNode. This 120 // is used to update existing menu items, as well as to configure newly 121 // created ones, like in AddNodeToMenu(). 122 // |set_title| is optional since it is only needed when we get a 123 // node changed notification. On initial build of the menu we set 124 // the title as part of alloc/init. 125 void ConfigureMenuItem(const BookmarkNode* node, NSMenuItem* item, 126 bool set_title); 127 128 // Returns the NSMenuItem for a given BookmarkNode. 129 NSMenuItem* MenuItemForNode(const BookmarkNode* node); 130 131 // Return the Bookmark menu. 132 virtual NSMenu* BookmarkMenu(); 133 134 // Start watching the bookmarks for changes. 135 void ObserveBookmarkModel(); 136 137 private: 138 friend class BookmarkMenuBridgeTest; 139 140 // True iff the menu is up-to-date with the actual BookmarkModel. 141 bool menuIsValid_; 142 143 Profile* profile_; // weak 144 BookmarkMenuCocoaController* controller_; // strong 145 146 // The folder image so we can use one copy for all. 147 base::scoped_nsobject<NSImage> folder_image_; 148 149 // In order to appropriately update items in the bookmark menu, without 150 // forcing a rebuild, map the model's nodes to menu items. 151 std::map<const BookmarkNode*, NSMenuItem*> bookmark_nodes_; 152 }; 153 154 #endif // CHROME_BROWSER_UI_COCOA_BOOKMARKS_BOOKMARK_MENU_BRIDGE_H_ 155