1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/prefs/pref_service.h"
9 #include "chrome/browser/bookmarks/bookmark_model.h"
10 #include "chrome/browser/bookmarks/bookmark_node_data.h"
11 #include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
12 #include "chrome/common/pref_names.h"
13 #include "components/user_prefs/user_prefs.h"
14 #include "ui/base/dragdrop/drag_drop_types.h"
15 #include "ui/base/dragdrop/os_exchange_data.h"
16 #include "ui/events/event.h"
17 #include "ui/views/drag_utils.h"
18 #include "ui/views/widget/widget.h"
22 void DragBookmarks(Profile
* profile
,
23 const std::vector
<const BookmarkNode
*>& nodes
,
25 ui::DragDropTypes::DragEventSource source
) {
26 DCHECK(!nodes
.empty());
28 // Set up our OLE machinery
29 ui::OSExchangeData data
;
30 BookmarkNodeData
drag_data(nodes
);
31 drag_data
.Write(profile
, &data
);
33 // Allow nested message loop so we get DnD events as we drag this around.
34 bool was_nested
= base::MessageLoop::current()->IsNested();
35 base::MessageLoop::current()->SetNestableTasksAllowed(true);
37 int operation
= ui::DragDropTypes::DRAG_COPY
|
38 ui::DragDropTypes::DRAG_MOVE
|
39 ui::DragDropTypes::DRAG_LINK
;
40 views::Widget
* widget
= views::Widget::GetWidgetForNativeView(view
);
43 widget
->RunShellDrag(NULL
, data
, gfx::Point(), operation
, source
);
45 // We hit this case when we're using WebContentsViewWin or
46 // WebContentsViewAura, instead of WebContentsViewViews.
47 views::RunShellDrag(view
, data
, gfx::Point(), operation
, source
);
50 base::MessageLoop::current()->SetNestableTasksAllowed(was_nested
);
53 int GetBookmarkDragOperation(content::BrowserContext
* browser_context
,
54 const BookmarkNode
* node
) {
55 PrefService
* prefs
= user_prefs::UserPrefs::Get(browser_context
);
57 int move
= ui::DragDropTypes::DRAG_MOVE
;
58 if (!prefs
->GetBoolean(prefs::kEditBookmarksEnabled
))
59 move
= ui::DragDropTypes::DRAG_NONE
;
61 return ui::DragDropTypes::DRAG_COPY
| ui::DragDropTypes::DRAG_LINK
| move
;
62 return ui::DragDropTypes::DRAG_COPY
| move
;
65 int GetPreferredBookmarkDropOperation(int source_operations
, int operations
) {
66 int common_ops
= (source_operations
& operations
);
68 return ui::DragDropTypes::DRAG_NONE
;
69 if (ui::DragDropTypes::DRAG_COPY
& common_ops
)
70 return ui::DragDropTypes::DRAG_COPY
;
71 if (ui::DragDropTypes::DRAG_LINK
& common_ops
)
72 return ui::DragDropTypes::DRAG_LINK
;
73 if (ui::DragDropTypes::DRAG_MOVE
& common_ops
)
74 return ui::DragDropTypes::DRAG_MOVE
;
75 return ui::DragDropTypes::DRAG_NONE
;
78 int GetBookmarkDropOperation(Profile
* profile
,
79 const ui::DropTargetEvent
& event
,
80 const BookmarkNodeData
& data
,
81 const BookmarkNode
* parent
,
83 if (data
.IsFromProfile(profile
) && data
.size() > 1)
84 // Currently only accept one dragged node at a time.
85 return ui::DragDropTypes::DRAG_NONE
;
87 if (!IsValidBookmarkDropLocation(profile
, data
, parent
, index
))
88 return ui::DragDropTypes::DRAG_NONE
;
90 if (data
.GetFirstNode(profile
))
91 // User is dragging from this profile: move.
92 return ui::DragDropTypes::DRAG_MOVE
;
94 // User is dragging from another app, copy.
95 return GetPreferredBookmarkDropOperation(event
.source_operations(),
96 ui::DragDropTypes::DRAG_COPY
| ui::DragDropTypes::DRAG_LINK
);
99 bool IsValidBookmarkDropLocation(Profile
* profile
,
100 const BookmarkNodeData
& data
,
101 const BookmarkNode
* drop_parent
,
103 if (!drop_parent
->is_folder()) {
108 if (!data
.is_valid())
111 if (data
.IsFromProfile(profile
)) {
112 std::vector
<const BookmarkNode
*> nodes
= data
.GetNodes(profile
);
113 for (size_t i
= 0; i
< nodes
.size(); ++i
) {
114 // Don't allow the drop if the user is attempting to drop on one of the
115 // nodes being dragged.
116 const BookmarkNode
* node
= nodes
[i
];
117 int node_index
= (drop_parent
== node
->parent()) ?
118 drop_parent
->GetIndexOf(nodes
[i
]) : -1;
119 if (node_index
!= -1 && (index
== node_index
|| index
== node_index
+ 1))
122 // drop_parent can't accept a child that is an ancestor.
123 if (drop_parent
->HasAncestor(node
))
128 // From the same profile, always accept.
132 } // namespace chrome