| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/views/bookmarks/bookmark_menu_controller_views.h" | 5 #include "chrome/browser/ui/views/bookmarks/bookmark_menu_controller_views.h" |
| 6 | 6 |
| 7 #include "base/stl_util-inl.h" | 7 #include "base/stl_util-inl.h" |
| 8 #include "base/utf_string_conversions.h" | 8 #include "base/utf_string_conversions.h" |
| 9 #include "chrome/browser/bookmarks/bookmark_model.h" | 9 #include "chrome/browser/bookmarks/bookmark_model.h" |
| 10 #include "chrome/browser/bookmarks/bookmark_node_data.h" | 10 #include "chrome/browser/bookmarks/bookmark_node_data.h" |
| 11 #include "chrome/browser/bookmarks/bookmark_utils.h" | 11 #include "chrome/browser/bookmarks/bookmark_utils.h" |
| 12 #include "chrome/browser/prefs/pref_service.h" | 12 #include "chrome/browser/prefs/pref_service.h" |
| 13 #include "chrome/browser/profiles/profile.h" | 13 #include "chrome/browser/profiles/profile.h" |
| 14 #include "chrome/browser/ui/browser.h" | |
| 15 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h" | 14 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h" |
| 15 #include "chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h" |
| 16 #include "chrome/browser/ui/views/event_utils.h" | 16 #include "chrome/browser/ui/views/event_utils.h" |
| 17 #include "chrome/common/pref_names.h" | 17 #include "chrome/common/pref_names.h" |
| 18 #include "content/browser/tab_contents/page_navigator.h" | 18 #include "content/browser/tab_contents/page_navigator.h" |
| 19 #include "content/browser/user_metrics.h" | 19 #include "content/browser/user_metrics.h" |
| 20 #include "content/common/page_transition_types.h" | 20 #include "content/common/page_transition_types.h" |
| 21 #include "grit/app_resources.h" | 21 #include "grit/app_resources.h" |
| 22 #include "grit/generated_resources.h" | 22 #include "grit/generated_resources.h" |
| 23 #include "grit/theme_resources.h" | 23 #include "grit/theme_resources.h" |
| 24 #include "ui/base/dragdrop/os_exchange_data.h" | 24 #include "ui/base/dragdrop/os_exchange_data.h" |
| 25 #include "ui/base/resource/resource_bundle.h" | 25 #include "ui/base/resource/resource_bundle.h" |
| 26 #include "views/controls/button/menu_button.h" | 26 #include "views/controls/button/menu_button.h" |
| 27 | 27 |
| 28 using views::MenuItemView; | 28 using views::MenuItemView; |
| 29 | 29 |
| 30 // Max width of a menu. There does not appear to be an OS value for this, yet | 30 BookmarkMenuController::BookmarkMenuController(Profile* profile, |
| 31 // both IE and FF restrict the max width of a menu. | |
| 32 static const int kMaxMenuWidth = 400; | |
| 33 | |
| 34 BookmarkMenuController::BookmarkMenuController(Browser* browser, | |
| 35 Profile* profile, | |
| 36 PageNavigator* navigator, | 31 PageNavigator* navigator, |
| 37 gfx::NativeWindow parent, | 32 gfx::NativeWindow parent, |
| 38 const BookmarkNode* node, | 33 const BookmarkNode* node, |
| 39 int start_child_index) | 34 int start_child_index) |
| 40 : browser_(browser), | 35 : menu_delegate_(new BookmarkMenuDelegate(profile, navigator, parent, 1)), |
| 41 profile_(profile), | |
| 42 page_navigator_(navigator), | |
| 43 parent_(parent), | |
| 44 node_(node), | 36 node_(node), |
| 45 menu_(NULL), | |
| 46 observer_(NULL), | 37 observer_(NULL), |
| 47 for_drop_(false), | 38 for_drop_(false), |
| 48 bookmark_bar_(NULL), | 39 bookmark_bar_(NULL) { |
| 49 next_menu_id_(1) { | 40 menu_delegate_->Init(this, NULL, node, start_child_index, |
| 50 menu_ = CreateMenu(node, start_child_index); | 41 BookmarkMenuDelegate::HIDE_OTHER_FOLDER); |
| 51 } | 42 } |
| 52 | 43 |
| 53 void BookmarkMenuController::RunMenuAt(BookmarkBarView* bookmark_bar, | 44 void BookmarkMenuController::RunMenuAt(BookmarkBarView* bookmark_bar, |
| 54 bool for_drop) { | 45 bool for_drop) { |
| 55 bookmark_bar_ = bookmark_bar; | 46 bookmark_bar_ = bookmark_bar; |
| 56 views::MenuButton* menu_button = bookmark_bar_->GetMenuButtonForNode(node_); | 47 views::MenuButton* menu_button = bookmark_bar_->GetMenuButtonForNode(node_); |
| 57 DCHECK(menu_button); | 48 DCHECK(menu_button); |
| 58 MenuItemView::AnchorPosition anchor; | 49 MenuItemView::AnchorPosition anchor; |
| 59 int start_index; | 50 int start_index; |
| 60 bookmark_bar_->GetAnchorPositionAndStartIndexForButton( | 51 bookmark_bar_->GetAnchorPositionAndStartIndexForButton( |
| 61 menu_button, &anchor, &start_index); | 52 menu_button, &anchor, &start_index); |
| 62 RunMenuAt(menu_button, anchor, for_drop); | 53 RunMenuAt(menu_button, anchor, for_drop); |
| 63 } | 54 } |
| 64 | 55 |
| 65 void BookmarkMenuController::RunMenuAt( | 56 void BookmarkMenuController::RunMenuAt( |
| 66 views::MenuButton* button, | 57 views::MenuButton* button, |
| 67 MenuItemView::AnchorPosition position, | 58 MenuItemView::AnchorPosition position, |
| 68 bool for_drop) { | 59 bool for_drop) { |
| 69 gfx::Point screen_loc; | 60 gfx::Point screen_loc; |
| 70 views::View::ConvertPointToScreen(button, &screen_loc); | 61 views::View::ConvertPointToScreen(button, &screen_loc); |
| 71 // Subtract 1 from the height to make the popup flush with the button border. | 62 // Subtract 1 from the height to make the popup flush with the button border. |
| 72 gfx::Rect bounds(screen_loc.x(), screen_loc.y(), button->width(), | 63 gfx::Rect bounds(screen_loc.x(), screen_loc.y(), button->width(), |
| 73 button->height() - 1); | 64 button->height() - 1); |
| 74 for_drop_ = for_drop; | 65 for_drop_ = for_drop; |
| 75 profile_->GetBookmarkModel()->AddObserver(this); | 66 menu_delegate_->profile()->GetBookmarkModel()->AddObserver(this); |
| 76 // The constructor creates the initial menu and that is all we should have | |
| 77 // at this point. | |
| 78 DCHECK(node_to_menu_map_.size() == 1); | |
| 79 if (for_drop) { | 67 if (for_drop) { |
| 80 menu_->RunMenuForDropAt(parent_, bounds, position); | 68 menu()->RunMenuForDropAt(menu_delegate_->parent(), bounds, position); |
| 81 } else { | 69 } else { |
| 82 menu_->RunMenuAt(parent_, button, bounds, position, false); | 70 menu()->RunMenuAt(menu_delegate_->parent(), button, bounds, position, |
| 71 false); |
| 83 delete this; | 72 delete this; |
| 84 } | 73 } |
| 85 } | 74 } |
| 86 | 75 |
| 87 void BookmarkMenuController::Cancel() { | 76 void BookmarkMenuController::Cancel() { |
| 88 menu_->Cancel(); | 77 menu_delegate_->menu()->Cancel(); |
| 89 } | 78 } |
| 90 | 79 |
| 91 std::wstring BookmarkMenuController::GetTooltipText( | 80 MenuItemView* BookmarkMenuController::menu() const { |
| 92 int id, const gfx::Point& screen_loc) { | 81 return menu_delegate_->menu(); |
| 93 DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end()); | |
| 94 | |
| 95 const BookmarkNode* node = menu_id_to_node_map_[id]; | |
| 96 if (node->type() == BookmarkNode::URL) | |
| 97 return BookmarkBarView::CreateToolTipForURLAndTitle( | |
| 98 screen_loc, node->GetURL(), UTF16ToWide(node->GetTitle()), profile_); | |
| 99 return std::wstring(); | |
| 100 } | 82 } |
| 101 | 83 |
| 102 bool BookmarkMenuController::IsTriggerableEvent(MenuItemView* view, | 84 MenuItemView* BookmarkMenuController::context_menu() const { |
| 85 return menu_delegate_->context_menu(); |
| 86 } |
| 87 |
| 88 std::wstring BookmarkMenuController::GetTooltipText(int id, |
| 89 const gfx::Point& p) { |
| 90 return menu_delegate_->GetTooltipText(id, p); |
| 91 } |
| 92 |
| 93 bool BookmarkMenuController::IsTriggerableEvent(views::MenuItemView* menu, |
| 103 const views::MouseEvent& e) { | 94 const views::MouseEvent& e) { |
| 104 return event_utils::IsPossibleDispositionEvent(e); | 95 return menu_delegate_->IsTriggerableEvent(menu, e); |
| 105 } | 96 } |
| 106 | 97 |
| 107 void BookmarkMenuController::ExecuteCommand(int id, int mouse_event_flags) { | 98 void BookmarkMenuController::ExecuteCommand(int id, int mouse_event_flags) { |
| 108 DCHECK(page_navigator_); | 99 menu_delegate_->ExecuteCommand(id, mouse_event_flags); |
| 109 DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end()); | |
| 110 | |
| 111 const BookmarkNode* node = menu_id_to_node_map_[id]; | |
| 112 std::vector<const BookmarkNode*> selection; | |
| 113 selection.push_back(node); | |
| 114 | |
| 115 WindowOpenDisposition initial_disposition = | |
| 116 event_utils::DispositionFromEventFlags(mouse_event_flags); | |
| 117 | |
| 118 bookmark_utils::OpenAll(parent_, profile_, page_navigator_, selection, | |
| 119 initial_disposition); | |
| 120 } | 100 } |
| 121 | 101 |
| 122 bool BookmarkMenuController::GetDropFormats( | 102 bool BookmarkMenuController::GetDropFormats( |
| 123 MenuItemView* menu, | 103 MenuItemView* menu, |
| 124 int* formats, | 104 int* formats, |
| 125 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) { | 105 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) { |
| 126 *formats = ui::OSExchangeData::URL; | 106 return menu_delegate_->GetDropFormats(menu, formats, custom_formats); |
| 127 custom_formats->insert(BookmarkNodeData::GetBookmarkCustomFormat()); | |
| 128 return true; | |
| 129 } | 107 } |
| 130 | 108 |
| 131 bool BookmarkMenuController::AreDropTypesRequired(MenuItemView* menu) { | 109 bool BookmarkMenuController::AreDropTypesRequired(MenuItemView* menu) { |
| 132 return true; | 110 return menu_delegate_->AreDropTypesRequired(menu); |
| 133 } | 111 } |
| 134 | 112 |
| 135 bool BookmarkMenuController::CanDrop(MenuItemView* menu, | 113 bool BookmarkMenuController::CanDrop(MenuItemView* menu, |
| 136 const ui::OSExchangeData& data) { | 114 const ui::OSExchangeData& data) { |
| 137 // Only accept drops of 1 node, which is the case for all data dragged from | 115 return menu_delegate_->CanDrop(menu, data); |
| 138 // bookmark bar and menus. | |
| 139 | |
| 140 if (!drop_data_.Read(data) || drop_data_.elements.size() != 1 || | |
| 141 !profile_->GetPrefs()->GetBoolean(prefs::kEditBookmarksEnabled)) | |
| 142 return false; | |
| 143 | |
| 144 if (drop_data_.has_single_url()) | |
| 145 return true; | |
| 146 | |
| 147 const BookmarkNode* drag_node = drop_data_.GetFirstNode(profile_); | |
| 148 if (!drag_node) { | |
| 149 // Dragging a folder from another profile, always accept. | |
| 150 return true; | |
| 151 } | |
| 152 | |
| 153 // Drag originated from same profile and is not a URL. Only accept it if | |
| 154 // the dragged node is not a parent of the node menu represents. | |
| 155 const BookmarkNode* drop_node = menu_id_to_node_map_[menu->GetCommand()]; | |
| 156 DCHECK(drop_node); | |
| 157 while (drop_node && drop_node != drag_node) | |
| 158 drop_node = drop_node->parent(); | |
| 159 return (drop_node == NULL); | |
| 160 } | 116 } |
| 161 | 117 |
| 162 int BookmarkMenuController::GetDropOperation( | 118 int BookmarkMenuController::GetDropOperation( |
| 163 MenuItemView* item, | 119 MenuItemView* item, |
| 164 const views::DropTargetEvent& event, | 120 const views::DropTargetEvent& event, |
| 165 DropPosition* position) { | 121 DropPosition* position) { |
| 166 // Should only get here if we have drop data. | 122 return menu_delegate_->GetDropOperation(item, event, position); |
| 167 DCHECK(drop_data_.is_valid()); | |
| 168 | |
| 169 const BookmarkNode* node = menu_id_to_node_map_[item->GetCommand()]; | |
| 170 const BookmarkNode* drop_parent = node->parent(); | |
| 171 int index_to_drop_at = drop_parent->GetIndexOf(node); | |
| 172 if (*position == DROP_AFTER) { | |
| 173 index_to_drop_at++; | |
| 174 } else if (*position == DROP_ON) { | |
| 175 drop_parent = node; | |
| 176 index_to_drop_at = node->child_count(); | |
| 177 } | |
| 178 DCHECK(drop_parent); | |
| 179 return bookmark_utils::BookmarkDropOperation( | |
| 180 profile_, event, drop_data_, drop_parent, index_to_drop_at); | |
| 181 } | 123 } |
| 182 | 124 |
| 183 int BookmarkMenuController::OnPerformDrop(MenuItemView* menu, | 125 int BookmarkMenuController::OnPerformDrop(MenuItemView* menu, |
| 184 DropPosition position, | 126 DropPosition position, |
| 185 const views::DropTargetEvent& event) { | 127 const views::DropTargetEvent& event) { |
| 186 const BookmarkNode* drop_node = menu_id_to_node_map_[menu->GetCommand()]; | 128 int result = menu_delegate_->OnPerformDrop(menu, position, event); |
| 187 DCHECK(drop_node); | |
| 188 BookmarkModel* model = profile_->GetBookmarkModel(); | |
| 189 DCHECK(model); | |
| 190 const BookmarkNode* drop_parent = drop_node->parent(); | |
| 191 DCHECK(drop_parent); | |
| 192 int index_to_drop_at = drop_parent->GetIndexOf(drop_node); | |
| 193 if (position == DROP_AFTER) { | |
| 194 index_to_drop_at++; | |
| 195 } else if (position == DROP_ON) { | |
| 196 DCHECK(drop_node->is_folder()); | |
| 197 drop_parent = drop_node; | |
| 198 index_to_drop_at = drop_node->child_count(); | |
| 199 } | |
| 200 | |
| 201 int result = bookmark_utils::PerformBookmarkDrop( | |
| 202 profile_, drop_data_, drop_parent, index_to_drop_at); | |
| 203 if (for_drop_) | 129 if (for_drop_) |
| 204 delete this; | 130 delete this; |
| 205 return result; | 131 return result; |
| 206 } | 132 } |
| 207 | 133 |
| 208 bool BookmarkMenuController::ShowContextMenu(MenuItemView* source, | 134 bool BookmarkMenuController::ShowContextMenu(MenuItemView* source, |
| 209 int id, | 135 int id, |
| 210 const gfx::Point& p, | 136 const gfx::Point& p, |
| 211 bool is_mouse_gesture) { | 137 bool is_mouse_gesture) { |
| 212 DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end()); | 138 return menu_delegate_->ShowContextMenu(source, id, p, is_mouse_gesture); |
| 213 std::vector<const BookmarkNode*> nodes; | |
| 214 nodes.push_back(menu_id_to_node_map_[id]); | |
| 215 context_menu_.reset( | |
| 216 new BookmarkContextMenu( | |
| 217 parent_, | |
| 218 profile_, | |
| 219 page_navigator_, | |
| 220 nodes[0]->parent(), | |
| 221 nodes)); | |
| 222 context_menu_->set_observer(this); | |
| 223 context_menu_->RunMenuAt(p); | |
| 224 context_menu_.reset(NULL); | |
| 225 return true; | |
| 226 } | 139 } |
| 227 | 140 |
| 228 void BookmarkMenuController::DropMenuClosed(MenuItemView* menu) { | 141 void BookmarkMenuController::DropMenuClosed(MenuItemView* menu) { |
| 229 delete this; | 142 delete this; |
| 230 } | 143 } |
| 231 | 144 |
| 232 bool BookmarkMenuController::CanDrag(MenuItemView* menu) { | 145 bool BookmarkMenuController::CanDrag(MenuItemView* menu) { |
| 233 return true; | 146 return menu_delegate_->CanDrag(menu); |
| 234 } | 147 } |
| 235 | 148 |
| 236 void BookmarkMenuController::WriteDragData(MenuItemView* sender, | 149 void BookmarkMenuController::WriteDragData(MenuItemView* sender, |
| 237 ui::OSExchangeData* data) { | 150 ui::OSExchangeData* data) { |
| 238 DCHECK(sender && data); | 151 return menu_delegate_->WriteDragData(sender, data); |
| 239 | |
| 240 UserMetrics::RecordAction(UserMetricsAction("BookmarkBar_DragFromFolder")); | |
| 241 | |
| 242 BookmarkNodeData drag_data(menu_id_to_node_map_[sender->GetCommand()]); | |
| 243 drag_data.Write(profile_, data); | |
| 244 } | 152 } |
| 245 | 153 |
| 246 int BookmarkMenuController::GetDragOperations(MenuItemView* sender) { | 154 int BookmarkMenuController::GetDragOperations(MenuItemView* sender) { |
| 247 return bookmark_utils::BookmarkDragOperation(profile_, | 155 return menu_delegate_->GetDragOperations(sender); |
| 248 menu_id_to_node_map_[sender->GetCommand()]); | |
| 249 } | 156 } |
| 250 | 157 |
| 251 views::MenuItemView* BookmarkMenuController::GetSiblingMenu( | 158 views::MenuItemView* BookmarkMenuController::GetSiblingMenu( |
| 252 views::MenuItemView* menu, | 159 views::MenuItemView* menu, |
| 253 const gfx::Point& screen_point, | 160 const gfx::Point& screen_point, |
| 254 views::MenuItemView::AnchorPosition* anchor, | 161 views::MenuItemView::AnchorPosition* anchor, |
| 255 bool* has_mnemonics, | 162 bool* has_mnemonics, |
| 256 views::MenuButton** button) { | 163 views::MenuButton** button) { |
| 257 if (!bookmark_bar_ || for_drop_) | 164 if (!bookmark_bar_ || for_drop_) |
| 258 return NULL; | 165 return NULL; |
| 259 gfx::Point bookmark_bar_loc(screen_point); | 166 gfx::Point bookmark_bar_loc(screen_point); |
| 260 views::View::ConvertPointToView(NULL, bookmark_bar_, &bookmark_bar_loc); | 167 views::View::ConvertPointToView(NULL, bookmark_bar_, &bookmark_bar_loc); |
| 261 int start_index; | 168 int start_index; |
| 262 const BookmarkNode* node = | 169 const BookmarkNode* node = |
| 263 bookmark_bar_->GetNodeForButtonAt(bookmark_bar_loc, &start_index); | 170 bookmark_bar_->GetNodeForButtonAt(bookmark_bar_loc, &start_index); |
| 264 if (!node || !node->is_folder()) | 171 if (!node || !node->is_folder()) |
| 265 return NULL; | 172 return NULL; |
| 266 | 173 |
| 267 MenuItemView* alt_menu = node_to_menu_map_[node]; | 174 menu_delegate_->SetActiveMenu(node, start_index); |
| 268 if (!alt_menu) | |
| 269 alt_menu = CreateMenu(node, start_index); | |
| 270 | |
| 271 menu_ = alt_menu; | |
| 272 | |
| 273 *button = bookmark_bar_->GetMenuButtonForNode(node); | 175 *button = bookmark_bar_->GetMenuButtonForNode(node); |
| 274 bookmark_bar_->GetAnchorPositionAndStartIndexForButton( | 176 bookmark_bar_->GetAnchorPositionAndStartIndexForButton( |
| 275 *button, anchor, &start_index); | 177 *button, anchor, &start_index); |
| 276 *has_mnemonics = false; | 178 *has_mnemonics = false; |
| 277 return alt_menu; | 179 return this->menu(); |
| 278 } | 180 } |
| 279 | 181 |
| 280 int BookmarkMenuController::GetMaxWidthForMenu(MenuItemView* view) { | 182 int BookmarkMenuController::GetMaxWidthForMenu(MenuItemView* view) { |
| 281 return kMaxMenuWidth; | 183 return menu_delegate_->GetMaxWidthForMenu(view); |
| 282 } | 184 } |
| 283 | 185 |
| 284 void BookmarkMenuController::BookmarkModelChanged() { | 186 void BookmarkMenuController::BookmarkModelChanged() { |
| 285 menu_->Cancel(); | 187 if (!menu_delegate_->is_mutating_model()) |
| 286 } | 188 menu()->Cancel(); |
| 287 | |
| 288 void BookmarkMenuController::BookmarkNodeFaviconLoaded( | |
| 289 BookmarkModel* model, const BookmarkNode* node) { | |
| 290 NodeToMenuIDMap::iterator menu_pair = node_to_menu_id_map_.find(node); | |
| 291 if (menu_pair == node_to_menu_id_map_.end()) | |
| 292 return; // We're not showing a menu item for the node. | |
| 293 | |
| 294 // Iterate through the menus looking for the menu containing node. | |
| 295 for (NodeToMenuMap::iterator i = node_to_menu_map_.begin(); | |
| 296 i != node_to_menu_map_.end(); ++i) { | |
| 297 MenuItemView* menu_item = i->second->GetMenuItemByID(menu_pair->second); | |
| 298 if (menu_item) { | |
| 299 menu_item->SetIcon(model->GetFavicon(node)); | |
| 300 return; | |
| 301 } | |
| 302 } | |
| 303 } | |
| 304 | |
| 305 void BookmarkMenuController::WillRemoveBookmarks( | |
| 306 const std::vector<const BookmarkNode*>& bookmarks) { | |
| 307 std::set<MenuItemView*> removed_menus; | |
| 308 | |
| 309 WillRemoveBookmarksImpl(bookmarks, &removed_menus); | |
| 310 | |
| 311 STLDeleteElements(&removed_menus); | |
| 312 } | |
| 313 | |
| 314 void BookmarkMenuController::DidRemoveBookmarks() { | |
| 315 profile_->GetBookmarkModel()->AddObserver(this); | |
| 316 } | |
| 317 | |
| 318 MenuItemView* BookmarkMenuController::CreateMenu(const BookmarkNode* parent, | |
| 319 int start_child_index) { | |
| 320 MenuItemView* menu = new MenuItemView(this); | |
| 321 menu->SetCommand(next_menu_id_++); | |
| 322 menu_id_to_node_map_[menu->GetCommand()] = parent; | |
| 323 menu->set_has_icons(true); | |
| 324 BuildMenu(parent, start_child_index, menu, &next_menu_id_); | |
| 325 node_to_menu_map_[parent] = menu; | |
| 326 return menu; | |
| 327 } | |
| 328 | |
| 329 void BookmarkMenuController::BuildMenu(const BookmarkNode* parent, | |
| 330 int start_child_index, | |
| 331 MenuItemView* menu, | |
| 332 int* next_menu_id) { | |
| 333 DCHECK(!parent->child_count() || | |
| 334 start_child_index < parent->child_count()); | |
| 335 for (int i = start_child_index; i < parent->child_count(); ++i) { | |
| 336 const BookmarkNode* node = parent->GetChild(i); | |
| 337 int id = *next_menu_id; | |
| 338 | |
| 339 (*next_menu_id)++; | |
| 340 if (node->is_url()) { | |
| 341 SkBitmap icon = profile_->GetBookmarkModel()->GetFavicon(node); | |
| 342 if (icon.width() == 0) { | |
| 343 icon = *ResourceBundle::GetSharedInstance(). | |
| 344 GetBitmapNamed(IDR_DEFAULT_FAVICON); | |
| 345 } | |
| 346 menu->AppendMenuItemWithIcon(id, UTF16ToWide(node->GetTitle()), icon); | |
| 347 node_to_menu_id_map_[node] = id; | |
| 348 } else if (node->is_folder()) { | |
| 349 SkBitmap* folder_icon = ResourceBundle::GetSharedInstance(). | |
| 350 GetBitmapNamed(IDR_BOOKMARK_BAR_FOLDER); | |
| 351 MenuItemView* submenu = menu->AppendSubMenuWithIcon(id, | |
| 352 UTF16ToWide(node->GetTitle()), *folder_icon); | |
| 353 node_to_menu_id_map_[node] = id; | |
| 354 BuildMenu(node, 0, submenu, next_menu_id); | |
| 355 } else { | |
| 356 NOTREACHED(); | |
| 357 } | |
| 358 menu_id_to_node_map_[id] = node; | |
| 359 } | |
| 360 } | 189 } |
| 361 | 190 |
| 362 BookmarkMenuController::~BookmarkMenuController() { | 191 BookmarkMenuController::~BookmarkMenuController() { |
| 363 profile_->GetBookmarkModel()->RemoveObserver(this); | 192 menu_delegate_->profile()->GetBookmarkModel()->RemoveObserver(this); |
| 364 if (observer_) | 193 if (observer_) |
| 365 observer_->BookmarkMenuDeleted(this); | 194 observer_->BookmarkMenuDeleted(this); |
| 366 STLDeleteValues(&node_to_menu_map_); | |
| 367 } | 195 } |
| 368 | |
| 369 MenuItemView* BookmarkMenuController::GetMenuByID(int id) { | |
| 370 for (NodeToMenuMap::const_iterator i = node_to_menu_map_.begin(); | |
| 371 i != node_to_menu_map_.end(); ++i) { | |
| 372 MenuItemView* menu = i->second->GetMenuItemByID(id); | |
| 373 if (menu) | |
| 374 return menu; | |
| 375 } | |
| 376 return NULL; | |
| 377 } | |
| 378 | |
| 379 void BookmarkMenuController::WillRemoveBookmarksImpl( | |
| 380 const std::vector<const BookmarkNode*>& bookmarks, | |
| 381 std::set<views::MenuItemView*>* removed_menus) { | |
| 382 // Remove the observer so that when the remove happens we don't prematurely | |
| 383 // cancel the menu. | |
| 384 profile_->GetBookmarkModel()->RemoveObserver(this); | |
| 385 | |
| 386 // Remove the menu items. | |
| 387 std::set<MenuItemView*> changed_parent_menus; | |
| 388 for (std::vector<const BookmarkNode*>::const_iterator i = bookmarks.begin(); | |
| 389 i != bookmarks.end(); ++i) { | |
| 390 NodeToMenuIDMap::iterator node_to_menu = node_to_menu_id_map_.find(*i); | |
| 391 if (node_to_menu != node_to_menu_id_map_.end()) { | |
| 392 MenuItemView* menu = GetMenuByID(node_to_menu->second); | |
| 393 DCHECK(menu); // If there an entry in node_to_menu_id_map_, there should | |
| 394 // be a menu. | |
| 395 removed_menus->insert(menu); | |
| 396 changed_parent_menus.insert(menu->GetParentMenuItem()); | |
| 397 menu->parent()->RemoveChildView(menu); | |
| 398 node_to_menu_id_map_.erase(node_to_menu); | |
| 399 } | |
| 400 } | |
| 401 | |
| 402 // All the bookmarks in |bookmarks| should have the same parent. It's possible | |
| 403 // to support different parents, but this would need to prune any nodes whose | |
| 404 // parent has been removed. As all nodes currently have the same parent, there | |
| 405 // is the DCHECK. | |
| 406 DCHECK(changed_parent_menus.size() <= 1); | |
| 407 | |
| 408 for (std::set<MenuItemView*>::const_iterator i = changed_parent_menus.begin(); | |
| 409 i != changed_parent_menus.end(); ++i) { | |
| 410 (*i)->ChildrenChanged(); | |
| 411 } | |
| 412 | |
| 413 // Remove any descendants of the removed nodes in node_to_menu_id_map_. | |
| 414 for (NodeToMenuIDMap::iterator i = node_to_menu_id_map_.begin(); | |
| 415 i != node_to_menu_id_map_.end(); ) { | |
| 416 bool ancestor_removed = false; | |
| 417 for (std::vector<const BookmarkNode*>::const_iterator j = bookmarks.begin(); | |
| 418 j != bookmarks.end(); ++j) { | |
| 419 if (i->first->HasAncestor(*j)) { | |
| 420 ancestor_removed = true; | |
| 421 break; | |
| 422 } | |
| 423 } | |
| 424 if (ancestor_removed) { | |
| 425 node_to_menu_id_map_.erase(i++); | |
| 426 } else { | |
| 427 ++i; | |
| 428 } | |
| 429 } | |
| 430 } | |
| OLD | NEW |