summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/bookmarks/base_bookmark_model_observer.h57
-rw-r--r--chrome/browser/bookmarks/bookmark_menu_controller.cc232
-rw-r--r--chrome/browser/bookmarks/bookmark_menu_controller.h137
-rw-r--r--chrome/browser/bookmarks/bookmark_utils.cc57
-rw-r--r--chrome/browser/bookmarks/bookmark_utils.h23
-rw-r--r--chrome/browser/browser.vcproj8
-rw-r--r--chrome/browser/views/bookmark_bar_view.cc408
-rw-r--r--chrome/browser/views/bookmark_bar_view.h31
-rw-r--r--chrome/views/chrome_menu.cc1
9 files changed, 570 insertions, 384 deletions
diff --git a/chrome/browser/bookmarks/base_bookmark_model_observer.h b/chrome/browser/bookmarks/base_bookmark_model_observer.h
new file mode 100644
index 0000000..34d755f
--- /dev/null
+++ b/chrome/browser/bookmarks/base_bookmark_model_observer.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_BOOKMARKS_BASE_BOOKMARK_MODEL_OBSERVER_H_
+#define CHROME_BROWSER_BOOKMARKS_BASE_BOOKMARK_MODEL_OBSERVER_H_
+
+#include "chrome/browser/bookmarks/bookmark_model.h"
+
+// Base class for a BookmarkModelObserver implementation. All mutations of the
+// model funnel into the method BookmarkModelChanged.
+class BaseBookmarkModelObserver : public BookmarkModelObserver {
+ public:
+ BaseBookmarkModelObserver() {}
+ virtual ~BaseBookmarkModelObserver() {}
+
+ virtual void BookmarkModelChanged() = 0;
+
+ virtual void Loaded(BookmarkModel* model) {}
+
+ virtual void BookmarkModelBeingDeleted(BookmarkModel* model) {
+ BookmarkModelChanged();
+ }
+ virtual void BookmarkNodeMoved(BookmarkModel* model,
+ BookmarkNode* old_parent,
+ int old_index,
+ BookmarkNode* new_parent,
+ int new_index) {
+ BookmarkModelChanged();
+ }
+ virtual void BookmarkNodeAdded(BookmarkModel* model,
+ BookmarkNode* parent,
+ int index) {
+ BookmarkModelChanged();
+ }
+ virtual void BookmarkNodeRemoved(BookmarkModel* model,
+ BookmarkNode* parent,
+ int index) {
+ BookmarkModelChanged();
+ }
+ virtual void BookmarkNodeChanged(BookmarkModel* model,
+ BookmarkNode* node) {
+ BookmarkModelChanged();
+ }
+ virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model,
+ BookmarkNode* node) {
+ }
+ virtual void BookmarkNodeChildrenReordered(BookmarkModel* model,
+ BookmarkNode* node) {
+ BookmarkModelChanged();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BaseBookmarkModelObserver);
+};
+
+#endif // CHROME_BROWSER_BOOKMARKS_BASE_BOOKMARK_MODEL_OBSERVER_H_
diff --git a/chrome/browser/bookmarks/bookmark_menu_controller.cc b/chrome/browser/bookmarks/bookmark_menu_controller.cc
new file mode 100644
index 0000000..058a2f5
--- /dev/null
+++ b/chrome/browser/bookmarks/bookmark_menu_controller.cc
@@ -0,0 +1,232 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/bookmarks/bookmark_menu_controller.h"
+
+#include "chrome/browser/bookmarks/bookmark_drag_data.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/tab_contents/page_navigator.h"
+#include "chrome/browser/views/event_utils.h"
+#include "chrome/common/os_exchange_data.h"
+#include "chrome/common/page_transition_types.h"
+#include "chrome/common/resource_bundle.h"
+#include "grit/theme_resources.h"
+
+BookmarkMenuController::BookmarkMenuController(Browser* browser,
+ Profile* profile,
+ PageNavigator* navigator,
+ HWND hwnd,
+ BookmarkNode* node,
+ int start_child_index)
+ : browser_(browser),
+ profile_(profile),
+ page_navigator_(navigator),
+ hwnd_(hwnd),
+ node_(node),
+ observer_(NULL),
+ for_drop_(false) {
+ menu_.reset(new views::MenuItemView(this));
+ int next_menu_id = 1;
+ menu_id_to_node_map_[menu_->GetCommand()] = node;
+ menu_->set_has_icons(true);
+ BuildMenu(node, start_child_index, menu_.get(), &next_menu_id);
+}
+
+void BookmarkMenuController::RunMenuAt(
+ const gfx::Rect& bounds,
+ views::MenuItemView::AnchorPosition position,
+ bool for_drop) {
+ for_drop_ = for_drop;
+ profile_->GetBookmarkModel()->AddObserver(this);
+ if (for_drop) {
+ menu_->RunMenuForDropAt(hwnd_, bounds, position);
+ } else {
+ menu_->RunMenuAt(hwnd_, bounds, position, false);
+ delete this;
+ }
+}
+
+void BookmarkMenuController::Cancel() {
+ menu_->Cancel();
+}
+
+bool BookmarkMenuController::IsTriggerableEvent(const views::MouseEvent& e) {
+ return event_utils::IsPossibleDispositionEvent(e);
+}
+
+void BookmarkMenuController::ExecuteCommand(int id, int mouse_event_flags) {
+ DCHECK(page_navigator_);
+ DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end());
+ GURL url = menu_id_to_node_map_[id]->GetURL();
+ page_navigator_->OpenURL(
+ url, GURL(), event_utils::DispositionFromEventFlags(mouse_event_flags),
+ PageTransition::AUTO_BOOKMARK);
+}
+
+bool BookmarkMenuController::CanDrop(views::MenuItemView* menu,
+ const OSExchangeData& data) {
+ // Only accept drops of 1 node, which is the case for all data dragged from
+ // bookmark bar and menus.
+
+ if (!drop_data_.Read(data) || drop_data_.elements.size() != 1)
+ return false;
+
+ if (drop_data_.has_single_url())
+ return true;
+
+ BookmarkNode* drag_node = drop_data_.GetFirstNode(profile_);
+ if (!drag_node) {
+ // Dragging a group from another profile, always accept.
+ return true;
+ }
+
+ // 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.
+ BookmarkNode* drop_node = menu_id_to_node_map_[menu->GetCommand()];
+ DCHECK(drop_node);
+ BookmarkNode* node = drop_node;
+ while (drop_node && drop_node != drag_node)
+ drop_node = drop_node->GetParent();
+ return (drop_node == NULL);
+}
+
+int BookmarkMenuController::GetDropOperation(
+ views::MenuItemView* item,
+ const views::DropTargetEvent& event,
+ DropPosition* position) {
+ // Should only get here if we have drop data.
+ DCHECK(drop_data_.is_valid());
+
+ BookmarkNode* node = menu_id_to_node_map_[item->GetCommand()];
+ BookmarkNode* drop_parent = node->GetParent();
+ int index_to_drop_at = drop_parent->IndexOfChild(node);
+ if (*position == DROP_AFTER) {
+ index_to_drop_at++;
+ } else if (*position == DROP_ON) {
+ drop_parent = node;
+ index_to_drop_at = node->GetChildCount();
+ }
+ DCHECK(drop_parent);
+ return bookmark_utils::BookmarkDropOperation(
+ profile_, event, drop_data_, drop_parent, index_to_drop_at);
+}
+
+int BookmarkMenuController::OnPerformDrop(views::MenuItemView* menu,
+ DropPosition position,
+ const views::DropTargetEvent& event) {
+ BookmarkNode* drop_node = menu_id_to_node_map_[menu->GetCommand()];
+ DCHECK(drop_node);
+ BookmarkModel* model = profile_->GetBookmarkModel();
+ DCHECK(model);
+ BookmarkNode* drop_parent = drop_node->GetParent();
+ DCHECK(drop_parent);
+ int index_to_drop_at = drop_parent->IndexOfChild(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->GetChildCount();
+ }
+
+ int result = bookmark_utils::PerformBookmarkDrop(
+ profile_, drop_data_, drop_parent, index_to_drop_at);
+ if (for_drop_)
+ delete this;
+ return result;
+}
+
+bool BookmarkMenuController::ShowContextMenu(views::MenuItemView* source,
+ int id,
+ int x,
+ int y,
+ bool is_mouse_gesture) {
+ DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end());
+ std::vector<BookmarkNode*> nodes;
+ nodes.push_back(menu_id_to_node_map_[id]);
+ context_menu_.reset(
+ new BookmarkContextMenu(hwnd_,
+ profile_,
+ browser_,
+ page_navigator_,
+ nodes[0]->GetParent(),
+ nodes,
+ BookmarkContextMenu::BOOKMARK_BAR));
+ context_menu_->RunMenuAt(x, y);
+ context_menu_.reset(NULL);
+ return true;
+}
+
+void BookmarkMenuController::DropMenuClosed(views::MenuItemView* menu) {
+ delete this;
+}
+
+bool BookmarkMenuController::CanDrag(views::MenuItemView* menu) {
+ return true;
+}
+
+void BookmarkMenuController::WriteDragData(views::MenuItemView* sender,
+ OSExchangeData* data) {
+ DCHECK(sender && data);
+
+ UserMetrics::RecordAction(L"BookmarkBar_DragFromFolder", profile_);
+
+ BookmarkDragData drag_data(menu_id_to_node_map_[sender->GetCommand()]);
+ drag_data.Write(profile_, data);
+}
+
+int BookmarkMenuController::GetDragOperations(views::MenuItemView* sender) {
+ return bookmark_utils::BookmarkDragOperation(
+ menu_id_to_node_map_[sender->GetCommand()]);
+}
+
+void BookmarkMenuController::BookmarkModelChanged() {
+ menu_->Cancel();
+}
+
+void BookmarkMenuController::BookmarkNodeFavIconLoaded(BookmarkModel* model,
+ BookmarkNode* node) {
+ if (node_to_menu_id_map_.find(node) != node_to_menu_id_map_.end())
+ menu_->SetIcon(node->GetFavIcon(), node_to_menu_id_map_[node]);
+}
+
+void BookmarkMenuController::BuildMenu(BookmarkNode* parent,
+ int start_child_index,
+ views::MenuItemView* menu,
+ int* next_menu_id) {
+ DCHECK(!parent->GetChildCount() ||
+ start_child_index < parent->GetChildCount());
+ for (int i = start_child_index; i < parent->GetChildCount(); ++i) {
+ BookmarkNode* node = parent->GetChild(i);
+ int id = *next_menu_id;
+
+ (*next_menu_id)++;
+ if (node->is_url()) {
+ SkBitmap icon = node->GetFavIcon();
+ if (icon.width() == 0) {
+ icon = *ResourceBundle::GetSharedInstance().
+ GetBitmapNamed(IDR_DEFAULT_FAVICON);
+ }
+ menu->AppendMenuItemWithIcon(id, node->GetTitle(), icon);
+ node_to_menu_id_map_[node] = id;
+ } else if (node->is_folder()) {
+ SkBitmap* folder_icon = ResourceBundle::GetSharedInstance().
+ GetBitmapNamed(IDR_BOOKMARK_BAR_FOLDER);
+ views::MenuItemView* submenu =
+ menu->AppendSubMenuWithIcon(id, node->GetTitle(), *folder_icon);
+ BuildMenu(node, 0, submenu, next_menu_id);
+ } else {
+ NOTREACHED();
+ }
+ menu_id_to_node_map_[id] = node;
+ }
+}
+
+BookmarkMenuController::~BookmarkMenuController() {
+ profile_->GetBookmarkModel()->RemoveObserver(this);
+ if (observer_)
+ observer_->BookmarkMenuDeleted(this);
+}
diff --git a/chrome/browser/bookmarks/bookmark_menu_controller.h b/chrome/browser/bookmarks/bookmark_menu_controller.h
new file mode 100644
index 0000000..27636a7
--- /dev/null
+++ b/chrome/browser/bookmarks/bookmark_menu_controller.h
@@ -0,0 +1,137 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_BOOKMARKS_BOOKMARK_MENU_CONTROLLER_H_
+#define CHROME_BROWSER_BOOKMARKS_BOOKMARK_MENU_CONTROLLER_H_
+
+#include <map>
+
+#include "chrome/browser/bookmarks/base_bookmark_model_observer.h"
+#include "chrome/browser/bookmarks/bookmark_context_menu.h"
+#include "chrome/browser/bookmarks/bookmark_drag_data.h"
+#include "chrome/views/chrome_menu.h"
+
+class BookmarkContextMenu;
+class BookmarkNode;
+class Browser;
+class OSExchangeData;
+class PageNavigator;
+class Profile;
+
+// BookmarkMenuController is responsible for showing a menu of bookmarks,
+// each item in the menu represents a bookmark.
+// BookmarkMenuController deletes itself as necessary, although the menu can
+// be explicitly hidden by way of the Cancel method.
+class BookmarkMenuController : public BaseBookmarkModelObserver,
+ public views::MenuDelegate {
+ public:
+ // The observer is notified prior to the menu being deleted.
+ class Observer {
+ public:
+ virtual void BookmarkMenuDeleted(BookmarkMenuController* controller) = 0;
+ };
+
+ // Creates a BookmarkMenuController showing the children of |node| starting
+ // at index |start_child_index|.
+ BookmarkMenuController(Browser* browser,
+ Profile* profile,
+ PageNavigator* page_navigator,
+ HWND hwnd,
+ BookmarkNode* node,
+ int start_child_index);
+
+ // Shows the menu.
+ void RunMenuAt(const gfx::Rect& bounds,
+ views::MenuItemView::AnchorPosition position,
+ bool for_drop);
+
+ // Hides the menu.
+ void Cancel();
+
+ // Returns the node the menu is showing for.
+ BookmarkNode* node() const { return node_; }
+
+ // Returns the menu.
+ views::MenuItemView* menu() const { return menu_.get(); }
+
+ // Returns the context menu, or NULL if the context menu isn't showing.
+ views::MenuItemView* context_menu() const {
+ return context_menu_.get() ? context_menu_->menu() : NULL;
+ }
+
+ void set_observer(Observer* observer) { observer_ = observer; }
+
+ // MenuDelegate methods.
+ virtual bool IsTriggerableEvent(const views::MouseEvent& e);
+ virtual void ExecuteCommand(int id, int mouse_event_flags);
+ virtual bool CanDrop(views::MenuItemView* menu, const OSExchangeData& data);
+ virtual int GetDropOperation(views::MenuItemView* item,
+ const views::DropTargetEvent& event,
+ DropPosition* position);
+ virtual int OnPerformDrop(views::MenuItemView* menu,
+ DropPosition position,
+ const views::DropTargetEvent& event);
+ virtual bool ShowContextMenu(views::MenuItemView* source,
+ int id,
+ int x,
+ int y,
+ bool is_mouse_gesture);
+ virtual void DropMenuClosed(views::MenuItemView* menu);
+ virtual bool CanDrag(views::MenuItemView* menu);
+ virtual void WriteDragData(views::MenuItemView* sender, OSExchangeData* data);
+ virtual int GetDragOperations(views::MenuItemView* sender);
+
+ virtual void BookmarkModelChanged();
+ virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model,
+ BookmarkNode* node);
+
+ private:
+ // BookmarkMenuController deletes itself as necessary.
+ ~BookmarkMenuController();
+
+ // Creates an entry in menu for each child node of |parent| starting at
+ // |start_child_index|.
+ void BuildMenu(BookmarkNode* parent,
+ int start_child_index,
+ views::MenuItemView* menu,
+ int* next_menu_id);
+
+ Browser* browser_;
+
+ Profile* profile_;
+
+ PageNavigator* page_navigator_;
+
+ // Parent of menus.
+ HWND hwnd_;
+
+ // The node we're showing the contents of.
+ BookmarkNode* node_;
+
+ // Maps from menu id to BookmarkNode.
+ std::map<int, BookmarkNode*> menu_id_to_node_map_;
+
+ // Mapping from node to menu id. This only contains entries for nodes of type
+ // URL.
+ std::map<BookmarkNode*, int> node_to_menu_id_map_;
+
+ // The menu.
+ scoped_ptr<views::MenuItemView> menu_;
+
+ // Data for the drop.
+ BookmarkDragData drop_data_;
+
+ // Used when a context menu is shown.
+ scoped_ptr<BookmarkContextMenu> context_menu_;
+
+ // The observer, may be null.
+ Observer* observer_;
+
+ // Is the menu being shown for a drop?
+ bool for_drop_;
+
+ DISALLOW_COPY_AND_ASSIGN(BookmarkMenuController);
+};
+
+#endif // CHROME_BROWSER_BOOKMARKS_BOOKMARK_MENU_CONTROLLER_H_
diff --git a/chrome/browser/bookmarks/bookmark_utils.cc b/chrome/browser/bookmarks/bookmark_utils.cc
index 2d33794..c9214b4 100644
--- a/chrome/browser/bookmarks/bookmark_utils.cc
+++ b/chrome/browser/bookmarks/bookmark_utils.cc
@@ -201,6 +201,63 @@ int PreferredDropOperation(int source_operations, int operations) {
return DragDropTypes::DRAG_NONE;
}
+int BookmarkDragOperation(BookmarkNode* node) {
+ if (node->is_url()) {
+ return DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE |
+ DragDropTypes::DRAG_LINK;
+ }
+ return DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE;
+}
+
+int BookmarkDropOperation(Profile* profile,
+ const views::DropTargetEvent& event,
+ const BookmarkDragData& data,
+ BookmarkNode* parent,
+ int index) {
+ if (data.IsFromProfile(profile) && data.size() > 1)
+ // Currently only accept one dragged node at a time.
+ return DragDropTypes::DRAG_NONE;
+
+ if (!bookmark_utils::IsValidDropLocation(profile, data, parent, index))
+ return DragDropTypes::DRAG_NONE;
+
+ if (data.GetFirstNode(profile)) {
+ // User is dragging from this profile: move.
+ return DragDropTypes::DRAG_MOVE;
+ }
+ // User is dragging from another app, copy.
+ return PreferredDropOperation(event.GetSourceOperations(),
+ DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK);
+}
+
+int PerformBookmarkDrop(Profile* profile,
+ const BookmarkDragData& data,
+ BookmarkNode* parent_node,
+ int index) {
+ BookmarkNode* dragged_node = data.GetFirstNode(profile);
+ BookmarkModel* model = profile->GetBookmarkModel();
+ if (dragged_node) {
+ // Drag from same profile, do a move.
+ model->Move(dragged_node, parent_node, index);
+ return DragDropTypes::DRAG_MOVE;
+ } else if (data.has_single_url()) {
+ // New URL, add it at the specified location.
+ std::wstring title = data.elements[0].title;
+ if (title.empty()) {
+ // No title, use the host.
+ title = UTF8ToWide(data.elements[0].url.host());
+ if (title.empty())
+ title = l10n_util::GetString(IDS_BOOMARK_BAR_UNKNOWN_DRAG_TITLE);
+ }
+ model->AddURL(parent_node, index, title, data.elements[0].url);
+ return DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK;
+ } else {
+ // Dropping a group from different profile. Always accept.
+ bookmark_utils::CloneDragData(model, data.elements, parent_node, index);
+ return DragDropTypes::DRAG_COPY;
+ }
+}
+
bool IsValidDropLocation(Profile* profile,
const BookmarkDragData& data,
BookmarkNode* drop_parent,
diff --git a/chrome/browser/bookmarks/bookmark_utils.h b/chrome/browser/bookmarks/bookmark_utils.h
index 9419731..26e60ef 100644
--- a/chrome/browser/bookmarks/bookmark_utils.h
+++ b/chrome/browser/bookmarks/bookmark_utils.h
@@ -17,6 +17,10 @@ class BookmarkNode;
class PageNavigator;
class Profile;
+namespace views {
+class DropTargetEvent;
+}
+
// A collection of bookmark utility functions used by various parts of the UI
// that show bookmarks: bookmark manager, bookmark bar view ...
namespace bookmark_utils {
@@ -26,6 +30,25 @@ namespace bookmark_utils {
// COPY, LINK then MOVE.
int PreferredDropOperation(int source_operations, int operations);
+// Returns the drag operations for the specified node.
+int BookmarkDragOperation(BookmarkNode* node);
+
+// Returns the preferred drop operation on a bookmark menu/bar.
+// |parent| is the parent node the drop is to occur on and |index| the index the
+// drop is over.
+int BookmarkDropOperation(Profile* profile,
+ const views::DropTargetEvent& event,
+ const BookmarkDragData& data,
+ BookmarkNode* parent,
+ int index);
+
+// Performs a drop of bookmark data onto |parent_node| at |index|. Returns the
+// type of drop the resulted.
+int PerformBookmarkDrop(Profile* profile,
+ const BookmarkDragData& data,
+ BookmarkNode* parent_node,
+ int index);
+
// Returns true if the bookmark data can be dropped on |drop_parent| at
// |index|. A drop from a separate profile is always allowed, where as
// a drop from the same profile is only allowed if none of the nodes in
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj
index da8341a..e5c0614 100644
--- a/chrome/browser/browser.vcproj
+++ b/chrome/browser/browser.vcproj
@@ -602,6 +602,14 @@
>
</File>
<File
+ RelativePath=".\bookmarks\bookmark_menu_controller.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\bookmarks\bookmark_menu_controller.h"
+ >
+ </File>
+ <File
RelativePath=".\bookmarks\bookmark_model.cc"
>
</File>
diff --git a/chrome/browser/views/bookmark_bar_view.cc b/chrome/browser/views/bookmark_bar_view.cc
index 4705051..dbfb38f 100644
--- a/chrome/browser/views/bookmark_bar_view.cc
+++ b/chrome/browser/views/bookmark_bar_view.cc
@@ -11,26 +11,17 @@
#include "chrome/browser/bookmarks/bookmark_context_menu.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/browser.h"
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/browser_window.h"
#include "chrome/browser/drag_utils.h"
-#include "chrome/browser/download/download_util.h"
#include "chrome/browser/extensions/extension.h"
#include "chrome/browser/extensions/extension_view.h"
#include "chrome/browser/extensions/extensions_service.h"
-#include "chrome/browser/history/history.h"
#include "chrome/browser/metrics/user_metrics.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/page_navigator.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/view_ids.h"
-#include "chrome/browser/views/bookmark_editor_view.h"
#include "chrome/browser/views/event_utils.h"
-#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/input_window.h"
#include "chrome/common/gfx/chrome_canvas.h"
-#include "chrome/common/gfx/favicon_size.h"
#include "chrome/common/gfx/text_elider.h"
#include "chrome/common/l10n_util.h"
#include "chrome/common/notification_service.h"
@@ -83,22 +74,12 @@ static const int kButtonPadding = 0;
// Command ids used in the menu allowing the user to choose when we're visible.
static const int kAlwaysShowCommandID = 1;
-// Whether the pref height has been calculated.
-static bool calcedSize = false;
-
-// The preferred height is the height needed for one button. As it is a constant
-// it is calculated once.
-static int prefButtonHeight = 0;
-
// Icon to display when one isn't found for the page.
static SkBitmap* kDefaultFavIcon = NULL;
// Icon used for folders.
static SkBitmap* kFolderIcon = NULL;
-// Icon used for most other menu.
-static SkBitmap* kBookmarkedOtherIcon = NULL;
-
// Background color.
static const SkColor kBackgroundColor = SkColorSetRGB(237, 244, 252);
@@ -203,15 +184,6 @@ static std::wstring CreateToolTipForURLAndTitle(const gfx::Point& screen_loc,
return result;
}
-// Returns the drag operations for the specified node.
-static int GetDragOperationsForNode(BookmarkNode* node) {
- if (node->GetType() == history::StarredEntry::URL) {
- return DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE |
- DragDropTypes::DRAG_LINK;
- }
- return DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE;
-}
-
// BookmarkButton -------------------------------------------------------------
// Buttons used for the bookmarks on the bookmark bar.
@@ -386,255 +358,8 @@ struct DropInfo {
BookmarkDragData data;
};
-// MenuRunner -----------------------------------------------------------------
-
-// MenuRunner manages creation and showing of a menu containing BookmarkNodes.
-// MenuRunner is used to show the contents of bookmark folders on the
-// bookmark bar, other folder, or overflow bookmarks.
-//
-class MenuRunner : public views::MenuDelegate,
- public BookmarkBarView::ModelChangedListener {
- public:
- // start_child_index is the index of the first child in node to add to the
- // menu.
- MenuRunner(BookmarkBarView* view, BookmarkNode* node, int start_child_index)
- : view_(view),
- node_(node),
- menu_(this) {
- int next_menu_id = 1;
- menu_id_to_node_map_[menu_.GetCommand()] = node;
- menu_.set_has_icons(true);
- BuildMenu(node, start_child_index, &menu_, &next_menu_id);
- }
-
- // Returns the node the menu is being run for.
- BookmarkNode* GetNode() {
- return node_;
- }
-
- void RunMenuAt(HWND hwnd,
- const gfx::Rect& bounds,
- MenuItemView::AnchorPosition position,
- bool for_drop) {
- view_->SetModelChangedListener(this);
- if (for_drop)
- menu_.RunMenuForDropAt(hwnd, bounds, position);
- else
- menu_.RunMenuAt(hwnd, bounds, position, false);
- view_->ClearModelChangedListenerIfEquals(this);
- }
-
- // Notification that the favicon has finished loading. Reset the icon
- // of the menu item.
- void FavIconLoaded(BookmarkNode* node) {
- if (node_to_menu_id_map_.find(node) !=
- node_to_menu_id_map_.end()) {
- menu_.SetIcon(node->GetFavIcon(), node_to_menu_id_map_[node]);
- }
- }
-
- virtual void ModelChanged() {
- menu_.Cancel();
- }
-
- MenuItemView* menu() { return &menu_; }
-
- MenuItemView* context_menu() {
- return context_menu_.get() ? context_menu_->menu() : NULL;
- }
-
- private:
- // Creates an entry in menu for each child node of parent starting at
- // start_child_index, recursively invoking this for any star groups.
- void BuildMenu(BookmarkNode* parent,
- int start_child_index,
- MenuItemView* menu,
- int* next_menu_id) {
- DCHECK(!parent->GetChildCount() ||
-
- start_child_index < parent->GetChildCount());
- for (int i = start_child_index; i < parent->GetChildCount(); ++i) {
- BookmarkNode* node = parent->GetChild(i);
- int id = *next_menu_id;
-
- (*next_menu_id)++;
- if (node->GetType() == history::StarredEntry::URL) {
- SkBitmap icon = node->GetFavIcon();
- if (icon.width() == 0)
- icon = *kDefaultFavIcon;
- menu->AppendMenuItemWithIcon(id, node->GetTitle(), icon);
- node_to_menu_id_map_[node] = id;
- } else {
- SkBitmap* folder_icon =
- ResourceBundle::GetSharedInstance().GetBitmapNamed(
- IDR_BOOKMARK_BAR_FOLDER);
- MenuItemView* submenu = menu->AppendSubMenuWithIcon(
- id, node->GetTitle(), *folder_icon);
- BuildMenu(node, 0, submenu, next_menu_id);
- }
- menu_id_to_node_map_[id] = node;
- }
- }
-
- // ViewMenuDelegate method. Overridden to forward to the PageNavigator so
- // that we accept any events that may trigger opening a url.
- virtual bool IsTriggerableEvent(const views::MouseEvent& e) {
- return event_utils::IsPossibleDispositionEvent(e);
- }
-
- // Invoked when a menu item is selected. Uses the PageNavigator set on
- // the BookmarkBarView to open the URL.
- virtual void ExecuteCommand(int id, int mouse_event_flags) {
- DCHECK(view_->GetPageNavigator());
- GURL url;
- DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end());
- url = menu_id_to_node_map_[id]->GetURL();
- view_->GetPageNavigator()->OpenURL(
- url, GURL(), event_utils::DispositionFromEventFlags(mouse_event_flags),
- PageTransition::AUTO_BOOKMARK);
- }
-
- virtual bool CanDrop(MenuItemView* menu, const OSExchangeData& data) {
- // Only accept drops of 1 node, which is the case for all data dragged from
- // bookmark bar and menus.
- if (!drop_data_.Read(data) || drop_data_.elements.size() != 1)
- return false;
-
- if (drop_data_.has_single_url())
- return true;
-
- BookmarkNode* drag_node = drop_data_.GetFirstNode(view_->GetProfile());
- if (!drag_node) {
- // Dragging a group from another profile, always accept.
- return true;
- }
- // 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.
- BookmarkNode* drop_node = menu_id_to_node_map_[menu->GetCommand()];
- DCHECK(drop_node);
- BookmarkNode* node = drop_node;
- while (drop_node && drop_node != drag_node)
- drop_node = drop_node->GetParent();
- return (drop_node == NULL);
- }
-
- virtual int GetDropOperation(MenuItemView* item,
- const views::DropTargetEvent& event,
- DropPosition* position) {
- DCHECK(drop_data_.is_valid());
- BookmarkNode* node = menu_id_to_node_map_[item->GetCommand()];
- BookmarkNode* drop_parent = node->GetParent();
- int index_to_drop_at = drop_parent->IndexOfChild(node);
- if (*position == DROP_AFTER) {
- index_to_drop_at++;
- } else if (*position == DROP_ON) {
- drop_parent = node;
- index_to_drop_at = node->GetChildCount();
- }
- DCHECK(drop_parent);
- return view_->CalculateDropOperation(event, drop_data_, drop_parent,
- index_to_drop_at);
- }
-
- virtual int OnPerformDrop(MenuItemView* menu,
- DropPosition position,
- const DropTargetEvent& event) {
- BookmarkNode* drop_node = menu_id_to_node_map_[menu->GetCommand()];
- DCHECK(drop_node);
- BookmarkModel* model = view_->GetModel();
- DCHECK(model);
- BookmarkNode* drop_parent = drop_node->GetParent();
- DCHECK(drop_parent);
- int index_to_drop_at = drop_parent->IndexOfChild(drop_node);
- if (position == DROP_AFTER) {
- index_to_drop_at++;
- } else if (position == DROP_ON) {
- DCHECK(drop_node->GetType() != history::StarredEntry::URL);
- drop_parent = drop_node;
- index_to_drop_at = drop_node->GetChildCount();
- }
-
- const int result = view_->PerformDropImpl(drop_data_, drop_parent,
- index_to_drop_at);
- if (view_->drop_menu_runner_.get() == this)
- view_->drop_menu_runner_.reset();
- // WARNING: we've been deleted!
- return result;
- }
-
- virtual bool ShowContextMenu(MenuItemView* source,
- int id,
- int x,
- int y,
- bool is_mouse_gesture) {
- DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end());
- std::vector<BookmarkNode*> nodes;
- nodes.push_back(menu_id_to_node_map_[id]);
- context_menu_.reset(
- new BookmarkContextMenu(view_->GetWidget()->GetHWND(),
- view_->GetProfile(),
- view_->browser(),
- view_->GetPageNavigator(),
- nodes[0]->GetParent(),
- nodes,
- BookmarkContextMenu::BOOKMARK_BAR));
- context_menu_->RunMenuAt(x, y);
- context_menu_.reset(NULL);
- return true;
- }
-
- virtual void DropMenuClosed(MenuItemView* menu) {
- if (view_->drop_menu_runner_.get() == this)
- view_->drop_menu_runner_.reset();
- }
-
- virtual bool CanDrag(MenuItemView* menu) {
- DCHECK(menu);
- return true;
- }
-
- virtual void WriteDragData(MenuItemView* sender, OSExchangeData* data) {
- DCHECK(sender && data);
-
- UserMetrics::RecordAction(L"BookmarkBar_DragFromFolder",
- view_->GetProfile());
-
- view_->WriteDragData(menu_id_to_node_map_[sender->GetCommand()], data);
- }
-
- virtual int GetDragOperations(MenuItemView* sender) {
- return GetDragOperationsForNode(
- menu_id_to_node_map_[sender->GetCommand()]);
- }
-
- // The node we're showing the contents of.
- BookmarkNode* node_;
-
- // The view that created us.
- BookmarkBarView* view_;
-
- // The menu.
- MenuItemView menu_;
-
- // Mapping from menu id to the BookmarkNode.
- std::map<int, BookmarkNode*> menu_id_to_node_map_;
-
- // Mapping from node to menu id. This only contains entries for nodes of type
- // URL.
- std::map<BookmarkNode*, int> node_to_menu_id_map_;
-
- // Data for the drop.
- BookmarkDragData drop_data_;
-
- scoped_ptr<BookmarkContextMenu> context_menu_;
-
- DISALLOW_COPY_AND_ASSIGN(MenuRunner);
-};
-
// ButtonSeparatorView --------------------------------------------------------
-// TODO(sky/glen): this is temporary, need to decide on what this should
-// look like.
class ButtonSeparatorView : public views::View {
public:
ButtonSeparatorView() {}
@@ -717,6 +442,8 @@ BookmarkBarView::BookmarkBarView(Profile* profile, Browser* browser)
browser_(browser),
page_navigator_(NULL),
model_(NULL),
+ bookmark_menu_(NULL),
+ bookmark_drop_menu_(NULL),
other_bookmarked_button_(NULL),
model_changed_listener_(NULL),
show_folder_drop_menu_task_(NULL),
@@ -729,7 +456,6 @@ BookmarkBarView::BookmarkBarView(Profile* profile, Browser* browser)
Init();
SetProfile(profile);
-
if (IsAlwaysShown()) {
size_animation_->Reset(1);
} else {
@@ -794,12 +520,6 @@ void BookmarkBarView::SetPageNavigator(PageNavigator* navigator) {
}
gfx::Size BookmarkBarView::GetPreferredSize() {
- if (!prefButtonHeight) {
- views::TextButton text_button(L"X");
- gfx::Size text_button_pref = text_button.GetMinimumSize();
- prefButtonHeight = static_cast<int>(text_button_pref.height());
- }
-
gfx::Size prefsize;
if (OnNewTabPage()) {
prefsize.set_height(kBarHeight + static_cast<int>(static_cast<double>
@@ -1089,7 +809,8 @@ int BookmarkBarView::OnDragUpdated(const DropTargetEvent& event) {
drop_info_->is_over_other = is_over_other;
if (drop_info_->is_menu_showing) {
- drop_menu_runner_.reset();
+ if (bookmark_drop_menu_)
+ bookmark_drop_menu_->Cancel();
drop_info_->is_menu_showing = false;
}
@@ -1125,7 +846,8 @@ void BookmarkBarView::OnDragExited() {
int BookmarkBarView::OnPerformDrop(const DropTargetEvent& event) {
StopShowFolderDropMenuTimer();
- drop_menu_runner_.reset();
+ if (bookmark_drop_menu_)
+ bookmark_drop_menu_->Cancel();
if (!drop_info_.get() || !drop_info_->drag_operation)
return DragDropTypes::DRAG_NONE;
@@ -1154,7 +876,7 @@ int BookmarkBarView::OnPerformDrop(const DropTargetEvent& event) {
} else {
parent_node = root;
}
- return PerformDropImpl(data, parent_node, index);
+ return bookmark_utils::PerformBookmarkDrop(profile_, data, parent_node, index);
}
void BookmarkBarView::OnFullscreenToggled(bool fullscreen) {
@@ -1192,29 +914,33 @@ void BookmarkBarView::AnimationEnded(const Animation* animation) {
SchedulePaint();
}
+void BookmarkBarView::BookmarkMenuDeleted(BookmarkMenuController* controller) {
+ if (controller == bookmark_menu_)
+ bookmark_menu_ = NULL;
+ else if (controller == bookmark_drop_menu_)
+ bookmark_drop_menu_ = NULL;
+}
+
views::TextButton* BookmarkBarView::GetBookmarkButton(int index) {
DCHECK(index >= 0 && index < GetBookmarkButtonCount());
return static_cast<views::TextButton*>(GetChildViewAt(index));
}
views::MenuItemView* BookmarkBarView::GetMenu() {
- return menu_runner_.get() ? menu_runner_->menu() : NULL;
+ return bookmark_menu_ ? bookmark_menu_->menu() : NULL;
}
views::MenuItemView* BookmarkBarView::GetContextMenu() {
- return menu_runner_.get() ? menu_runner_->context_menu() : NULL;
+ return bookmark_menu_ ? bookmark_menu_->context_menu() : NULL;
}
views::MenuItemView* BookmarkBarView::GetDropMenu() {
- return drop_menu_runner_.get() ? drop_menu_runner_->menu() : NULL;
+ return bookmark_drop_menu_ ? bookmark_drop_menu_->menu() : NULL;
}
void BookmarkBarView::Init() {
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- if (!calcedSize)
- calcedSize = false;
-
if (!kDefaultFavIcon)
kDefaultFavIcon = rb.GetBitmapNamed(IDR_DEFAULT_FAVICON);
@@ -1409,10 +1135,6 @@ void BookmarkBarView::BookmarkNodeChildrenReordered(BookmarkModel* model,
void BookmarkBarView::BookmarkNodeFavIconLoaded(BookmarkModel* model,
BookmarkNode* node) {
- if (menu_runner_.get())
- menu_runner_->FavIconLoaded(node);
- if (drop_menu_runner_.get())
- drop_menu_runner_->FavIconLoaded(node);
BookmarkNodeChangedImpl(model, node);
}
@@ -1447,7 +1169,7 @@ void BookmarkBarView::WriteDragData(BookmarkNode* node,
int BookmarkBarView::GetDragOperations(View* sender, int x, int y) {
for (int i = 0; i < GetBookmarkButtonCount(); ++i) {
if (sender == GetBookmarkButton(i)) {
- return GetDragOperationsForNode(
+ return bookmark_utils::BookmarkDragOperation(
model_->GetBookmarkBarNode()->GetChild(i));
}
}
@@ -1501,13 +1223,13 @@ void BookmarkBarView::RunMenu(views::View* view,
}
gfx::Point screen_loc(x, 0);
View::ConvertPointToScreen(this, &screen_loc);
- menu_runner_.reset(new MenuRunner(this, node, start_index));
- HWND parent_hwnd = GetWidget()->GetHWND();
- menu_runner_->RunMenuAt(parent_hwnd,
- gfx::Rect(screen_loc.x(), screen_loc.y(),
- view->width(), bar_height),
- anchor_point,
- false);
+ bookmark_menu_ = new BookmarkMenuController(
+ browser_, profile_, page_navigator_, GetWidget()->GetHWND(),
+ node, start_index);
+ bookmark_menu_->set_observer(this);
+ bookmark_menu_->RunMenuAt(gfx::Rect(screen_loc.x(), screen_loc.y(),
+ view->width(), bar_height),
+ anchor_point, false);
}
void BookmarkBarView::ButtonPressed(views::BaseButton* sender) {
@@ -1571,7 +1293,7 @@ void BookmarkBarView::ShowContextMenu(View* source,
}
views::View* BookmarkBarView::CreateBookmarkButton(BookmarkNode* node) {
- if (node->GetType() == history::StarredEntry::URL) {
+ if (node->is_url()) {
BookmarkButton* button = new BookmarkButton(node->GetURL(),
node->GetTitle(),
GetProfile());
@@ -1594,7 +1316,7 @@ void BookmarkBarView::ConfigureButton(BookmarkNode* node,
button->ClearMaxTextSize();
button->SetContextMenuController(this);
button->SetDragController(this);
- if (node->GetType() == history::StarredEntry::URL) {
+ if (node->is_url()) {
if (node->GetFavIcon().width() != 0)
button->SetIcon(node->GetFavIcon());
else
@@ -1682,9 +1404,12 @@ void BookmarkBarView::NotifyModelChanged() {
}
void BookmarkBarView::ShowDropFolderForNode(BookmarkNode* node) {
- if (drop_menu_runner_.get() && drop_menu_runner_->GetNode() == node) {
- // Already showing for the specified node.
- return;
+ if (bookmark_drop_menu_) {
+ if (bookmark_drop_menu_->node() == node) {
+ // Already showing for the specified node.
+ return;
+ }
+ bookmark_drop_menu_->Cancel();
}
int start_index = 0;
@@ -1723,11 +1448,13 @@ void BookmarkBarView::ShowDropFolderForNode(BookmarkNode* node) {
}
drop_info_->is_menu_showing = true;
- drop_menu_runner_.reset(new MenuRunner(this, node, start_index));
+ bookmark_drop_menu_ = new BookmarkMenuController(
+ browser_, profile_, page_navigator_, GetWidget()->GetHWND(),
+ node, start_index);
+ bookmark_drop_menu_->set_observer(this);
gfx::Point screen_loc;
View::ConvertPointToScreen(view_to_position_menu_from, &screen_loc);
- drop_menu_runner_->RunMenuAt(
- GetWidget()->GetHWND(),
+ bookmark_drop_menu_->RunMenuAt(
gfx::Rect(screen_loc.x(), screen_loc.y(),
view_to_position_menu_from->width(),
view_to_position_menu_from->height()),
@@ -1811,7 +1538,7 @@ int BookmarkBarView::CalculateDropOperation(const DropTargetEvent& event,
if (button_x < button_w) {
found = true;
BookmarkNode* node = model_->GetBookmarkBarNode()->GetChild(i);
- if (node->GetType() != history::StarredEntry::URL) {
+ if (node->is_folder()) {
if (button_x <= views::kDropBetweenPixels) {
*index = i;
} else if (button_x < button_w - views::kDropBetweenPixels) {
@@ -1859,7 +1586,8 @@ int BookmarkBarView::CalculateDropOperation(const DropTargetEvent& event,
*is_over_other ? model_->other_node() :
model_->GetBookmarkBarNode()->GetChild(*index);
int operation =
- CalculateDropOperation(event, data, parent, parent->GetChildCount());
+ bookmark_utils::BookmarkDropOperation(profile_,event, data, parent,
+ parent->GetChildCount());
if (!operation && !data.has_single_url() &&
data.GetFirstNode(profile_) == parent) {
// Don't open a menu if the node being dragged is the the menu to
@@ -1867,58 +1595,10 @@ int BookmarkBarView::CalculateDropOperation(const DropTargetEvent& event,
*drop_on = false;
}
return operation;
- } else {
- return CalculateDropOperation(event, data, model_->GetBookmarkBarNode(),
- *index);
- }
-}
-
-int BookmarkBarView::CalculateDropOperation(const DropTargetEvent& event,
- const BookmarkDragData& data,
- BookmarkNode* parent,
- int index) {
- if (data.IsFromProfile(profile_) && data.size() > 1)
- // Currently only accept one dragged node at a time.
- return DragDropTypes::DRAG_NONE;
-
- if (!bookmark_utils::IsValidDropLocation(profile_, data, parent, index))
- return DragDropTypes::DRAG_NONE;
-
- if (data.GetFirstNode(profile_)) {
- // User is dragging from this profile: move.
- return DragDropTypes::DRAG_MOVE;
- } else {
- // User is dragging from another app, copy.
- return bookmark_utils::PreferredDropOperation(
- event.GetSourceOperations(),
- DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK);
- }
-}
-
-int BookmarkBarView::PerformDropImpl(const BookmarkDragData& data,
- BookmarkNode* parent_node,
- int index) {
- BookmarkNode* dragged_node = data.GetFirstNode(profile_);
- if (dragged_node) {
- // Drag from same profile, do a move.
- model_->Move(dragged_node, parent_node, index);
- return DragDropTypes::DRAG_MOVE;
- } else if (data.has_single_url()) {
- // New URL, add it at the specified location.
- std::wstring title = data.elements[0].title;
- if (title.empty()) {
- // No title, use the host.
- title = UTF8ToWide(data.elements[0].url.host());
- if (title.empty())
- title = l10n_util::GetString(IDS_BOOMARK_BAR_UNKNOWN_DRAG_TITLE);
- }
- model_->AddURL(parent_node, index, title, data.elements[0].url);
- return DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK;
- } else {
- // Dropping a group from different profile. Always accept.
- bookmark_utils::CloneDragData(model_, data.elements, parent_node, index);
- return DragDropTypes::DRAG_COPY;
}
+ return bookmark_utils::BookmarkDropOperation(profile_, event, data,
+ model_->GetBookmarkBarNode(),
+ *index);
}
int BookmarkBarView::GetFirstHiddenNodeIndex() {
diff --git a/chrome/browser/views/bookmark_bar_view.h b/chrome/browser/views/bookmark_bar_view.h
index 5982fbf..8b42251 100644
--- a/chrome/browser/views/bookmark_bar_view.h
+++ b/chrome/browser/views/bookmark_bar_view.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_VIEWS_BOOKMARK_BAR_VIEW_H_
#include "chrome/browser/bookmarks/bookmark_drag_data.h"
+#include "chrome/browser/bookmarks/bookmark_menu_controller.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/common/slide_animation.h"
@@ -44,8 +45,8 @@ class BookmarkBarView : public views::View,
public NotificationObserver,
public views::ContextMenuController,
public views::DragController,
- public AnimationDelegate {
- friend class MenuRunner;
+ public AnimationDelegate,
+ public BookmarkMenuController::Observer {
friend class ShowFolderMenuTask;
public:
@@ -153,6 +154,9 @@ class BookmarkBarView : public views::View,
void AnimationProgressed(const Animation* animation);
void AnimationEnded(const Animation* animation);
+ // BookmarkMenuController::Observer
+ virtual void BookmarkMenuDeleted(BookmarkMenuController* controller);
+
// Returns the button at the specified index.
views::TextButton* GetBookmarkButton(int index);
@@ -359,19 +363,6 @@ class BookmarkBarView : public views::View,
bool* is_over_overflow,
bool* is_over_other);
- // Invokes CanDropAt to determine if this is a valid location for the data,
- // then returns the appropriate drag operation based on the data.
- int CalculateDropOperation(const views::DropTargetEvent& event,
- const BookmarkDragData& data,
- BookmarkNode* parent,
- int index);
-
- // Performs a drop of the specified data at the specified location. Returns
- // the result.
- int PerformDropImpl(const BookmarkDragData& data,
- BookmarkNode* parent_node,
- int index);
-
// Returns the index of the first hidden bookmark button. If all buttons are
// visible, this returns GetBookmarkButtonCount().
int GetFirstHiddenNodeIndex();
@@ -399,14 +390,14 @@ class BookmarkBarView : public views::View,
// shown. This is owned by the Profile.
BookmarkModel* model_;
- // Used to manage showing a Menu: either for the most recently bookmarked
+ // Used to manage showing a Menu, either for the most recently bookmarked
// entries, or for the a starred group.
- scoped_ptr<MenuRunner> menu_runner_;
+ BookmarkMenuController* bookmark_menu_;
// Used when showing a menu for drag and drop. That is, if the user drags
- // over a group this becomes non-null and is the MenuRunner used to manage
- // the menu showing the contents of the node.
- scoped_ptr<MenuRunner> drop_menu_runner_;
+ // over a group this becomes non-null and manages the menu showing the
+ // contents of the node.
+ BookmarkMenuController* bookmark_drop_menu_;
// Shows the other bookmark entries.
views::MenuButton* other_bookmarked_button_;
diff --git a/chrome/views/chrome_menu.cc b/chrome/views/chrome_menu.cc
index 6c038a5..ef33e6a 100644
--- a/chrome/views/chrome_menu.cc
+++ b/chrome/views/chrome_menu.cc
@@ -794,6 +794,7 @@ SubmenuView::SubmenuView(MenuItemView* parent)
: parent_menu_item_(parent),
host_(NULL),
drop_item_(NULL),
+ drop_position_(MenuDelegate::DROP_NONE),
scroll_view_container_(NULL) {
DCHECK(parent);
// We'll delete ourselves, otherwise the ScrollView would delete us on close.