summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-24 01:54:26 +0000
committersky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-24 01:54:26 +0000
commit9eb381798e60beac696ba13855b85691e9d22fb7 (patch)
tree9b1c83fcd7f442f06c5279b6730492d5d3fdef0d
parent4e8d907dd01011dd67fdf7661d98c7cbc663b0ff (diff)
downloadchromium_src-9eb381798e60beac696ba13855b85691e9d22fb7.zip
chromium_src-9eb381798e60beac696ba13855b85691e9d22fb7.tar.gz
chromium_src-9eb381798e60beac696ba13855b85691e9d22fb7.tar.bz2
Refactors some of the bookmark drag and drop code into a separate
class that I can use in the bookmark manager. BUG=674 TEST=make sure drag and drop on the bookmark bar still works, especially when moving folders around. Review URL: http://codereview.chromium.org/8115 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3896 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/bookmarks/bookmark_drag_data.cc6
-rw-r--r--chrome/browser/bookmarks/bookmark_drag_data.h5
-rw-r--r--chrome/browser/bookmarks/bookmark_drag_utils.cc91
-rw-r--r--chrome/browser/bookmarks/bookmark_drag_utils.h45
-rw-r--r--chrome/browser/views/bookmark_bar_view.cc65
-rw-r--r--chrome/browser/views/bookmark_bar_view.h13
6 files changed, 155 insertions, 70 deletions
diff --git a/chrome/browser/bookmarks/bookmark_drag_data.cc b/chrome/browser/bookmarks/bookmark_drag_data.cc
index 65d3445..85911a7 100644
--- a/chrome/browser/bookmarks/bookmark_drag_data.cc
+++ b/chrome/browser/bookmarks/bookmark_drag_data.cc
@@ -135,7 +135,7 @@ bool BookmarkDragData::Read(const OSExchangeData& data) {
std::vector<BookmarkNode*> BookmarkDragData::GetNodes(Profile* profile) const {
std::vector<BookmarkNode*> nodes;
- if (profile->GetPath() != profile_path_)
+ if (!IsFromProfile(profile))
return nodes;
for (size_t i = 0; i < elements.size(); ++i) {
@@ -154,3 +154,7 @@ BookmarkNode* BookmarkDragData::GetFirstNode(Profile* profile) const {
std::vector<BookmarkNode*> nodes = GetNodes(profile);
return nodes.size() == 1 ? nodes[0] : NULL;
}
+
+bool BookmarkDragData::IsFromProfile(Profile* profile) const {
+ return (profile->GetPath() == profile_path_);
+}
diff --git a/chrome/browser/bookmarks/bookmark_drag_data.h b/chrome/browser/bookmarks/bookmark_drag_data.h
index 10d269b..263bf8d 100644
--- a/chrome/browser/bookmarks/bookmark_drag_data.h
+++ b/chrome/browser/bookmarks/bookmark_drag_data.h
@@ -96,7 +96,10 @@ struct BookmarkDragData {
bool has_single_url() const { return is_valid() && elements[0].is_url; }
// Number of elements.
- size_t size() { return elements.size(); }
+ size_t size() const { return elements.size(); }
+
+ // Returns true if this data is from the specified profile.
+ bool IsFromProfile(Profile* profile) const;
// The actual elements written to the clipboard.
std::vector<Element> elements;
diff --git a/chrome/browser/bookmarks/bookmark_drag_utils.cc b/chrome/browser/bookmarks/bookmark_drag_utils.cc
new file mode 100644
index 0000000..863369c
--- /dev/null
+++ b/chrome/browser/bookmarks/bookmark_drag_utils.cc
@@ -0,0 +1,91 @@
+// Copyright (c) 2006-2008 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_drag_utils.h"
+
+#include "chrome/browser/bookmarks/bookmark_drag_data.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/common/drag_drop_types.h"
+#include "chrome/views/event.h"
+
+namespace {
+
+void CloneDragDataImpl(BookmarkModel* model,
+ const BookmarkDragData::Element& element,
+ BookmarkNode* parent,
+ int index_to_add_at) {
+ if (element.is_url) {
+ model->AddURL(parent, index_to_add_at, element.title, element.url);
+ } else {
+ BookmarkNode* new_folder = model->AddGroup(parent, index_to_add_at,
+ element.title);
+ for (int i = 0; i < static_cast<int>(element.children.size()); ++i)
+ CloneDragDataImpl(model, element.children[i], new_folder, i);
+ }
+}
+
+} // namespace
+
+namespace bookmark_drag_utils {
+
+int PreferredDropOperation(const views::DropTargetEvent& event,
+ int operation) {
+ int common_ops = (event.GetSourceOperations() & operation);
+ if (!common_ops)
+ return 0;
+ if (DragDropTypes::DRAG_COPY & common_ops)
+ return DragDropTypes::DRAG_COPY;
+ if (DragDropTypes::DRAG_LINK & common_ops)
+ return DragDropTypes::DRAG_LINK;
+ if (DragDropTypes::DRAG_MOVE & common_ops)
+ return DragDropTypes::DRAG_MOVE;
+ return DragDropTypes::DRAG_NONE;
+}
+
+bool IsValidDropLocation(Profile* profile,
+ const BookmarkDragData& data,
+ BookmarkNode* drop_parent,
+ int index) {
+ if (!drop_parent->is_folder()) {
+ NOTREACHED();
+ return false;
+ }
+
+ if (!data.is_valid())
+ return false;
+
+ if (data.IsFromProfile(profile)) {
+ std::vector<BookmarkNode*> nodes = data.GetNodes(profile);
+ for (size_t i = 0; i < nodes.size(); ++i) {
+ // Don't allow the drop if the user is attempting to drop on one of the
+ // nodes being dragged.
+ BookmarkNode* node = nodes[i];
+ int node_index = (drop_parent == node->GetParent()) ?
+ drop_parent->IndexOfChild(nodes[i]) : -1;
+ if (node_index != -1 && (index == node_index || index == node_index + 1))
+ return false;
+
+ // drop_parent can't accept a child that is an ancestor.
+ if (drop_parent->HasAncestor(node))
+ return false;
+ }
+ return true;
+ }
+ // From the same profile, always accept.
+ return true;
+}
+
+void CloneDragData(BookmarkModel* model,
+ const std::vector<BookmarkDragData::Element>& elements,
+ BookmarkNode* parent,
+ int index_to_add_at) {
+ if (!parent->is_folder() || !model) {
+ NOTREACHED();
+ return;
+ }
+ for (size_t i = 0; i < elements.size(); ++i)
+ CloneDragDataImpl(model, elements[i], parent, index_to_add_at + i);
+}
+
+} // namespace bookmark_drag_utils
diff --git a/chrome/browser/bookmarks/bookmark_drag_utils.h b/chrome/browser/bookmarks/bookmark_drag_utils.h
new file mode 100644
index 0000000..2805311
--- /dev/null
+++ b/chrome/browser/bookmarks/bookmark_drag_utils.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2006-2008 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_DRAG_UTILS_H_
+#define CHROME_BROWSER_BOOKMARKS_BOOKMARK_DRAG_UTILS_H_
+
+#include "chrome/browser/bookmarks/bookmark_drag_data.h"
+
+class BookmarkNode;
+class Profile;
+
+namespace views {
+class DropTargetEvent;
+}
+
+// Functions used in managing bookmark drag and drop. These functions are
+// used by both the bookmark bar and bookmark manager.
+namespace bookmark_drag_utils {
+
+// Calculates the drop operation given the event and supported set of
+// operations. This prefers the following ordering: COPY, LINK then MOVE.
+int PreferredDropOperation(const views::DropTargetEvent& event,
+ int operation);
+
+// 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
+// |data| are an ancestor of |drop_parent| and one of the nodes isn't already
+// a child of |drop_parent| at |index|.
+bool IsValidDropLocation(Profile* profile,
+ const BookmarkDragData& data,
+ BookmarkNode* drop_parent,
+ int index);
+
+// Clones drag data, adding newly created nodes to |parent| starting at
+// |index_to_add_at|.
+void CloneDragData(BookmarkModel* model,
+ const std::vector<BookmarkDragData::Element>& elements,
+ BookmarkNode* parent,
+ int index_to_add_at);
+
+}
+
+#endif // CHROME_BROWSER_BOOKMARKS_BOOKMARK_DRAG_UTILS_H_
diff --git a/chrome/browser/views/bookmark_bar_view.cc b/chrome/browser/views/bookmark_bar_view.cc
index 457339c..28d6b98 100644
--- a/chrome/browser/views/bookmark_bar_view.cc
+++ b/chrome/browser/views/bookmark_bar_view.cc
@@ -10,6 +10,7 @@
#include "base/gfx/skia_utils.h"
#include "chrome/app/theme/theme_resources.h"
#include "chrome/browser/bookmark_bar_context_menu_controller.h"
+#include "chrome/browser/bookmarks/bookmark_drag_utils.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
@@ -148,21 +149,6 @@ static const int kOtherFolderButtonTag = 1;
namespace {
-// Calculates the drop operation given the event and supported set of
-// operations.
-int PreferredDropOperation(const DropTargetEvent& event, int operation) {
- int common_ops = (event.GetSourceOperations() & operation);
- if (!common_ops)
- return 0;
- if (DragDropTypes::DRAG_COPY & common_ops)
- return DragDropTypes::DRAG_COPY;
- if (DragDropTypes::DRAG_LINK & common_ops)
- return DragDropTypes::DRAG_LINK;
- if (DragDropTypes::DRAG_MOVE & common_ops)
- return DragDropTypes::DRAG_MOVE;
- return DragDropTypes::DRAG_NONE;
-}
-
// Returns the tooltip text for the specified url and title. The returned
// text is clipped to fit within the bounds of the monitor.
//
@@ -1666,7 +1652,7 @@ int BookmarkBarView::CalculateDropOperation(const DropTargetEvent& event,
int ops = data.GetFirstNode(profile_)
? DragDropTypes::DRAG_MOVE
: DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK;
- return PreferredDropOperation(event, ops);
+ return bookmark_drag_utils::PreferredDropOperation(event, ops);
}
for (int i = 0; i < GetBookmarkButtonCount() &&
@@ -1743,7 +1729,11 @@ int BookmarkBarView::CalculateDropOperation(const DropTargetEvent& event,
const BookmarkDragData& data,
BookmarkNode* parent,
int index) {
- if (!CanDropAt(data, parent, index))
+ if (data.IsFromProfile(profile_) && data.size() > 1)
+ // Currently only accept one dragged node at a time.
+ return DragDropTypes::DRAG_NONE;
+
+ if (!bookmark_drag_utils::IsValidDropLocation(profile_, data, parent, index))
return DragDropTypes::DRAG_NONE;
if (data.GetFirstNode(profile_)) {
@@ -1751,33 +1741,11 @@ int BookmarkBarView::CalculateDropOperation(const DropTargetEvent& event,
return DragDropTypes::DRAG_MOVE;
} else {
// User is dragging from another app, copy.
- return PreferredDropOperation(
+ return bookmark_drag_utils::PreferredDropOperation(
event, DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK);
}
}
-bool BookmarkBarView::CanDropAt(const BookmarkDragData& data,
- BookmarkNode* parent,
- int index) {
- DCHECK(data.is_valid());
- BookmarkNode* dragged_node = data.GetFirstNode(profile_);
- if (dragged_node) {
- if (dragged_node->GetParent() == parent) {
- const int existing_index = parent->IndexOfChild(dragged_node);
- if (index == existing_index || existing_index + 1 == index)
- return false;
- }
- // Allow the drop only if the node we're going to drop on isn't a
- // descendant of the dragged node.
- BookmarkNode* test_node = parent;
- while (test_node && test_node != dragged_node)
- test_node = test_node->GetParent();
- return (test_node == NULL);
- } // else case clones, always allow.
- return true;
-}
-
-
int BookmarkBarView::PerformDropImpl(const BookmarkDragData& data,
BookmarkNode* parent_node,
int index) {
@@ -1799,25 +1767,12 @@ int BookmarkBarView::PerformDropImpl(const BookmarkDragData& data,
return DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK;
} else {
// Dropping a group from different profile. Always accept.
- CloneDragData(data.elements[0], parent_node, index);
+ bookmark_drag_utils::CloneDragData(model_, data.elements, parent_node,
+ index);
return DragDropTypes::DRAG_COPY;
}
}
-void BookmarkBarView::CloneDragData(const BookmarkDragData::Element& element,
- BookmarkNode* parent,
- int index_to_add_at) {
- DCHECK(model_);
- if (element.is_url) {
- model_->AddURL(parent, index_to_add_at, element.title, element.url);
- } else {
- BookmarkNode* new_folder = model_->AddGroup(parent, index_to_add_at,
- element.title);
- for (int i = 0; i < static_cast<int>(element.children.size()); ++i)
- CloneDragData(element.children[i], new_folder, i);
- }
-}
-
int BookmarkBarView::GetFirstHiddenNodeIndex() {
const int bb_count = GetBookmarkButtonCount();
for (int i = 0; i < bb_count; ++i) {
diff --git a/chrome/browser/views/bookmark_bar_view.h b/chrome/browser/views/bookmark_bar_view.h
index c5480ff..242a7f2 100644
--- a/chrome/browser/views/bookmark_bar_view.h
+++ b/chrome/browser/views/bookmark_bar_view.h
@@ -352,25 +352,12 @@ class BookmarkBarView : public views::View,
BookmarkNode* parent,
int index);
- // Returns true if the specified location is a valid drop location for
- // the supplied drag data.
- bool CanDropAt(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);
- // Creates a new group/entry for data, and recursively invokes itself for
- // all children of data. This is used during drag and drop to clone a
- // group from another profile.
- void CloneDragData(const BookmarkDragData::Element& data,
- BookmarkNode* parent,
- int index_to_add_at);
-
// Returns the index of the first hidden bookmark button. If all buttons are
// visible, this returns GetBookmarkButtonCount().
int GetFirstHiddenNodeIndex();