bookmark_menu_delegate.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model_factory.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/bookmarks/bookmark_utils.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/event_utils.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/page_navigator.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/user_metrics.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_resources.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/dragdrop/os_exchange_data.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/window_open_disposition.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/menu_button.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_item_view.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/submenu_view.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::PageNavigator; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::UserMetricsAction; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using views::MenuItemView; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Max width of a menu. There does not appear to be an OS value for this, yet 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// both IE and FF restrict the max width of a menu. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMaxMenuWidth = 400; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarkMenuDelegate::BookmarkMenuDelegate(Browser* browser, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageNavigator* navigator, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::Widget* parent, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int first_menu_id) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : browser_(browser), 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_(browser->profile()), 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) page_navigator_(navigator), 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent_(parent), 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_(NULL), 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for_drop_(false), 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent_menu_item_(NULL), 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_menu_id_(first_menu_id), 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) real_delegate_(NULL), 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_mutating_model_(false), 5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) location_(BOOKMARK_LAUNCH_LOCATION_NONE) {} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarkMenuDelegate::~BookmarkMenuDelegate() { 583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) GetBookmarkModel()->RemoveObserver(this); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void BookmarkMenuDelegate::Init(views::MenuDelegate* real_delegate, 6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) MenuItemView* parent, 6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const BookmarkNode* node, 6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int start_child_index, 6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ShowOptions show_options, 6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) BookmarkLaunchLocation location) { 673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) GetBookmarkModel()->AddObserver(this); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) real_delegate_ = real_delegate; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent_menu_item_ = parent; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int initial_count = parent->GetSubmenu() ? 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent->GetSubmenu()->GetMenuItemCount() : 0; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((start_child_index < node->child_count()) && 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (initial_count > 0)) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent->AppendSeparator(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildMenu(node, start_child_index, parent, &next_menu_id_); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (show_options == SHOW_PERMANENT_FOLDERS) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildMenusForPermanentNodes(parent, &next_menu_id_); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_ = CreateMenu(node, start_child_index, show_options); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) location_ = location; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkMenuDelegate::SetPageNavigator(PageNavigator* navigator) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) page_navigator_ = navigator; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (context_menu_.get()) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_menu_->SetPageNavigator(navigator); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)BookmarkModel* BookmarkMenuDelegate::GetBookmarkModel() { 943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return BookmarkModelFactory::GetForProfile(profile_); 953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkMenuDelegate::SetActiveMenu(const BookmarkNode* node, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int start_index) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!parent_menu_item_); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node_to_menu_map_[node]) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateMenu(node, start_index, HIDE_PERMANENT_FOLDERS); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_ = node_to_menu_map_[node]; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 BookmarkMenuDelegate::GetTooltipText( 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& screen_loc) const { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuIDToNodeMap::const_iterator i = menu_id_to_node_map_.find(id); 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // When removing bookmarks it may be possible to end up here without a node. 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (i == menu_id_to_node_map_.end()) { 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(is_mutating_model_); 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return string16(); 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = i->second; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node->is_url()) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return BookmarkBarView::CreateToolTipForURLAndTitle( 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) screen_loc, node->url(), node->GetTitle(), profile_, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent()->GetNativeView()); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return string16(); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkMenuDelegate::IsTriggerableEvent(views::MenuItemView* menu, 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::Event& e) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return e.type() == ui::ET_GESTURE_TAP || 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.type() == ui::ET_GESTURE_TAP_DOWN || 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_utils::IsPossibleDispositionEvent(e); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkMenuDelegate::ExecuteCommand(int id, int mouse_event_flags) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end()); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = menu_id_to_node_map_[id]; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<const BookmarkNode*> selection; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection.push_back(node); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::OpenAll(parent_->GetNativeWindow(), page_navigator_, selection, 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::DispositionFromEventFlags(mouse_event_flags), 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) profile_); 14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) RecordBookmarkLaunch(location_); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarkMenuDelegate::ShouldExecuteCommandWithoutClosingMenu( 14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int id, 14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const ui::Event& event) { 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (event.flags() & ui::EF_LEFT_MOUSE_BUTTON) && 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::DispositionFromEventFlags(event.flags()) == NEW_BACKGROUND_TAB; 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkMenuDelegate::GetDropFormats( 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuItemView* menu, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* formats, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<ui::OSExchangeData::CustomFormat>* custom_formats) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *formats = ui::OSExchangeData::URL; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) custom_formats->insert(BookmarkNodeData::GetBookmarkCustomFormat()); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkMenuDelegate::AreDropTypesRequired(MenuItemView* menu) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkMenuDelegate::CanDrop(MenuItemView* menu, 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::OSExchangeData& data) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only accept drops of 1 node, which is the case for all data dragged from 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bookmark bar and menus. 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!drop_data_.Read(data) || drop_data_.elements.size() != 1 || 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !profile_->GetPrefs()->GetBoolean(prefs::kEditBookmarksEnabled)) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drop_data_.has_single_url()) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* drag_node = drop_data_.GetFirstNode(profile_); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!drag_node) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Dragging a folder from another profile, always accept. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Drag originated from same profile and is not a URL. Only accept it if 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the dragged node is not a parent of the node menu represents. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (menu_id_to_node_map_.find(menu->GetCommand()) == 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_id_to_node_map_.end()) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't know the menu assume its because we're embedded. We'll 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // figure out the real operation when GetDropOperation is invoked. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* drop_node = menu_id_to_node_map_[menu->GetCommand()]; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(drop_node); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (drop_node && drop_node != drag_node) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_node = drop_node->parent(); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (drop_node == NULL); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BookmarkMenuDelegate::GetDropOperation( 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuItemView* item, 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::DropTargetEvent& event, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::MenuDelegate::DropPosition* position) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should only get here if we have drop data. 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(drop_data_.is_valid()); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = menu_id_to_node_map_[item->GetCommand()]; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* drop_parent = node->parent(); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index_to_drop_at = drop_parent->GetIndexOf(node); 2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) BookmarkModel* model = GetBookmarkModel(); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (*position) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case views::MenuDelegate::DROP_AFTER: 2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (node == model->other_node() || node == model->mobile_node()) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Dropping after these nodes makes no sense. 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *position = views::MenuDelegate::DROP_NONE; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index_to_drop_at++; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case views::MenuDelegate::DROP_BEFORE: 2183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (node == model->mobile_node()) { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Dropping before this node makes no sense. 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *position = views::MenuDelegate::DROP_NONE; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case views::MenuDelegate::DROP_ON: 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_parent = node; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index_to_drop_at = node->child_count(); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(drop_parent); 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return chrome::GetBookmarkDropOperation(profile_, event, drop_data_, 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) drop_parent, index_to_drop_at); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BookmarkMenuDelegate::OnPerformDrop( 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuItemView* menu, 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::MenuDelegate::DropPosition position, 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::DropTargetEvent& event) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* drop_node = menu_id_to_node_map_[menu->GetCommand()]; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(drop_node); 2433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) BookmarkModel* model = GetBookmarkModel(); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(model); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* drop_parent = drop_node->parent(); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(drop_parent); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index_to_drop_at = drop_parent->GetIndexOf(drop_node); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (position) { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case views::MenuDelegate::DROP_AFTER: 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index_to_drop_at++; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case views::MenuDelegate::DROP_ON: 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(drop_node->is_folder()); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_parent = drop_node; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index_to_drop_at = drop_node->child_count(); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case views::MenuDelegate::DROP_BEFORE: 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drop_node == model->other_node() || 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_node == model->mobile_node()) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This can happen with SHOW_PERMANENT_FOLDERS. 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_parent = model->bookmark_bar_node(); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index_to_drop_at = drop_parent->child_count(); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return chrome::DropBookmarks(profile_, drop_data_, 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) drop_parent, index_to_drop_at); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkMenuDelegate::ShowContextMenu(MenuItemView* source, 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id, 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& p, 2797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ui::MenuSourceType source_type) { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end()); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<const BookmarkNode*> nodes; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nodes.push_back(menu_id_to_node_map_[id]); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool close_on_delete = !parent_menu_item_ && 2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) (nodes[0]->parent() == GetBookmarkModel()->other_node() && 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nodes[0]->parent()->child_count() == 1); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_menu_.reset( 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new BookmarkContextMenu( 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent_, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_, 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_, 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) page_navigator_, 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nodes[0]->parent(), 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nodes, 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close_on_delete)); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_menu_->set_observer(this); 2967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) context_menu_->RunMenuAt(p, source_type); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_menu_.reset(NULL); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkMenuDelegate::CanDrag(MenuItemView* menu) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = menu_id_to_node_map_[menu->GetCommand()]; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't let users drag the other folder. 3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return node->parent() != GetBookmarkModel()->root_node(); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkMenuDelegate::WriteDragData(MenuItemView* sender, 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::OSExchangeData* data) { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(sender && data); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RecordAction(UserMetricsAction("BookmarkBar_DragFromFolder")); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNodeData drag_data(menu_id_to_node_map_[sender->GetCommand()]); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_data.Write(profile_, data); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BookmarkMenuDelegate::GetDragOperations(MenuItemView* sender) { 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return chrome::GetBookmarkDragOperation( 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_, menu_id_to_node_map_[sender->GetCommand()]); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BookmarkMenuDelegate::GetMaxWidthForMenu(MenuItemView* menu) { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kMaxMenuWidth; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkMenuDelegate::BookmarkModelChanged() { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkMenuDelegate::BookmarkNodeFaviconChanged( 330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) BookmarkModel* model, 331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const BookmarkNode* node) { 332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NodeToMenuMap::iterator menu_pair = node_to_menu_map_.find(node); 333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (menu_pair == node_to_menu_map_.end()) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // We're not showing a menu item for the node. 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) menu_pair->second->SetIcon(model->GetFavicon(node).AsImageSkia()); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkMenuDelegate::WillRemoveBookmarks( 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<const BookmarkNode*>& bookmarks) { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!is_mutating_model_); 342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) is_mutating_model_ = true; // Set to false in DidRemoveBookmarks(). 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the observer so that when the remove happens we don't prematurely 345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // cancel the menu. The observer is added back in DidRemoveBookmarks(). 3463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) GetBookmarkModel()->RemoveObserver(this); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the menu items. 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<MenuItemView*> changed_parent_menus; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<const BookmarkNode*>::const_iterator i(bookmarks.begin()); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != bookmarks.end(); ++i) { 352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NodeToMenuMap::iterator node_to_menu = node_to_menu_map_.find(*i); 353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (node_to_menu != node_to_menu_map_.end()) { 354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MenuItemView* menu = node_to_menu->second; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuItemView* parent = menu->GetParentMenuItem(); 356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // |parent| is NULL when removing a root. This happens when right clicking 357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // to delete an empty folder. 358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (parent) { 359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) changed_parent_menus.insert(parent); 360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) parent->RemoveMenuItemAt(menu->parent()->GetIndexOf(menu)); 361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) node_to_menu_map_.erase(node_to_menu); 363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) menu_id_to_node_map_.erase(menu->GetCommand()); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All the bookmarks in |bookmarks| should have the same parent. It's possible 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to support different parents, but this would need to prune any nodes whose 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // parent has been removed. As all nodes currently have the same parent, there 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is the DCHECK. 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(changed_parent_menus.size() <= 1); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Remove any descendants of the removed nodes in |node_to_menu_map_|. 374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (NodeToMenuMap::iterator i(node_to_menu_map_.begin()); 375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) i != node_to_menu_map_.end(); ) { 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ancestor_removed = false; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<const BookmarkNode*>::const_iterator j(bookmarks.begin()); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j != bookmarks.end(); ++j) { 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->first->HasAncestor(*j)) { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ancestor_removed = true; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (ancestor_removed) { 385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) menu_id_to_node_map_.erase(i->second->GetCommand()); 386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) node_to_menu_map_.erase(i++); 387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i; 389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (std::set<MenuItemView*>::const_iterator i(changed_parent_menus.begin()); 393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch i != changed_parent_menus.end(); ++i) 394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*i)->ChildrenChanged(); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkMenuDelegate::DidRemoveBookmarks() { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Balances remove in WillRemoveBookmarksImpl. 3993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) GetBookmarkModel()->AddObserver(this); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(is_mutating_model_); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_mutating_model_ = false; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuItemView* BookmarkMenuDelegate::CreateMenu(const BookmarkNode* parent, 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int start_child_index, 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShowOptions show_options) { 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuItemView* menu = new MenuItemView(real_delegate_); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu->SetCommand(next_menu_id_++); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_id_to_node_map_[menu->GetCommand()] = parent; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu->set_has_icons(true); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildMenu(parent, start_child_index, menu, &next_menu_id_); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (show_options == SHOW_PERMANENT_FOLDERS) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildMenusForPermanentNodes(menu, &next_menu_id_); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return menu; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkMenuDelegate::BuildMenusForPermanentNodes( 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::MenuItemView* menu, 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* next_menu_id) { 4203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) BookmarkModel* model = GetBookmarkModel(); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool added_separator = false; 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildMenuForPermanentNode(model->other_node(), menu, next_menu_id, 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &added_separator); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildMenuForPermanentNode(model->mobile_node(), menu, next_menu_id, 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &added_separator); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkMenuDelegate::BuildMenuForPermanentNode( 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node, 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuItemView* menu, 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* next_menu_id, 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool* added_separator) { 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node->IsVisible() || node->GetTotalNodeCount() == 1) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // No children, don't create a menu. 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!*added_separator) { 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *added_separator = true; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu->AppendSeparator(); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id = *next_menu_id; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*next_menu_id)++; 442d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); 443d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) gfx::ImageSkia* folder_icon = rb->GetImageSkiaNamed(IDR_BOOKMARK_BAR_FOLDER); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuItemView* submenu = menu->AppendSubMenuWithIcon( 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id, node->GetTitle(), *folder_icon); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildMenu(node, 0, submenu, next_menu_id); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_id_to_node_map_[id] = node; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkMenuDelegate::BuildMenu(const BookmarkNode* parent, 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int start_child_index, 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuItemView* menu, 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* next_menu_id) { 454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) node_to_menu_map_[parent] = menu; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(parent->empty() || start_child_index < parent->child_count()); 456d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = start_child_index; i < parent->child_count(); ++i) { 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = parent->GetChild(i); 459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const int id = *next_menu_id; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*next_menu_id)++; 461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) menu_id_to_node_map_[id] = node; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node->is_url()) { 4643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const gfx::Image& image = GetBookmarkModel()->GetFavicon(node); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::ImageSkia* icon = image.IsEmpty() ? 466d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rb->GetImageSkiaNamed(IDR_DEFAULT_FAVICON) : image.ToImageSkia(); 467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) node_to_menu_map_[node] = 468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) menu->AppendMenuItemWithIcon(id, node->GetTitle(), *icon); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (node->is_folder()) { 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia* folder_icon = 471d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rb->GetImageSkiaNamed(IDR_BOOKMARK_BAR_FOLDER); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuItemView* submenu = menu->AppendSubMenuWithIcon( 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id, node->GetTitle(), *folder_icon); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildMenu(node, 0, submenu, next_menu_id); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 480