- add sources.
[platform/framework/web/crosswalk.git] / src / ui / views / widget / drop_helper.cc
1 // Copyright (c) 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.
4
5 #include "ui/views/widget/drop_helper.h"
6
7 #include "ui/base/dragdrop/drag_drop_types.h"
8 #include "ui/views/view.h"
9 #include "ui/views/widget/widget.h"
10
11 namespace views {
12
13 DropHelper::DropHelper(View* root_view)
14     : root_view_(root_view),
15       target_view_(NULL),
16       deepest_view_(NULL) {
17 }
18
19 DropHelper::~DropHelper() {
20 }
21
22 void DropHelper::ResetTargetViewIfEquals(View* view) {
23   if (target_view_ == view)
24     target_view_ = NULL;
25   if (deepest_view_ == view)
26     deepest_view_ = NULL;
27 }
28
29 int DropHelper::OnDragOver(const OSExchangeData& data,
30                            const gfx::Point& root_view_location,
31                            int drag_operation) {
32   View* view = CalculateTargetViewImpl(root_view_location, data, true,
33                                        &deepest_view_);
34
35   if (view != target_view_) {
36     // Target changed notify old drag exited, then new drag entered.
37     NotifyDragExit();
38     target_view_ = view;
39     NotifyDragEntered(data, root_view_location, drag_operation);
40   }
41
42   return NotifyDragOver(data, root_view_location, drag_operation);
43 }
44
45 void DropHelper::OnDragExit() {
46   NotifyDragExit();
47   deepest_view_ = target_view_ = NULL;
48 }
49
50 int DropHelper::OnDrop(const OSExchangeData& data,
51                        const gfx::Point& root_view_location,
52                        int drag_operation) {
53   View* drop_view = target_view_;
54   deepest_view_ = target_view_ = NULL;
55   if (!drop_view)
56     return ui::DragDropTypes::DRAG_NONE;
57
58   if (drag_operation == ui::DragDropTypes::DRAG_NONE) {
59     drop_view->OnDragExited();
60     return ui::DragDropTypes::DRAG_NONE;
61   }
62
63   gfx::Point view_location(root_view_location);
64   View* root_view = drop_view->GetWidget()->GetRootView();
65   View::ConvertPointToTarget(root_view, drop_view, &view_location);
66   ui::DropTargetEvent drop_event(data, view_location, view_location,
67                                  drag_operation);
68   return drop_view->OnPerformDrop(drop_event);
69 }
70
71 View* DropHelper::CalculateTargetView(
72     const gfx::Point& root_view_location,
73     const OSExchangeData& data,
74     bool check_can_drop) {
75   return CalculateTargetViewImpl(root_view_location, data, check_can_drop,
76                                  NULL);
77 }
78
79 View* DropHelper::CalculateTargetViewImpl(
80     const gfx::Point& root_view_location,
81     const OSExchangeData& data,
82     bool check_can_drop,
83     View** deepest_view) {
84   View* view = root_view_->GetEventHandlerForPoint(root_view_location);
85   if (view == deepest_view_) {
86     // The view the mouse is over hasn't changed; reuse the target.
87     return target_view_;
88   }
89   if (deepest_view)
90     *deepest_view = view;
91   // TODO(sky): for the time being these are separate. Once I port chrome menu
92   // I can switch to the #else implementation and nuke the OS_WIN
93   // implementation.
94 #if defined(OS_WIN)
95   // View under mouse changed, which means a new view may want the drop.
96   // Walk the tree, stopping at target_view_ as we know it'll accept the
97   // drop.
98   while (view && view != target_view_ &&
99          (!view->enabled() || !view->CanDrop(data))) {
100     view = view->parent();
101   }
102 #else
103   int formats = 0;
104   std::set<OSExchangeData::CustomFormat> custom_formats;
105   while (view && view != target_view_) {
106     if (view->enabled() &&
107         view->GetDropFormats(&formats, &custom_formats) &&
108         data.HasAnyFormat(formats, custom_formats) &&
109         (!check_can_drop || view->CanDrop(data))) {
110       // Found the view.
111       return view;
112     }
113     formats = 0;
114     custom_formats.clear();
115     view = view->parent();
116   }
117 #endif
118   return view;
119 }
120
121 void DropHelper::NotifyDragEntered(const OSExchangeData& data,
122                                    const gfx::Point& root_view_location,
123                                    int drag_operation) {
124   if (!target_view_)
125     return;
126
127   gfx::Point target_view_location(root_view_location);
128   View::ConvertPointToTarget(root_view_, target_view_, &target_view_location);
129   ui::DropTargetEvent enter_event(data,
130                                   target_view_location,
131                                   target_view_location,
132                                   drag_operation);
133   target_view_->OnDragEntered(enter_event);
134 }
135
136 int DropHelper::NotifyDragOver(const OSExchangeData& data,
137                                const gfx::Point& root_view_location,
138                                int drag_operation) {
139   if (!target_view_)
140     return ui::DragDropTypes::DRAG_NONE;
141
142   gfx::Point target_view_location(root_view_location);
143   View::ConvertPointToTarget(root_view_, target_view_, &target_view_location);
144   ui::DropTargetEvent enter_event(data,
145                                   target_view_location,
146                                   target_view_location,
147                                   drag_operation);
148   return target_view_->OnDragUpdated(enter_event);
149 }
150
151 void DropHelper::NotifyDragExit() {
152   if (target_view_)
153     target_view_->OnDragExited();
154 }
155
156 }  // namespace views