OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/views/controls/menu/menu_controller.h" | 5 #include "ui/views/controls/menu/menu_controller.h" |
6 | 6 |
7 #include "base/run_loop.h" | 7 #include "base/run_loop.h" |
8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
9 #include "ui/events/event_handler.h" | 9 #include "ui/events/event_handler.h" |
10 #include "ui/events/null_event_targeter.h" | 10 #include "ui/events/null_event_targeter.h" |
(...skipping 28 matching lines...) Expand all Loading... | |
39 | 39 |
40 class TestMenuItemView : public MenuItemView { | 40 class TestMenuItemView : public MenuItemView { |
41 public: | 41 public: |
42 TestMenuItemView() : MenuItemView(nullptr) {} | 42 TestMenuItemView() : MenuItemView(nullptr) {} |
43 ~TestMenuItemView() override {} | 43 ~TestMenuItemView() override {} |
44 | 44 |
45 private: | 45 private: |
46 DISALLOW_COPY_AND_ASSIGN(TestMenuItemView); | 46 DISALLOW_COPY_AND_ASSIGN(TestMenuItemView); |
47 }; | 47 }; |
48 | 48 |
49 class SubmenuViewShown : public SubmenuView { | |
50 public: | |
51 SubmenuViewShown(MenuItemView* parent) : SubmenuView(parent) {} | |
52 ~SubmenuViewShown() override {} | |
53 bool IsShowing() override { return true; } | |
54 | |
55 private: | |
56 DISALLOW_COPY_AND_ASSIGN(SubmenuViewShown); | |
57 }; | |
58 | |
59 class TestMenuItemViewShown : public MenuItemView { | |
60 public: | |
61 TestMenuItemViewShown() : MenuItemView(nullptr) {} | |
sadrul
2015/07/15 19:21:52
Can it set |submenu_| here? Would that allow not m
varkha
2015/07/15 19:51:34
It is probably possible but the way CreateSubmenu
varkha
2015/07/16 16:32:33
I did that in Patch Set #4. Please see if you like
| |
62 ~TestMenuItemViewShown() override {} | |
63 SubmenuView* CreateSubmenu() override { return new SubmenuViewShown(this); } | |
64 | |
65 private: | |
66 DISALLOW_COPY_AND_ASSIGN(TestMenuItemViewShown); | |
67 }; | |
68 | |
49 class TestPlatformEventSource : public ui::PlatformEventSource { | 69 class TestPlatformEventSource : public ui::PlatformEventSource { |
50 public: | 70 public: |
51 TestPlatformEventSource() { | 71 TestPlatformEventSource() { |
52 #if defined(USE_X11) | 72 #if defined(USE_X11) |
53 ui::DeviceDataManagerX11::CreateInstance(); | 73 ui::DeviceDataManagerX11::CreateInstance(); |
54 #endif | 74 #endif |
55 } | 75 } |
56 ~TestPlatformEventSource() override {} | 76 ~TestPlatformEventSource() override {} |
57 | 77 |
58 uint32_t Dispatch(const ui::PlatformEvent& event) { | 78 uint32_t Dispatch(const ui::PlatformEvent& event) { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
163 #endif | 183 #endif |
164 return widget.Pass(); | 184 return widget.Pass(); |
165 } | 185 } |
166 | 186 |
167 const MenuItemView* pending_state_item() const { | 187 const MenuItemView* pending_state_item() const { |
168 return controller_->pending_state_.item; | 188 return controller_->pending_state_.item; |
169 } | 189 } |
170 | 190 |
171 void SetPendingStateItem(MenuItemView* item) { | 191 void SetPendingStateItem(MenuItemView* item) { |
172 controller_->pending_state_.item = item; | 192 controller_->pending_state_.item = item; |
193 controller_->pending_state_.submenu_open = true; | |
173 } | 194 } |
174 | 195 |
175 void ResetSelection() { | 196 void ResetSelection() { |
176 controller_->SetSelection(nullptr, | 197 controller_->SetSelection(nullptr, |
177 MenuController::SELECTION_EXIT | | 198 MenuController::SELECTION_EXIT | |
178 MenuController::SELECTION_UPDATE_IMMEDIATELY); | 199 MenuController::SELECTION_UPDATE_IMMEDIATELY); |
179 } | 200 } |
180 | 201 |
181 void IncrementSelection(int delta) { | 202 void IncrementSelection(int delta) { |
182 controller_->IncrementSelection(delta); | 203 controller_->IncrementSelection(delta); |
183 } | 204 } |
184 | 205 |
185 MenuItemView* FindFirstSelectableMenuItem(MenuItemView* parent) { | 206 MenuItemView* FindInitialSelectableMenuItem(MenuItemView* parent, int delta) { |
186 return controller_->FindFirstSelectableMenuItem(parent); | 207 return controller_->FindInitialSelectableMenuItem(parent, delta); |
187 } | 208 } |
188 | 209 |
189 MenuItemView* FindNextSelectableMenuItem(MenuItemView* parent, | 210 MenuItemView* FindNextSelectableMenuItem(MenuItemView* parent, |
190 int index, | 211 int index, |
191 int delta) { | 212 int delta) { |
192 return controller_->FindNextSelectableMenuItem(parent, index, delta); | 213 return controller_->FindNextSelectableMenuItem(parent, index, delta); |
193 } | 214 } |
194 void SetupMenu(views::Widget* owner, views::MenuItemView* item) { | 215 void SetupMenu(views::Widget* owner, views::MenuItemView* item) { |
195 ResetMenuController(); | 216 ResetMenuController(); |
196 controller_ = new MenuController(nullptr, true, nullptr); | 217 controller_ = new MenuController(nullptr, true, nullptr); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
368 base::Unretained(this), MenuController::EXIT_OUTERMOST)); | 389 base::Unretained(this), MenuController::EXIT_OUTERMOST)); |
369 | 390 |
370 RunMenu(owner.get()); | 391 RunMenu(owner.get()); |
371 EXPECT_EQ(0, test_event_handler.outstanding_touches()); | 392 EXPECT_EQ(0, test_event_handler.outstanding_touches()); |
372 | 393 |
373 owner->GetNativeWindow()->GetRootWindow()->RemovePreTargetHandler( | 394 owner->GetNativeWindow()->GetRootWindow()->RemovePreTargetHandler( |
374 &test_event_handler); | 395 &test_event_handler); |
375 } | 396 } |
376 #endif // defined(USE_X11) | 397 #endif // defined(USE_X11) |
377 | 398 |
378 TEST_F(MenuControllerTest, FirstSelectedItem) { | 399 TEST_F(MenuControllerTest, InitialSelectedItem) { |
379 scoped_ptr<Widget> owner(CreateOwnerWidget()); | 400 scoped_ptr<Widget> owner(CreateOwnerWidget()); |
380 scoped_ptr<TestMenuItemView> menu_item(new TestMenuItemView); | 401 scoped_ptr<TestMenuItemView> menu_item(new TestMenuItemView); |
381 menu_item->AppendMenuItemWithLabel(1, base::ASCIIToUTF16("One")); | 402 menu_item->AppendMenuItemWithLabel(1, base::ASCIIToUTF16("One")); |
382 menu_item->AppendMenuItemWithLabel(2, base::ASCIIToUTF16("Two")); | 403 menu_item->AppendMenuItemWithLabel(2, base::ASCIIToUTF16("Two")); |
383 // Disabling the item "One" gets it skipped when a menu is first opened. | 404 menu_item->AppendMenuItemWithLabel(3, base::ASCIIToUTF16("Three")); |
384 menu_item->GetSubmenu()->GetMenuItemAt(0)->SetEnabled(false); | |
385 | |
386 SetupMenu(owner.get(), menu_item.get()); | 405 SetupMenu(owner.get(), menu_item.get()); |
387 | 406 |
388 // First selectable item should be item "Two". | 407 // Leave items "Two" and "Three" enabled. |
389 MenuItemView* first_selectable = FindFirstSelectableMenuItem(menu_item.get()); | 408 menu_item->GetSubmenu()->GetMenuItemAt(0)->SetEnabled(false); |
409 // The first selectable item should be item "Two". | |
410 MenuItemView* first_selectable = | |
411 FindInitialSelectableMenuItem(menu_item.get(), 1); | |
412 ASSERT_NE(nullptr, first_selectable); | |
390 EXPECT_EQ(2, first_selectable->GetCommand()); | 413 EXPECT_EQ(2, first_selectable->GetCommand()); |
414 // The last selectable item should be item "Three". | |
415 MenuItemView* last_selectable = | |
416 FindInitialSelectableMenuItem(menu_item.get(), -1); | |
417 ASSERT_NE(nullptr, last_selectable); | |
418 EXPECT_EQ(3, last_selectable->GetCommand()); | |
419 | |
420 // Leave items "One" and "Two" enabled. | |
421 menu_item->GetSubmenu()->GetMenuItemAt(0)->SetEnabled(true); | |
422 menu_item->GetSubmenu()->GetMenuItemAt(1)->SetEnabled(true); | |
423 menu_item->GetSubmenu()->GetMenuItemAt(2)->SetEnabled(false); | |
424 // The first selectable item should be item "One". | |
425 first_selectable = FindInitialSelectableMenuItem(menu_item.get(), 1); | |
426 ASSERT_NE(nullptr, first_selectable); | |
427 EXPECT_EQ(1, first_selectable->GetCommand()); | |
428 // The last selectable item should be item "Two". | |
429 last_selectable = FindInitialSelectableMenuItem(menu_item.get(), -1); | |
430 ASSERT_NE(nullptr, last_selectable); | |
431 EXPECT_EQ(2, last_selectable->GetCommand()); | |
432 | |
433 // Leave only a single item "One" enabled. | |
434 menu_item->GetSubmenu()->GetMenuItemAt(0)->SetEnabled(true); | |
435 menu_item->GetSubmenu()->GetMenuItemAt(1)->SetEnabled(false); | |
436 menu_item->GetSubmenu()->GetMenuItemAt(2)->SetEnabled(false); | |
437 // The first selectable item should be item "One". | |
438 first_selectable = FindInitialSelectableMenuItem(menu_item.get(), 1); | |
439 ASSERT_NE(nullptr, first_selectable); | |
440 EXPECT_EQ(1, first_selectable->GetCommand()); | |
441 // The last selectable item should be item "One". | |
442 last_selectable = FindInitialSelectableMenuItem(menu_item.get(), -1); | |
443 ASSERT_NE(nullptr, last_selectable); | |
444 EXPECT_EQ(1, last_selectable->GetCommand()); | |
445 | |
446 // Leave only a single item "Three" enabled. | |
447 menu_item->GetSubmenu()->GetMenuItemAt(0)->SetEnabled(false); | |
448 menu_item->GetSubmenu()->GetMenuItemAt(1)->SetEnabled(false); | |
449 menu_item->GetSubmenu()->GetMenuItemAt(2)->SetEnabled(true); | |
450 // The first selectable item should be item "Three". | |
451 first_selectable = FindInitialSelectableMenuItem(menu_item.get(), 1); | |
452 ASSERT_NE(nullptr, first_selectable); | |
453 EXPECT_EQ(3, first_selectable->GetCommand()); | |
454 // The last selectable item should be item "Three". | |
455 last_selectable = FindInitialSelectableMenuItem(menu_item.get(), -1); | |
456 ASSERT_NE(nullptr, last_selectable); | |
457 EXPECT_EQ(3, last_selectable->GetCommand()); | |
458 | |
459 // Leave only a single item ("Two") selected. It should be the first and the | |
460 // last selectable item. | |
461 menu_item->GetSubmenu()->GetMenuItemAt(0)->SetEnabled(false); | |
462 menu_item->GetSubmenu()->GetMenuItemAt(1)->SetEnabled(true); | |
463 menu_item->GetSubmenu()->GetMenuItemAt(2)->SetEnabled(false); | |
464 first_selectable = FindInitialSelectableMenuItem(menu_item.get(), 1); | |
465 ASSERT_NE(nullptr, first_selectable); | |
466 EXPECT_EQ(2, first_selectable->GetCommand()); | |
467 last_selectable = FindInitialSelectableMenuItem(menu_item.get(), -1); | |
468 ASSERT_NE(nullptr, last_selectable); | |
469 EXPECT_EQ(2, last_selectable->GetCommand()); | |
391 | 470 |
392 // There should be no next or previous selectable item since there is only a | 471 // There should be no next or previous selectable item since there is only a |
393 // single enabled item in the menu. | 472 // single enabled item in the menu. |
394 SetPendingStateItem(first_selectable); | |
395 EXPECT_EQ(nullptr, FindNextSelectableMenuItem(menu_item.get(), 1, 1)); | 473 EXPECT_EQ(nullptr, FindNextSelectableMenuItem(menu_item.get(), 1, 1)); |
396 EXPECT_EQ(nullptr, FindNextSelectableMenuItem(menu_item.get(), 1, -1)); | 474 EXPECT_EQ(nullptr, FindNextSelectableMenuItem(menu_item.get(), 1, -1)); |
397 | 475 |
398 // Clear references in menu controller to the menu item that is going away. | 476 // Clear references in menu controller to the menu item that is going away. |
399 ResetSelection(); | 477 ResetSelection(); |
400 } | 478 } |
401 | 479 |
402 TEST_F(MenuControllerTest, NextSelectedItem) { | 480 TEST_F(MenuControllerTest, NextSelectedItem) { |
403 scoped_ptr<Widget> owner(CreateOwnerWidget()); | 481 scoped_ptr<Widget> owner(CreateOwnerWidget()); |
404 scoped_ptr<TestMenuItemView> menu_item(new TestMenuItemView); | 482 scoped_ptr<TestMenuItemView> menu_item(new TestMenuItemView); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
438 EXPECT_EQ(2, pending_state_item()->GetCommand()); | 516 EXPECT_EQ(2, pending_state_item()->GetCommand()); |
439 | 517 |
440 // Select previous item. | 518 // Select previous item. |
441 IncrementSelection(-1); | 519 IncrementSelection(-1); |
442 EXPECT_EQ(1, pending_state_item()->GetCommand()); | 520 EXPECT_EQ(1, pending_state_item()->GetCommand()); |
443 | 521 |
444 // Clear references in menu controller to the menu item that is going away. | 522 // Clear references in menu controller to the menu item that is going away. |
445 ResetSelection(); | 523 ResetSelection(); |
446 } | 524 } |
447 | 525 |
526 TEST_F(MenuControllerTest, NextSelectedItemUp) { | |
527 scoped_ptr<Widget> owner(CreateOwnerWidget()); | |
528 scoped_ptr<TestMenuItemViewShown> menu_item(new TestMenuItemViewShown); | |
529 menu_item->AppendMenuItemWithLabel(1, base::ASCIIToUTF16("One")); | |
530 menu_item->AppendMenuItemWithLabel(2, base::ASCIIToUTF16("Two")); | |
531 menu_item->AppendMenuItemWithLabel(3, base::ASCIIToUTF16("Three")); | |
532 menu_item->AppendMenuItemWithLabel(4, base::ASCIIToUTF16("Four")); | |
533 // Disabling the item "Four" gets it skipped when using keyboard to navigate. | |
534 menu_item->GetSubmenu()->GetMenuItemAt(3)->SetEnabled(false); | |
535 | |
536 SetupMenu(owner.get(), menu_item.get()); | |
537 | |
538 // Fake initial root item selection and submenu showing. | |
539 SetPendingStateItem(menu_item.get()); | |
540 EXPECT_EQ(0, pending_state_item()->GetCommand()); | |
541 | |
542 // Move up and select a previous (in our case the last enabled) item. | |
543 IncrementSelection(-1); | |
544 EXPECT_EQ(3, pending_state_item()->GetCommand()); | |
545 } | |
546 | |
448 } // namespace views | 547 } // namespace views |
OLD | NEW |