blob: 8920234f71b7c8d749d433e9954ec70899ce372a [file] [log] [blame]
// 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/views/root_view_drop_target.h"
#include "base/gfx/point.h"
#include "base/logging.h"
#include "chrome/common/drag_drop_types.h"
#include "chrome/views/root_view.h"
#include "chrome/views/widget.h"
namespace views {
RootViewDropTarget::RootViewDropTarget(RootView* root_view)
: BaseDropTarget(root_view->GetWidget()->GetHWND()),
root_view_(root_view),
target_view_(NULL),
deepest_view_(NULL) {
}
RootViewDropTarget::~RootViewDropTarget() {
}
void RootViewDropTarget::ResetTargetViewIfEquals(View* view) {
if (target_view_ == view)
target_view_ = NULL;
if (deepest_view_ == view)
deepest_view_ = NULL;
}
DWORD RootViewDropTarget::OnDragOver(IDataObject* data_object,
DWORD key_state,
POINT cursor_position,
DWORD effect) {
const OSExchangeData data(data_object);
gfx::Point root_view_location(cursor_position.x, cursor_position.y);
View::ConvertPointToView(NULL, root_view_, &root_view_location);
View* view = CalculateTargetView(root_view_location, data);
if (view != target_view_) {
// Target changed notify old drag exited, then new drag entered.
if (target_view_)
target_view_->OnDragExited();
target_view_ = view;
if (target_view_) {
gfx::Point target_view_location(root_view_location);
View::ConvertPointToView(root_view_, target_view_, &target_view_location);
DropTargetEvent enter_event(data,
target_view_location.x(),
target_view_location.y(),
DragDropTypes::DropEffectToDragOperation(effect));
target_view_->OnDragEntered(enter_event);
}
}
if (target_view_) {
gfx::Point target_view_location(root_view_location);
View::ConvertPointToView(root_view_, target_view_, &target_view_location);
DropTargetEvent enter_event(data,
target_view_location.x(),
target_view_location.y(),
DragDropTypes::DropEffectToDragOperation(effect));
int result_operation = target_view_->OnDragUpdated(enter_event);
return DragDropTypes::DragOperationToDropEffect(result_operation);
} else {
return DROPEFFECT_NONE;
}
}
void RootViewDropTarget::OnDragLeave(IDataObject* data_object) {
if (target_view_)
target_view_->OnDragExited();
deepest_view_ = target_view_ = NULL;
}
DWORD RootViewDropTarget::OnDrop(IDataObject* data_object,
DWORD key_state,
POINT cursor_position,
DWORD effect) {
const OSExchangeData data(data_object);
DWORD drop_effect = OnDragOver(data_object, key_state, cursor_position,
effect);
View* drop_view = target_view_;
deepest_view_ = target_view_ = NULL;
if (drop_effect != DROPEFFECT_NONE) {
gfx::Point view_location(cursor_position.x, cursor_position.y);
View::ConvertPointToView(NULL, drop_view, &view_location);
DropTargetEvent drop_event(data, view_location.x(), view_location.y(),
DragDropTypes::DropEffectToDragOperation(effect));
return DragDropTypes::DragOperationToDropEffect(
drop_view->OnPerformDrop(drop_event));
} else {
if (drop_view)
drop_view->OnDragExited();
return DROPEFFECT_NONE;
}
}
View* RootViewDropTarget::CalculateTargetView(
const gfx::Point& root_view_location,
const OSExchangeData& data) {
View* view = root_view_->GetViewForPoint(root_view_location);
if (view == deepest_view_) {
// The view the mouse is over hasn't changed; reuse the target.
return target_view_;
}
// View under mouse changed, which means a new view may want the drop.
// Walk the tree, stopping at target_view_ as we know it'll accept the
// drop.
deepest_view_ = view;
while (view && view != target_view_ &&
(!view->IsEnabled() || !view->CanDrop(data))) {
view = view->GetParent();
}
return view;
}
} // namespace views