root/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. DragBookmarks
  2. GetBookmarkDragOperation
  3. GetPreferredBookmarkDropOperation
  4. GetBookmarkDropOperation
  5. IsValidBookmarkDropLocation

// Copyright 2012 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/ui/views/bookmarks/bookmark_drag_drop_views.h"

#include "base/message_loop/message_loop.h"
#include "base/prefs/pref_service.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_node_data.h"
#include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
#include "chrome/common/pref_names.h"
#include "components/user_prefs/user_prefs.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/events/event.h"
#include "ui/views/drag_utils.h"
#include "ui/views/widget/widget.h"

namespace chrome {

void DragBookmarks(Profile* profile,
                   const std::vector<const BookmarkNode*>& nodes,
                   gfx::NativeView view,
                   ui::DragDropTypes::DragEventSource source) {
  DCHECK(!nodes.empty());

  // Set up our OLE machinery
  ui::OSExchangeData data;
  BookmarkNodeData drag_data(nodes);
  drag_data.Write(profile, &data);

  // Allow nested message loop so we get DnD events as we drag this around.
  bool was_nested = base::MessageLoop::current()->IsNested();
  base::MessageLoop::current()->SetNestableTasksAllowed(true);

  int operation = ui::DragDropTypes::DRAG_COPY |
                  ui::DragDropTypes::DRAG_MOVE |
                  ui::DragDropTypes::DRAG_LINK;
  views::Widget* widget = views::Widget::GetWidgetForNativeView(view);

  if (widget) {
    widget->RunShellDrag(NULL, data, gfx::Point(), operation, source);
  } else {
    // We hit this case when we're using WebContentsViewWin or
    // WebContentsViewAura, instead of WebContentsViewViews.
    views::RunShellDrag(view, data, gfx::Point(), operation, source);
  }

  base::MessageLoop::current()->SetNestableTasksAllowed(was_nested);
}

int GetBookmarkDragOperation(content::BrowserContext* browser_context,
                             const BookmarkNode* node) {
  PrefService* prefs = user_prefs::UserPrefs::Get(browser_context);

  int move = ui::DragDropTypes::DRAG_MOVE;
  if (!prefs->GetBoolean(prefs::kEditBookmarksEnabled))
    move = ui::DragDropTypes::DRAG_NONE;
  if (node->is_url())
    return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK | move;
  return ui::DragDropTypes::DRAG_COPY | move;
}

int GetPreferredBookmarkDropOperation(int source_operations, int operations) {
  int common_ops = (source_operations & operations);
  if (!common_ops)
    return ui::DragDropTypes::DRAG_NONE;
  if (ui::DragDropTypes::DRAG_COPY & common_ops)
    return ui::DragDropTypes::DRAG_COPY;
  if (ui::DragDropTypes::DRAG_LINK & common_ops)
    return ui::DragDropTypes::DRAG_LINK;
  if (ui::DragDropTypes::DRAG_MOVE & common_ops)
    return ui::DragDropTypes::DRAG_MOVE;
  return ui::DragDropTypes::DRAG_NONE;
}

int GetBookmarkDropOperation(Profile* profile,
                             const ui::DropTargetEvent& event,
                             const BookmarkNodeData& data,
                             const BookmarkNode* parent,
                             int index) {
  if (data.IsFromProfile(profile) && data.size() > 1)
    // Currently only accept one dragged node at a time.
    return ui::DragDropTypes::DRAG_NONE;

  if (!IsValidBookmarkDropLocation(profile, data, parent, index))
    return ui::DragDropTypes::DRAG_NONE;

  if (data.GetFirstNode(profile))
    // User is dragging from this profile: move.
    return ui::DragDropTypes::DRAG_MOVE;

  // User is dragging from another app, copy.
  return GetPreferredBookmarkDropOperation(event.source_operations(),
      ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK);
}

bool IsValidBookmarkDropLocation(Profile* profile,
                                 const BookmarkNodeData& data,
                                 const 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<const 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.
      const BookmarkNode* node = nodes[i];
      int node_index = (drop_parent == node->parent()) ?
          drop_parent->GetIndexOf(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;
}

}  // namespace chrome

/* [<][>][^][v][top][bottom][index][help] */