Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(588)

Side by Side Diff: chrome/browser/ui/views/menu_view_drag_and_drop_test.cc

Issue 378333003: Allow menus to stay open during a child view's drag and drop (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Test Fix Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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 "base/strings/utf_string_conversions.h"
6 #include "chrome/browser/ui/views/menu_test_base.h"
7 #include "chrome/test/base/interactive_test_utils.h"
8 #include "ui/base/dragdrop/drag_drop_types.h"
9 #include "ui/base/dragdrop/os_exchange_data.h"
10 #include "ui/views/controls/menu/menu_item_view.h"
11 #include "ui/views/controls/menu/submenu_view.h"
12 #include "ui/views/view.h"
13
14 namespace {
15
16 // Borrowed from chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc,
17 // since these are also disabled on Linux for drag and drop.
18 // TODO(erg): Fix DND tests on linux_aura. crbug.com/163931
19 #if defined(OS_LINUX) && defined(USE_AURA)
20 #define MAYBE(x) DISABLED_##x
21 #else
22 #define MAYBE(x) x
23 #endif
24
25 const char kTestNestedDragData[] = "test_nested_drag_data";
26 const char kTestTopLevelDragData[] = "test_top_level_drag_data";
27
28 // A simple view which can be dragged.
29 class TestDragView : public views::View {
30 public:
31 TestDragView();
32 virtual ~TestDragView();
33
34 private:
35 // views::View:
36 virtual int GetDragOperations(const gfx::Point& point) OVERRIDE;
37 virtual void WriteDragData(const gfx::Point& point,
38 ui::OSExchangeData* data) OVERRIDE;
39
40 DISALLOW_COPY_AND_ASSIGN(TestDragView);
41 };
42
43 TestDragView::TestDragView() {
44 }
45
46 TestDragView::~TestDragView() {
47 }
48
49 int TestDragView::GetDragOperations(const gfx::Point& point) {
50 return ui::DragDropTypes::DRAG_MOVE;
51 }
52
53 void TestDragView::WriteDragData(const gfx::Point& point,
54 ui::OSExchangeData* data) {
55 data->SetString(base::ASCIIToUTF16(kTestNestedDragData));
56 }
57
58 // A simple view to serve as a drop target.
59 class TestTargetView : public views::View {
60 public:
61 TestTargetView();
62 virtual ~TestTargetView();
63
64 // Initializes this view to have the same bounds as |parent| and two draggable
65 // child views.
66 void Init(views::View* parent);
67 bool dragging() const { return dragging_; }
68 bool dropped() const { return dropped_; }
69
70 private:
71 // views::View:
72 virtual bool GetDropFormats(
73 int* formats,
74 std::set<OSExchangeData::CustomFormat>* custom_formats) OVERRIDE;
75 virtual bool AreDropTypesRequired() OVERRIDE;
76 virtual bool CanDrop(const OSExchangeData& data) OVERRIDE;
77 virtual void OnDragEntered(const ui::DropTargetEvent& event) OVERRIDE;
78 virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE;
79 virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE;
80 virtual void OnDragExited() OVERRIDE;
81
82 // Whether or not we are currently dragging.
83 bool dragging_;
84
85 // Whether or not a drop has been performed on the view.
86 bool dropped_;
87
88 DISALLOW_COPY_AND_ASSIGN(TestTargetView);
89 };
90
91 TestTargetView::TestTargetView() : dragging_(false), dropped_(false) {
92 }
93
94 void TestTargetView::Init(views::View* parent) {
95 // First, match the parent's size.
96 SetSize(parent->size());
97
98 // Then add two draggable views, each 10x2.
99 views::View* first = new TestDragView();
100 AddChildView(first);
101 first->SetBounds(2, 2, 10, 2);
102
103 views::View* second = new TestDragView();
104 AddChildView(second);
105 second->SetBounds(15, 2, 10, 2);
106 }
107
108 TestTargetView::~TestTargetView() {
109 }
110
111 bool TestTargetView::GetDropFormats(
112 int* formats, std::set<OSExchangeData::CustomFormat>* custom_formats) {
113 *formats = ui::OSExchangeData::STRING;
114 return true;
115 }
116
117 bool TestTargetView::AreDropTypesRequired() {
118 return true;
119 }
120
121 bool TestTargetView::CanDrop(const OSExchangeData& data) {
122 base::string16 contents;
123 return data.GetString(&contents) &&
124 contents == base::ASCIIToUTF16(kTestNestedDragData);
125 }
126
127 void TestTargetView::OnDragEntered(const ui::DropTargetEvent& event) {
128 dragging_ = true;
129 }
130
131 int TestTargetView::OnDragUpdated(const ui::DropTargetEvent& event) {
132 return ui::DragDropTypes::DRAG_MOVE;
133 }
134
135 int TestTargetView::OnPerformDrop(const ui::DropTargetEvent& event) {
136 dragging_ = false;
137 dropped_ = true;
138 return ui::DragDropTypes::DRAG_MOVE;
139 }
140
141 void TestTargetView::OnDragExited() {
142 dragging_ = false;
143 }
144
145 } // namespace
146
147 class MenuViewDragAndDropTest : public MenuTestBase {
148 public:
149 MenuViewDragAndDropTest();
150 virtual ~MenuViewDragAndDropTest();
151
152 protected:
153 TestTargetView* target_view() { return target_view_; }
154 bool asked_to_close() const { return asked_to_close_; }
155 bool performed_in_menu_drop() const { return performed_in_menu_drop_; }
156
157 private:
158 // MenuTestBase:
159 virtual void BuildMenu(views::MenuItemView* menu) OVERRIDE;
160
161 // views::MenuDelegate:
162 virtual bool GetDropFormats(
163 views::MenuItemView* menu,
164 int* formats,
165 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) OVERRIDE;
166 virtual bool AreDropTypesRequired(views::MenuItemView* menu) OVERRIDE;
167 virtual bool CanDrop(views::MenuItemView* menu,
168 const ui::OSExchangeData& data) OVERRIDE;
169 virtual int GetDropOperation(views::MenuItemView* item,
170 const ui::DropTargetEvent& event,
171 DropPosition* position) OVERRIDE;
172 virtual int OnPerformDrop(views::MenuItemView* menu,
173 DropPosition position,
174 const ui::DropTargetEvent& event) OVERRIDE;
175 virtual bool CanDrag(views::MenuItemView* menu) OVERRIDE;
176 virtual void WriteDragData(views::MenuItemView* sender,
177 ui::OSExchangeData* data) OVERRIDE;
178 virtual int GetDragOperations(views::MenuItemView* sender) OVERRIDE;
179 virtual bool ShouldCloseOnDragComplete() OVERRIDE;
180
181 // The special view in the menu, which supports its own drag and drop.
182 TestTargetView* target_view_;
183
184 // Whether or not we have been asked to close on drag complete.
185 bool asked_to_close_;
186
187 // Whether or not a drop was performed in-menu (i.e., not including drops
188 // in separate child views).
189 bool performed_in_menu_drop_;
190
191 DISALLOW_COPY_AND_ASSIGN(MenuViewDragAndDropTest);
192 };
193
194 MenuViewDragAndDropTest::MenuViewDragAndDropTest()
195 : target_view_(NULL),
196 asked_to_close_(false),
197 performed_in_menu_drop_(false) {
198 }
199
200 MenuViewDragAndDropTest::~MenuViewDragAndDropTest() {
201 }
202
203 void MenuViewDragAndDropTest::BuildMenu(views::MenuItemView* menu) {
204 // Build a menu item that has a nested view that supports its own drag and
205 // drop...
206 views::MenuItemView* menu_item_view =
207 menu->AppendMenuItem(1,
208 base::ASCIIToUTF16("item 1"),
209 views::MenuItemView::NORMAL);
210 target_view_ = new TestTargetView();
211 menu_item_view->AddChildView(target_view_);
212 // ... as well as two other, normal items.
213 menu->AppendMenuItemWithLabel(2, base::ASCIIToUTF16("item 2"));
214 menu->AppendMenuItemWithLabel(3, base::ASCIIToUTF16("item 3"));
215 }
216
217 bool MenuViewDragAndDropTest::GetDropFormats(
218 views::MenuItemView* menu,
219 int* formats,
220 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) {
221 *formats = ui::OSExchangeData::STRING;
222 return true;
223 }
224
225 bool MenuViewDragAndDropTest::AreDropTypesRequired(views::MenuItemView* menu) {
226 return true;
227 }
228
229 bool MenuViewDragAndDropTest::CanDrop(views::MenuItemView* menu,
230 const ui::OSExchangeData& data) {
231 base::string16 contents;
232 return data.GetString(&contents) &&
233 contents == base::ASCIIToUTF16(kTestTopLevelDragData);
234 }
235
236 int MenuViewDragAndDropTest::GetDropOperation(views::MenuItemView* item,
237 const ui::DropTargetEvent& event,
238 DropPosition* position) {
239 return ui::DragDropTypes::DRAG_MOVE;
240 }
241
242
243 int MenuViewDragAndDropTest::OnPerformDrop(views::MenuItemView* menu,
244 DropPosition position,
245 const ui::DropTargetEvent& event) {
246 performed_in_menu_drop_ = true;
247 return ui::DragDropTypes::DRAG_MOVE;
248 }
249
250 bool MenuViewDragAndDropTest::CanDrag(views::MenuItemView* menu) {
251 return true;
252 }
253
254 void MenuViewDragAndDropTest::WriteDragData(
255 views::MenuItemView* sender, ui::OSExchangeData* data) {
256 data->SetString(base::ASCIIToUTF16(kTestTopLevelDragData));
257 }
258
259 int MenuViewDragAndDropTest::GetDragOperations(views::MenuItemView* sender) {
260 return ui::DragDropTypes::DRAG_MOVE;
261 }
262
263 bool MenuViewDragAndDropTest::ShouldCloseOnDragComplete() {
264 asked_to_close_ = true;
265 return false;
266 }
267
268 class MenuViewDragAndDropTestTestInMenuDrag : public MenuViewDragAndDropTest {
269 public:
270 MenuViewDragAndDropTestTestInMenuDrag() {}
271 virtual ~MenuViewDragAndDropTestTestInMenuDrag() {}
272
273 private:
274 // MenuViewDragAndDropTest:
275 virtual void DoTestWithMenuOpen() OVERRIDE;
276
277 void Step2();
278 void Step3();
279 void Step4();
280 };
281
282 void MenuViewDragAndDropTestTestInMenuDrag::DoTestWithMenuOpen() {
283 // A few sanity checks to make sure the menu built correctly.
284 views::SubmenuView* submenu = menu()->GetSubmenu();
285 ASSERT_TRUE(submenu);
286 ASSERT_TRUE(submenu->IsShowing());
287 ASSERT_EQ(3, submenu->GetMenuItemCount());
288
289 // We do this here (instead of in BuildMenu()) so that the menu is already
290 // built and the bounds are correct.
291 target_view()->Init(submenu->GetMenuItemAt(0));
292
293 // We're going to drag the second menu element.
294 views::MenuItemView* drag_view = submenu->GetMenuItemAt(1);
295 ASSERT_TRUE(drag_view != NULL);
296
297 // Move mouse to center of menu and press button.
298 ui_test_utils::MoveMouseToCenterAndPress(
299 drag_view,
300 ui_controls::LEFT,
301 ui_controls::DOWN,
302 CreateEventTask(this, &MenuViewDragAndDropTestTestInMenuDrag::Step2));
303 }
304
305 void MenuViewDragAndDropTestTestInMenuDrag::Step2() {
306 views::MenuItemView* drop_target = menu()->GetSubmenu()->GetMenuItemAt(2);
307 gfx::Point loc(1, drop_target->height() - 1);
308 views::View::ConvertPointToScreen(drop_target, &loc);
309
310 // Start a drag.
311 ui_controls::SendMouseMoveNotifyWhenDone(
312 loc.x() + 10,
313 loc.y(),
314 CreateEventTask(this, &MenuViewDragAndDropTestTestInMenuDrag::Step3));
315
316 ScheduleMouseMoveInBackground(loc.x(), loc.y());
317 }
318
319 void MenuViewDragAndDropTestTestInMenuDrag::Step3() {
320 // Drop the item on the target.
321 views::MenuItemView* drop_target = menu()->GetSubmenu()->GetMenuItemAt(2);
322 gfx::Point loc(1, drop_target->height() - 2);
323 views::View::ConvertPointToScreen(drop_target, &loc);
324 ui_controls::SendMouseMove(loc.x(), loc.y());
325
326 ui_controls::SendMouseEventsNotifyWhenDone(
327 ui_controls::LEFT,
328 ui_controls::UP,
329 CreateEventTask(this, &MenuViewDragAndDropTestTestInMenuDrag::Step4));
330 }
331
332 void MenuViewDragAndDropTestTestInMenuDrag::Step4() {
333 // Verify our state.
334 // We should have performed an in-menu drop, and the nested view should not
335 // have had a drag and drop. Since the drag happened in menu code, the
336 // delegate should not have been asked whether or not to close, and the menu
337 // should simply be closed.
338 EXPECT_TRUE(performed_in_menu_drop());
339 EXPECT_FALSE(target_view()->dropped());
340 EXPECT_FALSE(asked_to_close());
341 EXPECT_FALSE(menu()->GetSubmenu()->IsShowing());
342
343 Done();
344 }
345
346 VIEW_TEST(MenuViewDragAndDropTestTestInMenuDrag, MAYBE(TestInMenuDrag))
347
348 class MenuViewDragAndDropTestNestedDrag : public MenuViewDragAndDropTest {
349 public:
350 MenuViewDragAndDropTestNestedDrag() {}
351 virtual ~MenuViewDragAndDropTestNestedDrag() {}
352
353 private:
354 // MenuViewDragAndDropTest:
355 virtual void DoTestWithMenuOpen() OVERRIDE;
356
357 void Step2();
358 void Step3();
359 void Step4();
360 };
361
362 void MenuViewDragAndDropTestNestedDrag::DoTestWithMenuOpen() {
363 // Sanity checks: We should be showing the menu, it should have three
364 // children, and the first of those children should have a nested view of the
365 // TestTargetView.
366 views::SubmenuView* submenu = menu()->GetSubmenu();
367 ASSERT_TRUE(submenu);
368 ASSERT_TRUE(submenu->IsShowing());
369 ASSERT_EQ(3, submenu->GetMenuItemCount());
370 views::View* first_view = submenu->GetMenuItemAt(0);
371 ASSERT_EQ(1, first_view->child_count());
372 views::View* child_view = first_view->child_at(0);
373 ASSERT_EQ(child_view, target_view());
374
375 // We do this here (instead of in BuildMenu()) so that the menu is already
376 // built and the bounds are correct.
377 target_view()->Init(submenu->GetMenuItemAt(0));
378
379 // The target view should now have two children.
380 ASSERT_EQ(2, target_view()->child_count());
381
382 views::View* drag_view = target_view()->child_at(0);
383 ASSERT_TRUE(drag_view != NULL);
384
385 // Move mouse to center of menu and press button.
386 ui_test_utils::MoveMouseToCenterAndPress(
387 drag_view,
388 ui_controls::LEFT,
389 ui_controls::DOWN,
390 CreateEventTask(this, &MenuViewDragAndDropTestNestedDrag::Step2));
391 }
392
393 void MenuViewDragAndDropTestNestedDrag::Step2() {
394 views::View* drop_target = target_view()->child_at(1);
395 gfx::Point loc(2, 0);
396 views::View::ConvertPointToScreen(drop_target, &loc);
397
398 // Start a drag.
399 ui_controls::SendMouseMoveNotifyWhenDone(
400 loc.x() + 3,
401 loc.y(),
402 CreateEventTask(this, &MenuViewDragAndDropTestNestedDrag::Step3));
403
404 ScheduleMouseMoveInBackground(loc.x(), loc.y());
405 }
406
407 void MenuViewDragAndDropTestNestedDrag::Step3() {
408 // The view should be dragging now.
409 EXPECT_TRUE(target_view()->dragging());
410
411 // Drop the item so that it's now the second item.
412 views::View* drop_target = target_view()->child_at(1);
413 gfx::Point loc(5, 0);
414 views::View::ConvertPointToScreen(drop_target, &loc);
415 ui_controls::SendMouseMove(loc.x(), loc.y());
416
417 ui_controls::SendMouseEventsNotifyWhenDone(
418 ui_controls::LEFT,
419 ui_controls::UP,
420 CreateEventTask(this, &MenuViewDragAndDropTestNestedDrag::Step4));
421 }
422
423 void MenuViewDragAndDropTestNestedDrag::Step4() {
424 // Check our state.
425 // The target view should have finished its drag, and should have dropped the
426 // view. The main menu should not have done any drag, and the delegate should
427 // have been asked if it wanted to close. Since the delegate did not want to
428 // close, the menu should still be open.
429 EXPECT_FALSE(target_view()->dragging());
430 EXPECT_TRUE(target_view()->dropped());
431 EXPECT_FALSE(performed_in_menu_drop());
432 EXPECT_TRUE(asked_to_close());
433 EXPECT_TRUE(menu()->GetSubmenu()->IsShowing());
434
435 // Clean up.
436 menu()->GetSubmenu()->Close();
437
438 Done();
439 }
440
441 VIEW_TEST(MenuViewDragAndDropTestNestedDrag,
442 MAYBE(MenuViewDragAndDropNestedDrag))
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc ('k') | chrome/browser/ui/views/toolbar/wrench_menu.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698