bookmark_drag_drop_views.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/message_loop/message_loop.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_node_data.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/pref_names.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/user_prefs/user_prefs.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/dragdrop/drag_drop_types.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/dragdrop/os_exchange_data.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/events/event.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/drag_utils.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/widget/widget.h" 197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chrome { 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragBookmarks(Profile* profile, 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<const BookmarkNode*>& nodes, 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::NativeView view, 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::DragDropTypes::DragEventSource source) { 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!nodes.empty()); 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Set up our OLE machinery 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::OSExchangeData data; 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BookmarkNodeData drag_data(nodes); 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) drag_data.Write(profile, &data); 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Allow nested message loop so we get DnD events as we drag this around. 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool was_nested = base::MessageLoop::current()->IsNested(); 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::MessageLoop::current()->SetNestableTasksAllowed(true); 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int operation = ui::DragDropTypes::DRAG_COPY | 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::DragDropTypes::DRAG_MOVE | 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::DragDropTypes::DRAG_LINK; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::Widget* widget = views::Widget::GetWidgetForNativeView(view); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (widget) { 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) widget->RunShellDrag(NULL, data, gfx::Point(), operation, source); 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We hit this case when we're using WebContentsViewWin or 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // WebContentsViewAura, instead of WebContentsViewViews. 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::RunShellDrag(view, data, gfx::Point(), operation, source); 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::MessageLoop::current()->SetNestableTasksAllowed(was_nested); 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int GetBookmarkDragOperation(content::BrowserContext* browser_context, 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BookmarkNode* node) { 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PrefService* prefs = user_prefs::UserPrefs::Get(browser_context); 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int move = ui::DragDropTypes::DRAG_MOVE; 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!prefs->GetBoolean(prefs::kEditBookmarksEnabled)) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) move = ui::DragDropTypes::DRAG_NONE; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (node->is_url()) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK | move; 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ui::DragDropTypes::DRAG_COPY | move; 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int GetPreferredBookmarkDropOperation(int source_operations, int operations) { 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int common_ops = (source_operations & operations); 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!common_ops) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ui::DragDropTypes::DRAG_NONE; 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ui::DragDropTypes::DRAG_COPY & common_ops) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ui::DragDropTypes::DRAG_COPY; 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ui::DragDropTypes::DRAG_LINK & common_ops) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ui::DragDropTypes::DRAG_LINK; 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ui::DragDropTypes::DRAG_MOVE & common_ops) 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ui::DragDropTypes::DRAG_MOVE; 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ui::DragDropTypes::DRAG_NONE; 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int GetBookmarkDropOperation(Profile* profile, 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ui::DropTargetEvent& event, 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BookmarkNodeData& data, 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BookmarkNode* parent, 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int index) { 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data.IsFromProfile(profile) && data.size() > 1) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Currently only accept one dragged node at a time. 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ui::DragDropTypes::DRAG_NONE; 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!IsValidBookmarkDropLocation(profile, data, parent, index)) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ui::DragDropTypes::DRAG_NONE; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data.GetFirstNode(profile)) 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // User is dragging from this profile: move. 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ui::DragDropTypes::DRAG_MOVE; 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // User is dragging from another app, copy. 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GetPreferredBookmarkDropOperation(event.source_operations(), 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsValidBookmarkDropLocation(Profile* profile, 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BookmarkNodeData& data, 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BookmarkNode* drop_parent, 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int index) { 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!drop_parent->is_folder()) { 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!data.is_valid()) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data.IsFromProfile(profile)) { 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<const BookmarkNode*> nodes = data.GetNodes(profile); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < nodes.size(); ++i) { 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Don't allow the drop if the user is attempting to drop on one of the 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // nodes being dragged. 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BookmarkNode* node = nodes[i]; 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int node_index = (drop_parent == node->parent()) ? 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) drop_parent->GetIndexOf(nodes[i]) : -1; 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (node_index != -1 && (index == node_index || index == node_index + 1)) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // drop_parent can't accept a child that is an ancestor. 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (drop_parent->HasAncestor(node)) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // From the same profile, always accept. 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace chrome 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)