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