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
,
24 gfx::NativeView view
) {
25 DCHECK(!nodes
.empty());
27 // Set up our OLE machinery
28 ui::OSExchangeData data
;
29 BookmarkNodeData
drag_data(nodes
);
30 drag_data
.Write(profile
, &data
);
32 // Allow nested message loop so we get DnD events as we drag this around.
33 bool was_nested
= base::MessageLoop::current()->IsNested();
34 base::MessageLoop::current()->SetNestableTasksAllowed(true);
36 int operation
= ui::DragDropTypes::DRAG_COPY
|
37 ui::DragDropTypes::DRAG_MOVE
|
38 ui::DragDropTypes::DRAG_LINK
;
39 views::Widget
* widget
= views::Widget::GetWidgetForNativeView(view
);
40 // TODO(varunjain): Properly determine and send DRAG_EVENT_SOURCE below.
42 widget
->RunShellDrag(NULL
, data
, gfx::Point(), operation
,
43 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE
);
45 // We hit this case when we're using WebContentsViewWin or
46 // WebContentsViewAura, instead of WebContentsViewViews.
47 views::RunShellDrag(view
, data
, gfx::Point(), operation
,
48 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE
);
51 base::MessageLoop::current()->SetNestableTasksAllowed(was_nested
);
54 int GetBookmarkDragOperation(content::BrowserContext
* browser_context
,
55 const BookmarkNode
* node
) {
56 PrefService
* prefs
= user_prefs::UserPrefs::Get(browser_context
);
58 int move
= ui::DragDropTypes::DRAG_MOVE
;
59 if (!prefs
->GetBoolean(prefs::kEditBookmarksEnabled
))
60 move
= ui::DragDropTypes::DRAG_NONE
;
62 return ui::DragDropTypes::DRAG_COPY
| ui::DragDropTypes::DRAG_LINK
| move
;
63 return ui::DragDropTypes::DRAG_COPY
| move
;
66 int GetPreferredBookmarkDropOperation(int source_operations
, int operations
) {
67 int common_ops
= (source_operations
& operations
);
69 return ui::DragDropTypes::DRAG_NONE
;
70 if (ui::DragDropTypes::DRAG_COPY
& common_ops
)
71 return ui::DragDropTypes::DRAG_COPY
;
72 if (ui::DragDropTypes::DRAG_LINK
& common_ops
)
73 return ui::DragDropTypes::DRAG_LINK
;
74 if (ui::DragDropTypes::DRAG_MOVE
& common_ops
)
75 return ui::DragDropTypes::DRAG_MOVE
;
76 return ui::DragDropTypes::DRAG_NONE
;
79 int GetBookmarkDropOperation(Profile
* profile
,
80 const ui::DropTargetEvent
& event
,
81 const BookmarkNodeData
& data
,
82 const BookmarkNode
* parent
,
84 if (data
.IsFromProfile(profile
) && data
.size() > 1)
85 // Currently only accept one dragged node at a time.
86 return ui::DragDropTypes::DRAG_NONE
;
88 if (!IsValidBookmarkDropLocation(profile
, data
, parent
, index
))
89 return ui::DragDropTypes::DRAG_NONE
;
91 if (data
.GetFirstNode(profile
))
92 // User is dragging from this profile: move.
93 return ui::DragDropTypes::DRAG_MOVE
;
95 // User is dragging from another app, copy.
96 return GetPreferredBookmarkDropOperation(event
.source_operations(),
97 ui::DragDropTypes::DRAG_COPY
| ui::DragDropTypes::DRAG_LINK
);
100 bool IsValidBookmarkDropLocation(Profile
* profile
,
101 const BookmarkNodeData
& data
,
102 const BookmarkNode
* drop_parent
,
104 if (!drop_parent
->is_folder()) {
109 if (!data
.is_valid())
112 if (data
.IsFromProfile(profile
)) {
113 std::vector
<const BookmarkNode
*> nodes
= data
.GetNodes(profile
);
114 for (size_t i
= 0; i
< nodes
.size(); ++i
) {
115 // Don't allow the drop if the user is attempting to drop on one of the
116 // nodes being dragged.
117 const BookmarkNode
* node
= nodes
[i
];
118 int node_index
= (drop_parent
== node
->parent()) ?
119 drop_parent
->GetIndexOf(nodes
[i
]) : -1;
120 if (node_index
!= -1 && (index
== node_index
|| index
== node_index
+ 1))
123 // drop_parent can't accept a child that is an ancestor.
124 if (drop_parent
->HasAncestor(node
))
129 // From the same profile, always accept.
133 } // namespace chrome