Index: chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc |
=================================================================== |
--- chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc (revision 86142) |
+++ chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc (working copy) |
@@ -2,7 +2,7 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "chrome/browser/ui/views/bookmarks/bookmark_menu_controller_views.h" |
+#include "chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h" |
#include "base/stl_util-inl.h" |
#include "base/utf_string_conversions.h" |
@@ -11,7 +11,6 @@ |
#include "chrome/browser/bookmarks/bookmark_utils.h" |
#include "chrome/browser/prefs/pref_service.h" |
#include "chrome/browser/profiles/profile.h" |
-#include "chrome/browser/ui/browser.h" |
#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h" |
#include "chrome/browser/ui/views/event_utils.h" |
#include "chrome/common/pref_names.h" |
@@ -22,8 +21,10 @@ |
#include "grit/generated_resources.h" |
#include "grit/theme_resources.h" |
#include "ui/base/dragdrop/os_exchange_data.h" |
+#include "ui/base/l10n/l10n_util.h" |
#include "ui/base/resource/resource_bundle.h" |
#include "views/controls/button/menu_button.h" |
+#include "views/controls/menu/menu_item_view.h" |
using views::MenuItemView; |
@@ -31,65 +32,51 @@ |
// both IE and FF restrict the max width of a menu. |
static const int kMaxMenuWidth = 400; |
-BookmarkMenuController::BookmarkMenuController(Browser* browser, |
- Profile* profile, |
- PageNavigator* navigator, |
- gfx::NativeWindow parent, |
- const BookmarkNode* node, |
- int start_child_index) |
- : browser_(browser), |
- profile_(profile), |
+BookmarkMenuDelegate::BookmarkMenuDelegate(Profile* profile, |
+ PageNavigator* navigator, |
+ gfx::NativeWindow parent, |
+ int first_menu_id) |
+ : profile_(profile), |
page_navigator_(navigator), |
parent_(parent), |
- node_(node), |
menu_(NULL), |
- observer_(NULL), |
for_drop_(false), |
- bookmark_bar_(NULL), |
- next_menu_id_(1) { |
- menu_ = CreateMenu(node, start_child_index); |
+ next_menu_id_(first_menu_id), |
+ real_delegate_(NULL), |
+ is_mutating_model_(false) { |
} |
-void BookmarkMenuController::RunMenuAt(BookmarkBarView* bookmark_bar, |
- bool for_drop) { |
- bookmark_bar_ = bookmark_bar; |
- views::MenuButton* menu_button = bookmark_bar_->GetMenuButtonForNode(node_); |
- DCHECK(menu_button); |
- MenuItemView::AnchorPosition anchor; |
- int start_index; |
- bookmark_bar_->GetAnchorPositionAndStartIndexForButton( |
- menu_button, &anchor, &start_index); |
- RunMenuAt(menu_button, anchor, for_drop); |
+BookmarkMenuDelegate::~BookmarkMenuDelegate() { |
+ profile_->GetBookmarkModel()->RemoveObserver(this); |
+ STLDeleteValues(&node_to_menu_map_); |
} |
-void BookmarkMenuController::RunMenuAt( |
- views::MenuButton* button, |
- MenuItemView::AnchorPosition position, |
- bool for_drop) { |
- gfx::Point screen_loc; |
- views::View::ConvertPointToScreen(button, &screen_loc); |
- // Subtract 1 from the height to make the popup flush with the button border. |
- gfx::Rect bounds(screen_loc.x(), screen_loc.y(), button->width(), |
- button->height() - 1); |
- for_drop_ = for_drop; |
+void BookmarkMenuDelegate::Init(views::MenuDelegate* real_delegate, |
+ MenuItemView* parent, |
+ const BookmarkNode* node, |
+ int start_child_index, |
+ ShowOptions show_options) { |
profile_->GetBookmarkModel()->AddObserver(this); |
- // The constructor creates the initial menu and that is all we should have |
- // at this point. |
- DCHECK(node_to_menu_map_.size() == 1); |
- if (for_drop) { |
- menu_->RunMenuForDropAt(parent_, bounds, position); |
+ real_delegate_ = real_delegate; |
+ if (parent) { |
+ BuildMenu(node, start_child_index, parent, &next_menu_id_); |
+ if (show_options == SHOW_OTHER_FOLDER) |
+ BuildOtherFolderMenu(parent, &next_menu_id_); |
} else { |
- menu_->RunMenuAt(parent_, button, bounds, position, false); |
- delete this; |
+ menu_ = CreateMenu(node, start_child_index, show_options); |
} |
} |
-void BookmarkMenuController::Cancel() { |
- menu_->Cancel(); |
+void BookmarkMenuDelegate::SetActiveMenu(const BookmarkNode* node, |
+ int start_index) { |
+ if (!node_to_menu_map_[node]) |
+ CreateMenu(node, start_index, HIDE_OTHER_FOLDER); |
+ menu_ = node_to_menu_map_[node]; |
} |
-std::wstring BookmarkMenuController::GetTooltipText( |
- int id, const gfx::Point& screen_loc) { |
+std::wstring BookmarkMenuDelegate::GetTooltipText( |
+ int id, |
+ const gfx::Point& screen_loc) { |
DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end()); |
const BookmarkNode* node = menu_id_to_node_map_[id]; |
@@ -99,13 +86,12 @@ |
return std::wstring(); |
} |
-bool BookmarkMenuController::IsTriggerableEvent(MenuItemView* view, |
- const views::MouseEvent& e) { |
+bool BookmarkMenuDelegate::IsTriggerableEvent(views::MenuItemView* menu, |
+ const views::MouseEvent& e) { |
return event_utils::IsPossibleDispositionEvent(e); |
} |
-void BookmarkMenuController::ExecuteCommand(int id, int mouse_event_flags) { |
- DCHECK(page_navigator_); |
+void BookmarkMenuDelegate::ExecuteCommand(int id, int mouse_event_flags) { |
DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end()); |
const BookmarkNode* node = menu_id_to_node_map_[id]; |
@@ -119,21 +105,21 @@ |
initial_disposition); |
} |
-bool BookmarkMenuController::GetDropFormats( |
- MenuItemView* menu, |
- int* formats, |
- std::set<ui::OSExchangeData::CustomFormat>* custom_formats) { |
+bool BookmarkMenuDelegate::GetDropFormats( |
+ MenuItemView* menu, |
+ int* formats, |
+ std::set<ui::OSExchangeData::CustomFormat>* custom_formats) { |
*formats = ui::OSExchangeData::URL; |
custom_formats->insert(BookmarkNodeData::GetBookmarkCustomFormat()); |
return true; |
} |
-bool BookmarkMenuController::AreDropTypesRequired(MenuItemView* menu) { |
+bool BookmarkMenuDelegate::AreDropTypesRequired(MenuItemView* menu) { |
return true; |
} |
-bool BookmarkMenuController::CanDrop(MenuItemView* menu, |
- const ui::OSExchangeData& data) { |
+bool BookmarkMenuDelegate::CanDrop(MenuItemView* menu, |
+ const ui::OSExchangeData& data) { |
// Only accept drops of 1 node, which is the case for all data dragged from |
// bookmark bar and menus. |
@@ -152,6 +138,12 @@ |
// Drag originated from same profile and is not a URL. Only accept it if |
// the dragged node is not a parent of the node menu represents. |
+ if (menu_id_to_node_map_.find(menu->GetCommand()) == |
+ menu_id_to_node_map_.end()) { |
+ // If we don't know the menu assume its because we're embedded. We'll |
+ // figure out the real operation when GetDropOperation is invoked. |
+ return true; |
+ } |
const BookmarkNode* drop_node = menu_id_to_node_map_[menu->GetCommand()]; |
DCHECK(drop_node); |
while (drop_node && drop_node != drag_node) |
@@ -159,19 +151,24 @@ |
return (drop_node == NULL); |
} |
-int BookmarkMenuController::GetDropOperation( |
+int BookmarkMenuDelegate::GetDropOperation( |
MenuItemView* item, |
const views::DropTargetEvent& event, |
- DropPosition* position) { |
+ views::MenuDelegate::DropPosition* position) { |
// Should only get here if we have drop data. |
DCHECK(drop_data_.is_valid()); |
const BookmarkNode* node = menu_id_to_node_map_[item->GetCommand()]; |
const BookmarkNode* drop_parent = node->parent(); |
int index_to_drop_at = drop_parent->GetIndexOf(node); |
- if (*position == DROP_AFTER) { |
+ if (*position == views::MenuDelegate::DROP_AFTER) { |
+ if (node == profile_->GetBookmarkModel()->other_node()) { |
+ // The other folder is shown after all bookmarks on the bookmark bar. |
+ // Dropping after the other folder makes no sense. |
+ *position = views::MenuDelegate::DROP_NONE; |
+ } |
index_to_drop_at++; |
- } else if (*position == DROP_ON) { |
+ } else if (*position == views::MenuDelegate::DROP_ON) { |
drop_parent = node; |
index_to_drop_at = node->child_count(); |
} |
@@ -180,9 +177,10 @@ |
profile_, event, drop_data_, drop_parent, index_to_drop_at); |
} |
-int BookmarkMenuController::OnPerformDrop(MenuItemView* menu, |
- DropPosition position, |
- const views::DropTargetEvent& event) { |
+int BookmarkMenuDelegate::OnPerformDrop( |
+ MenuItemView* menu, |
+ views::MenuDelegate::DropPosition position, |
+ const views::DropTargetEvent& event) { |
const BookmarkNode* drop_node = menu_id_to_node_map_[menu->GetCommand()]; |
DCHECK(drop_node); |
BookmarkModel* model = profile_->GetBookmarkModel(); |
@@ -190,25 +188,38 @@ |
const BookmarkNode* drop_parent = drop_node->parent(); |
DCHECK(drop_parent); |
int index_to_drop_at = drop_parent->GetIndexOf(drop_node); |
- if (position == DROP_AFTER) { |
- index_to_drop_at++; |
- } else if (position == DROP_ON) { |
- DCHECK(drop_node->is_folder()); |
- drop_parent = drop_node; |
- index_to_drop_at = drop_node->child_count(); |
+ switch (position) { |
+ case views::MenuDelegate::DROP_AFTER: |
+ index_to_drop_at++; |
+ break; |
+ |
+ case views::MenuDelegate::DROP_ON: |
+ DCHECK(drop_node->is_folder()); |
+ drop_parent = drop_node; |
+ index_to_drop_at = drop_node->child_count(); |
+ break; |
+ |
+ case views::MenuDelegate::DROP_BEFORE: |
+ if (drop_node == model->other_node()) { |
+ // This can happen with SHOW_OTHER_FOLDER. |
+ drop_parent = model->GetBookmarkBarNode(); |
+ index_to_drop_at = drop_parent->child_count(); |
+ } |
+ break; |
+ |
+ default: |
+ break; |
} |
int result = bookmark_utils::PerformBookmarkDrop( |
profile_, drop_data_, drop_parent, index_to_drop_at); |
- if (for_drop_) |
- delete this; |
return result; |
} |
-bool BookmarkMenuController::ShowContextMenu(MenuItemView* source, |
- int id, |
- const gfx::Point& p, |
- bool is_mouse_gesture) { |
+bool BookmarkMenuDelegate::ShowContextMenu(MenuItemView* source, |
+ int id, |
+ const gfx::Point& p, |
+ bool is_mouse_gesture) { |
DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end()); |
std::vector<const BookmarkNode*> nodes; |
nodes.push_back(menu_id_to_node_map_[id]); |
@@ -225,16 +236,14 @@ |
return true; |
} |
-void BookmarkMenuController::DropMenuClosed(MenuItemView* menu) { |
- delete this; |
+bool BookmarkMenuDelegate::CanDrag(MenuItemView* menu) { |
+ const BookmarkNode* node = menu_id_to_node_map_[menu->GetCommand()]; |
+ // Don't let users drag the other folder. |
+ return node->parent() != profile_->GetBookmarkModel()->root_node(); |
} |
-bool BookmarkMenuController::CanDrag(MenuItemView* menu) { |
- return true; |
-} |
- |
-void BookmarkMenuController::WriteDragData(MenuItemView* sender, |
- ui::OSExchangeData* data) { |
+void BookmarkMenuDelegate::WriteDragData(MenuItemView* sender, |
+ ui::OSExchangeData* data) { |
DCHECK(sender && data); |
UserMetrics::RecordAction(UserMetricsAction("BookmarkBar_DragFromFolder")); |
@@ -243,49 +252,19 @@ |
drag_data.Write(profile_, data); |
} |
-int BookmarkMenuController::GetDragOperations(MenuItemView* sender) { |
- return bookmark_utils::BookmarkDragOperation(profile_, |
- menu_id_to_node_map_[sender->GetCommand()]); |
+int BookmarkMenuDelegate::GetDragOperations(MenuItemView* sender) { |
+ return bookmark_utils::BookmarkDragOperation( |
+ profile_, menu_id_to_node_map_[sender->GetCommand()]); |
} |
-views::MenuItemView* BookmarkMenuController::GetSiblingMenu( |
- views::MenuItemView* menu, |
- const gfx::Point& screen_point, |
- views::MenuItemView::AnchorPosition* anchor, |
- bool* has_mnemonics, |
- views::MenuButton** button) { |
- if (!bookmark_bar_ || for_drop_) |
- return NULL; |
- gfx::Point bookmark_bar_loc(screen_point); |
- views::View::ConvertPointToView(NULL, bookmark_bar_, &bookmark_bar_loc); |
- int start_index; |
- const BookmarkNode* node = |
- bookmark_bar_->GetNodeForButtonAt(bookmark_bar_loc, &start_index); |
- if (!node || !node->is_folder()) |
- return NULL; |
- |
- MenuItemView* alt_menu = node_to_menu_map_[node]; |
- if (!alt_menu) |
- alt_menu = CreateMenu(node, start_index); |
- |
- menu_ = alt_menu; |
- |
- *button = bookmark_bar_->GetMenuButtonForNode(node); |
- bookmark_bar_->GetAnchorPositionAndStartIndexForButton( |
- *button, anchor, &start_index); |
- *has_mnemonics = false; |
- return alt_menu; |
-} |
- |
-int BookmarkMenuController::GetMaxWidthForMenu(MenuItemView* view) { |
+int BookmarkMenuDelegate::GetMaxWidthForMenu(MenuItemView* menu) { |
return kMaxMenuWidth; |
} |
-void BookmarkMenuController::BookmarkModelChanged() { |
- menu_->Cancel(); |
+void BookmarkMenuDelegate::BookmarkModelChanged() { |
} |
-void BookmarkMenuController::BookmarkNodeFaviconLoaded( |
+void BookmarkMenuDelegate::BookmarkNodeFaviconLoaded( |
BookmarkModel* model, const BookmarkNode* node) { |
NodeToMenuIDMap::iterator menu_pair = node_to_menu_id_map_.find(node); |
if (menu_pair == node_to_menu_id_map_.end()) |
@@ -302,34 +281,55 @@ |
} |
} |
-void BookmarkMenuController::WillRemoveBookmarks( |
+void BookmarkMenuDelegate::WillRemoveBookmarks( |
const std::vector<const BookmarkNode*>& bookmarks) { |
+ DCHECK(!is_mutating_model_); |
+ is_mutating_model_ = true; |
std::set<MenuItemView*> removed_menus; |
- |
WillRemoveBookmarksImpl(bookmarks, &removed_menus); |
- |
STLDeleteElements(&removed_menus); |
} |
-void BookmarkMenuController::DidRemoveBookmarks() { |
+void BookmarkMenuDelegate::DidRemoveBookmarks() { |
+ // Balances remove in WillRemoveBookmarksImpl. |
profile_->GetBookmarkModel()->AddObserver(this); |
+ DCHECK(is_mutating_model_); |
+ is_mutating_model_ = false; |
} |
-MenuItemView* BookmarkMenuController::CreateMenu(const BookmarkNode* parent, |
- int start_child_index) { |
- MenuItemView* menu = new MenuItemView(this); |
+MenuItemView* BookmarkMenuDelegate::CreateMenu(const BookmarkNode* parent, |
+ int start_child_index, |
+ ShowOptions show_options) { |
+ MenuItemView* menu = new MenuItemView(real_delegate_); |
menu->SetCommand(next_menu_id_++); |
menu_id_to_node_map_[menu->GetCommand()] = parent; |
menu->set_has_icons(true); |
BuildMenu(parent, start_child_index, menu, &next_menu_id_); |
+ if (show_options == SHOW_OTHER_FOLDER) |
+ BuildOtherFolderMenu(menu, &next_menu_id_); |
node_to_menu_map_[parent] = menu; |
return menu; |
} |
-void BookmarkMenuController::BuildMenu(const BookmarkNode* parent, |
- int start_child_index, |
- MenuItemView* menu, |
- int* next_menu_id) { |
+void BookmarkMenuDelegate::BuildOtherFolderMenu( |
+ MenuItemView* menu, int* next_menu_id) { |
+ const BookmarkNode* other_folder = profile_->GetBookmarkModel()->other_node(); |
+ int id = *next_menu_id; |
+ (*next_menu_id)++; |
+ SkBitmap* folder_icon = ResourceBundle::GetSharedInstance(). |
+ GetBitmapNamed(IDR_BOOKMARK_BAR_FOLDER); |
+ MenuItemView* submenu = menu->AppendSubMenuWithIcon( |
+ id, UTF16ToWide( |
+ l10n_util::GetStringUTF16(IDS_BOOMARK_BAR_OTHER_BOOKMARKED)), |
+ *folder_icon); |
+ BuildMenu(other_folder, 0, submenu, next_menu_id); |
+ menu_id_to_node_map_[id] = other_folder; |
+} |
+ |
+void BookmarkMenuDelegate::BuildMenu(const BookmarkNode* parent, |
+ int start_child_index, |
+ MenuItemView* menu, |
+ int* next_menu_id) { |
DCHECK(!parent->child_count() || |
start_child_index < parent->child_count()); |
for (int i = start_child_index; i < parent->child_count(); ++i) { |
@@ -348,8 +348,8 @@ |
} else if (node->is_folder()) { |
SkBitmap* folder_icon = ResourceBundle::GetSharedInstance(). |
GetBitmapNamed(IDR_BOOKMARK_BAR_FOLDER); |
- MenuItemView* submenu = menu->AppendSubMenuWithIcon(id, |
- UTF16ToWide(node->GetTitle()), *folder_icon); |
+ MenuItemView* submenu = menu->AppendSubMenuWithIcon( |
+ id, UTF16ToWide(node->GetTitle()), *folder_icon); |
node_to_menu_id_map_[node] = id; |
BuildMenu(node, 0, submenu, next_menu_id); |
} else { |
@@ -359,14 +359,7 @@ |
} |
} |
-BookmarkMenuController::~BookmarkMenuController() { |
- profile_->GetBookmarkModel()->RemoveObserver(this); |
- if (observer_) |
- observer_->BookmarkMenuDeleted(this); |
- STLDeleteValues(&node_to_menu_map_); |
-} |
- |
-MenuItemView* BookmarkMenuController::GetMenuByID(int id) { |
+MenuItemView* BookmarkMenuDelegate::GetMenuByID(int id) { |
for (NodeToMenuMap::const_iterator i = node_to_menu_map_.begin(); |
i != node_to_menu_map_.end(); ++i) { |
MenuItemView* menu = i->second->GetMenuItemByID(id); |
@@ -376,11 +369,11 @@ |
return NULL; |
} |
-void BookmarkMenuController::WillRemoveBookmarksImpl( |
- const std::vector<const BookmarkNode*>& bookmarks, |
- std::set<views::MenuItemView*>* removed_menus) { |
+void BookmarkMenuDelegate::WillRemoveBookmarksImpl( |
+ const std::vector<const BookmarkNode*>& bookmarks, |
+ std::set<views::MenuItemView*>* removed_menus) { |
// Remove the observer so that when the remove happens we don't prematurely |
- // cancel the menu. |
+ // cancel the menu. The observer ias added back in DidRemoveBookmarks. |
profile_->GetBookmarkModel()->RemoveObserver(this); |
// Remove the menu items. |
@@ -391,7 +384,7 @@ |
if (node_to_menu != node_to_menu_id_map_.end()) { |
MenuItemView* menu = GetMenuByID(node_to_menu->second); |
DCHECK(menu); // If there an entry in node_to_menu_id_map_, there should |
- // be a menu. |
+ // be a menu. |
removed_menus->insert(menu); |
changed_parent_menus.insert(menu->GetParentMenuItem()); |
menu->parent()->RemoveChildView(menu); |