OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/combobox/combobox.h" | 5 #include "ui/views/controls/combobox/combobox.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 int actions_performed_; | 178 int actions_performed_; |
179 | 179 |
180 private: | 180 private: |
181 DISALLOW_COPY_AND_ASSIGN(TestComboboxListener); | 181 DISALLOW_COPY_AND_ASSIGN(TestComboboxListener); |
182 }; | 182 }; |
183 | 183 |
184 } // namespace | 184 } // namespace |
185 | 185 |
186 class ComboboxTest : public ViewsTestBase { | 186 class ComboboxTest : public ViewsTestBase { |
187 public: | 187 public: |
188 ComboboxTest() : widget_(NULL), combobox_(NULL) {} | 188 ComboboxTest() {} |
189 | 189 |
190 void TearDown() override { | 190 void TearDown() override { |
191 if (widget_) | 191 if (widget_) |
192 widget_->Close(); | 192 widget_->Close(); |
193 ViewsTestBase::TearDown(); | 193 ViewsTestBase::TearDown(); |
194 } | 194 } |
195 | 195 |
196 void InitCombobox(const std::set<int>* separators, Combobox::Style style) { | 196 void InitCombobox(const std::set<int>* separators, Combobox::Style style) { |
197 model_.reset(new TestComboboxModel()); | 197 model_.reset(new TestComboboxModel()); |
198 | 198 |
199 if (separators) | 199 if (separators) |
200 model_->SetSeparators(*separators); | 200 model_->SetSeparators(*separators); |
201 | 201 |
202 ASSERT_FALSE(combobox_); | 202 ASSERT_FALSE(combobox_); |
203 combobox_ = new TestCombobox(model_.get(), style); | 203 combobox_ = new TestCombobox(model_.get(), style); |
204 test_api_.reset(new ComboboxTestApi(combobox_)); | 204 test_api_.reset(new ComboboxTestApi(combobox_)); |
| 205 test_api_->InstallTestMenuRunner(&menu_show_count_); |
205 combobox_->set_id(1); | 206 combobox_->set_id(1); |
206 | 207 |
207 widget_ = new Widget; | 208 widget_ = new Widget; |
208 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); | 209 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); |
209 params.bounds = gfx::Rect(200, 200, 200, 200); | 210 params.bounds = gfx::Rect(200, 200, 200, 200); |
210 widget_->Init(params); | 211 widget_->Init(params); |
211 View* container = new View(); | 212 View* container = new View(); |
212 widget_->SetContentsView(container); | 213 widget_->SetContentsView(container); |
213 container->AddChildView(combobox_); | 214 container->AddChildView(combobox_); |
214 widget_->Show(); | 215 widget_->Show(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | 248 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); |
248 widget_->OnMouseEvent(&released_event); | 249 widget_->OnMouseEvent(&released_event); |
249 } | 250 } |
250 | 251 |
251 void PerformClick(const gfx::Point& point) { | 252 void PerformClick(const gfx::Point& point) { |
252 PerformMousePress(point); | 253 PerformMousePress(point); |
253 PerformMouseRelease(point); | 254 PerformMouseRelease(point); |
254 } | 255 } |
255 | 256 |
256 // We need widget to populate wrapper class. | 257 // We need widget to populate wrapper class. |
257 Widget* widget_; | 258 Widget* widget_ = nullptr; |
258 | 259 |
259 // |combobox_| will be allocated InitCombobox() and then owned by |widget_|. | 260 // |combobox_| will be allocated InitCombobox() and then owned by |widget_|. |
260 TestCombobox* combobox_; | 261 TestCombobox* combobox_ = nullptr; |
261 std::unique_ptr<ComboboxTestApi> test_api_; | 262 std::unique_ptr<ComboboxTestApi> test_api_; |
262 | 263 |
263 // Combobox does not take ownership of the model, hence it needs to be scoped. | 264 // Combobox does not take ownership of the model, hence it needs to be scoped. |
264 std::unique_ptr<TestComboboxModel> model_; | 265 std::unique_ptr<TestComboboxModel> model_; |
265 | 266 |
| 267 // The current menu show count. |
| 268 int menu_show_count_ = 0; |
| 269 |
266 private: | 270 private: |
267 DISALLOW_COPY_AND_ASSIGN(ComboboxTest); | 271 DISALLOW_COPY_AND_ASSIGN(ComboboxTest); |
268 }; | 272 }; |
269 | 273 |
270 TEST_F(ComboboxTest, KeyTest) { | 274 TEST_F(ComboboxTest, KeyTest) { |
271 InitCombobox(nullptr, Combobox::STYLE_NORMAL); | 275 InitCombobox(nullptr, Combobox::STYLE_NORMAL); |
272 SendKeyEvent(ui::VKEY_END); | 276 SendKeyEvent(ui::VKEY_END); |
273 EXPECT_EQ(combobox_->selected_index() + 1, model_->GetItemCount()); | 277 EXPECT_EQ(combobox_->selected_index() + 1, model_->GetItemCount()); |
274 SendKeyEvent(ui::VKEY_HOME); | 278 SendKeyEvent(ui::VKEY_HOME); |
275 EXPECT_EQ(combobox_->selected_index(), 0); | 279 EXPECT_EQ(combobox_->selected_index(), 0); |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 combobox->set_listener(evil_listener.get()); | 500 combobox->set_listener(evil_listener.get()); |
497 ASSERT_NO_FATAL_FAILURE(ComboboxTestApi(combobox).PerformActionAt(2)); | 501 ASSERT_NO_FATAL_FAILURE(ComboboxTestApi(combobox).PerformActionAt(2)); |
498 EXPECT_TRUE(evil_listener->deleted()); | 502 EXPECT_TRUE(evil_listener->deleted()); |
499 } | 503 } |
500 | 504 |
501 TEST_F(ComboboxTest, Click) { | 505 TEST_F(ComboboxTest, Click) { |
502 InitCombobox(nullptr, Combobox::STYLE_NORMAL); | 506 InitCombobox(nullptr, Combobox::STYLE_NORMAL); |
503 | 507 |
504 TestComboboxListener listener; | 508 TestComboboxListener listener; |
505 combobox_->set_listener(&listener); | 509 combobox_->set_listener(&listener); |
506 | |
507 combobox_->Layout(); | 510 combobox_->Layout(); |
508 int menu_show_count = 0; | |
509 test_api_->InstallTestMenuRunner(&menu_show_count); | |
510 | 511 |
511 // Click the left side. The menu is shown. | 512 // Click the left side. The menu is shown. |
512 EXPECT_EQ(0, menu_show_count); | 513 EXPECT_EQ(0, menu_show_count_); |
513 PerformClick(gfx::Point(combobox_->x() + 1, | 514 PerformClick(gfx::Point(combobox_->x() + 1, |
514 combobox_->y() + combobox_->height() / 2)); | 515 combobox_->y() + combobox_->height() / 2)); |
515 EXPECT_FALSE(listener.on_perform_action_called()); | 516 EXPECT_FALSE(listener.on_perform_action_called()); |
516 EXPECT_EQ(1, menu_show_count); | 517 EXPECT_EQ(1, menu_show_count_); |
517 } | 518 } |
518 | 519 |
519 TEST_F(ComboboxTest, ClickButDisabled) { | 520 TEST_F(ComboboxTest, ClickButDisabled) { |
520 InitCombobox(nullptr, Combobox::STYLE_NORMAL); | 521 InitCombobox(nullptr, Combobox::STYLE_NORMAL); |
521 | 522 |
522 TestComboboxListener listener; | 523 TestComboboxListener listener; |
523 combobox_->set_listener(&listener); | 524 combobox_->set_listener(&listener); |
524 | 525 |
525 combobox_->Layout(); | 526 combobox_->Layout(); |
526 combobox_->SetEnabled(false); | 527 combobox_->SetEnabled(false); |
527 | 528 |
528 // Click the left side, but nothing happens since the combobox is disabled. | 529 // Click the left side, but nothing happens since the combobox is disabled. |
529 int menu_show_count = 0; | |
530 test_api_->InstallTestMenuRunner(&menu_show_count); | |
531 PerformClick(gfx::Point(combobox_->x() + 1, | 530 PerformClick(gfx::Point(combobox_->x() + 1, |
532 combobox_->y() + combobox_->height() / 2)); | 531 combobox_->y() + combobox_->height() / 2)); |
533 EXPECT_FALSE(listener.on_perform_action_called()); | 532 EXPECT_FALSE(listener.on_perform_action_called()); |
534 EXPECT_EQ(0, menu_show_count); | 533 EXPECT_EQ(0, menu_show_count_); |
535 } | 534 } |
536 | 535 |
537 TEST_F(ComboboxTest, NotifyOnClickWithReturnKey) { | 536 TEST_F(ComboboxTest, NotifyOnClickWithReturnKey) { |
538 InitCombobox(nullptr, Combobox::STYLE_NORMAL); | 537 InitCombobox(nullptr, Combobox::STYLE_NORMAL); |
539 | 538 |
540 TestComboboxListener listener; | 539 TestComboboxListener listener; |
541 combobox_->set_listener(&listener); | 540 combobox_->set_listener(&listener); |
542 | 541 |
543 // With STYLE_NORMAL, the click event is ignored. | 542 // With STYLE_NORMAL, the click event is ignored. Instead the menu is shown. |
544 SendKeyEvent(ui::VKEY_RETURN); | 543 SendKeyEvent(ui::VKEY_RETURN); |
| 544 EXPECT_EQ(1, menu_show_count_); |
545 EXPECT_FALSE(listener.on_perform_action_called()); | 545 EXPECT_FALSE(listener.on_perform_action_called()); |
546 } | 546 } |
547 | 547 |
548 TEST_F(ComboboxTest, NotifyOnClickWithReturnKeyActionStyle) { | 548 TEST_F(ComboboxTest, NotifyOnClickWithReturnKeyActionStyle) { |
549 InitCombobox(nullptr, Combobox::STYLE_ACTION); | 549 InitCombobox(nullptr, Combobox::STYLE_ACTION); |
550 | 550 |
551 TestComboboxListener listener; | 551 TestComboboxListener listener; |
552 combobox_->set_listener(&listener); | 552 combobox_->set_listener(&listener); |
553 | 553 |
554 // With STYLE_ACTION, the click event is notified. | 554 // With STYLE_ACTION, the click event is notified and the menu is not shown. |
555 SendKeyEvent(ui::VKEY_RETURN); | 555 SendKeyEvent(ui::VKEY_RETURN); |
| 556 EXPECT_EQ(0, menu_show_count_); |
556 EXPECT_TRUE(listener.on_perform_action_called()); | 557 EXPECT_TRUE(listener.on_perform_action_called()); |
557 EXPECT_EQ(0, listener.perform_action_index()); | 558 EXPECT_EQ(0, listener.perform_action_index()); |
558 } | 559 } |
559 | 560 |
560 TEST_F(ComboboxTest, NotifyOnClickWithSpaceKey) { | 561 TEST_F(ComboboxTest, NotifyOnClickWithSpaceKey) { |
561 InitCombobox(nullptr, Combobox::STYLE_NORMAL); | 562 InitCombobox(nullptr, Combobox::STYLE_NORMAL); |
562 | 563 |
563 TestComboboxListener listener; | 564 TestComboboxListener listener; |
564 combobox_->set_listener(&listener); | 565 combobox_->set_listener(&listener); |
565 | 566 |
566 // With STYLE_NORMAL, the click event is ignored. | 567 // With STYLE_NORMAL, the click event is ignored. Instead the menu is shwon. |
567 SendKeyEvent(ui::VKEY_SPACE); | 568 SendKeyEvent(ui::VKEY_SPACE); |
| 569 EXPECT_EQ(1, menu_show_count_); |
568 EXPECT_FALSE(listener.on_perform_action_called()); | 570 EXPECT_FALSE(listener.on_perform_action_called()); |
| 571 |
569 SendKeyEventWithType(ui::VKEY_SPACE, ui::ET_KEY_RELEASED); | 572 SendKeyEventWithType(ui::VKEY_SPACE, ui::ET_KEY_RELEASED); |
| 573 EXPECT_EQ(1, menu_show_count_); |
570 EXPECT_FALSE(listener.on_perform_action_called()); | 574 EXPECT_FALSE(listener.on_perform_action_called()); |
571 } | 575 } |
572 | 576 |
573 TEST_F(ComboboxTest, NotifyOnClickWithSpaceKeyActionStyle) { | 577 TEST_F(ComboboxTest, NotifyOnClickWithSpaceKeyActionStyle) { |
574 InitCombobox(nullptr, Combobox::STYLE_ACTION); | 578 InitCombobox(nullptr, Combobox::STYLE_ACTION); |
575 | 579 |
576 TestComboboxListener listener; | 580 TestComboboxListener listener; |
577 combobox_->set_listener(&listener); | 581 combobox_->set_listener(&listener); |
578 | 582 |
579 // With STYLE_ACTION, the click event is notified after releasing. | 583 // With STYLE_ACTION, the click event is notified after releasing and the menu |
| 584 // is not shown. |
580 SendKeyEvent(ui::VKEY_SPACE); | 585 SendKeyEvent(ui::VKEY_SPACE); |
| 586 EXPECT_EQ(0, menu_show_count_); |
581 EXPECT_FALSE(listener.on_perform_action_called()); | 587 EXPECT_FALSE(listener.on_perform_action_called()); |
| 588 |
582 SendKeyEventWithType(ui::VKEY_SPACE, ui::ET_KEY_RELEASED); | 589 SendKeyEventWithType(ui::VKEY_SPACE, ui::ET_KEY_RELEASED); |
| 590 EXPECT_EQ(0, menu_show_count_); |
583 EXPECT_TRUE(listener.on_perform_action_called()); | 591 EXPECT_TRUE(listener.on_perform_action_called()); |
584 EXPECT_EQ(0, listener.perform_action_index()); | 592 EXPECT_EQ(0, listener.perform_action_index()); |
585 } | 593 } |
586 | 594 |
587 TEST_F(ComboboxTest, NotifyOnClickWithMouse) { | 595 TEST_F(ComboboxTest, NotifyOnClickWithMouse) { |
588 InitCombobox(nullptr, Combobox::STYLE_ACTION); | 596 InitCombobox(nullptr, Combobox::STYLE_ACTION); |
589 | 597 |
590 TestComboboxListener listener; | 598 TestComboboxListener listener; |
591 combobox_->set_listener(&listener); | 599 combobox_->set_listener(&listener); |
592 | 600 |
593 combobox_->Layout(); | 601 combobox_->Layout(); |
594 | 602 |
595 // Click the right side (arrow button). The menu is shown. | 603 // Click the right side (arrow button). The menu is shown. |
596 int menu_show_count = 0; | |
597 test_api_->InstallTestMenuRunner(&menu_show_count); | |
598 const gfx::Point right_point(combobox_->x() + combobox_->width() - 1, | 604 const gfx::Point right_point(combobox_->x() + combobox_->width() - 1, |
599 combobox_->y() + combobox_->height() / 2); | 605 combobox_->y() + combobox_->height() / 2); |
600 | 606 |
601 EXPECT_EQ(0, menu_show_count); | 607 EXPECT_EQ(0, menu_show_count_); |
602 | 608 |
603 // On Mac, actions occur on mouse down. Otherwise mouse up. | 609 // On Mac, actions occur on mouse down. Otherwise mouse up. |
604 #if defined(OS_MACOSX) | 610 #if defined(OS_MACOSX) |
605 const int kActOnMouseDown = 1; | 611 const int kActOnMouseDown = 1; |
606 #else | 612 #else |
607 const int kActOnMouseDown = 0; | 613 const int kActOnMouseDown = 0; |
608 #endif | 614 #endif |
609 | 615 |
610 PerformMousePress(right_point); | 616 PerformMousePress(right_point); |
611 EXPECT_EQ(kActOnMouseDown, menu_show_count); | 617 EXPECT_EQ(kActOnMouseDown, menu_show_count_); |
612 PerformMouseRelease(right_point); | 618 PerformMouseRelease(right_point); |
613 EXPECT_EQ(1, menu_show_count); | 619 EXPECT_EQ(1, menu_show_count_); |
614 | 620 |
615 // Click the left side (text button). The click event is notified. | 621 // Click the left side (text button). The click event is notified. |
616 const gfx::Point left_point( | 622 const gfx::Point left_point( |
617 gfx::Point(combobox_->x() + 1, combobox_->y() + combobox_->height() / 2)); | 623 gfx::Point(combobox_->x() + 1, combobox_->y() + combobox_->height() / 2)); |
618 test_api_->InstallTestMenuRunner(&menu_show_count); | |
619 | 624 |
620 PerformMousePress(left_point); | 625 PerformMousePress(left_point); |
621 PerformMouseRelease(left_point); | 626 PerformMouseRelease(left_point); |
622 | 627 |
623 EXPECT_EQ(1, menu_show_count); // Unchanged. | 628 EXPECT_EQ(1, menu_show_count_); // Unchanged. |
624 EXPECT_EQ(0, listener.perform_action_index()); | 629 EXPECT_EQ(0, listener.perform_action_index()); |
625 } | 630 } |
626 | 631 |
627 TEST_F(ComboboxTest, ConsumingPressKeyEvents) { | 632 TEST_F(ComboboxTest, ConsumingPressKeyEvents) { |
628 InitCombobox(nullptr, Combobox::STYLE_NORMAL); | 633 InitCombobox(nullptr, Combobox::STYLE_NORMAL); |
629 | 634 |
630 int menu_show_count = 0; | |
631 test_api_->InstallTestMenuRunner(&menu_show_count); | |
632 EXPECT_TRUE(combobox_->OnKeyPressed( | 635 EXPECT_TRUE(combobox_->OnKeyPressed( |
633 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::EF_NONE))); | 636 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::EF_NONE))); |
634 EXPECT_EQ(1, menu_show_count); | 637 EXPECT_EQ(1, menu_show_count_); |
635 EXPECT_TRUE(combobox_->OnKeyPressed( | 638 EXPECT_TRUE(combobox_->OnKeyPressed( |
636 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, ui::EF_NONE))); | 639 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, ui::EF_NONE))); |
637 EXPECT_EQ(2, menu_show_count); | 640 EXPECT_EQ(2, menu_show_count_); |
638 } | 641 } |
639 | 642 |
640 TEST_F(ComboboxTest, ConsumingKeyPressEventsActionStyle) { | 643 TEST_F(ComboboxTest, ConsumingKeyPressEventsActionStyle) { |
641 // When the combobox's style is STYLE_ACTION, pressing events of a space key | 644 // When the combobox's style is STYLE_ACTION, pressing events of a space key |
642 // or an enter key will be consumed. | 645 // or an enter key will be consumed and the menu is not shown. |
643 InitCombobox(nullptr, Combobox::STYLE_ACTION); | 646 InitCombobox(nullptr, Combobox::STYLE_ACTION); |
| 647 |
644 EXPECT_TRUE(combobox_->OnKeyPressed( | 648 EXPECT_TRUE(combobox_->OnKeyPressed( |
645 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::EF_NONE))); | 649 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::EF_NONE))); |
| 650 EXPECT_EQ(0, menu_show_count_); |
646 EXPECT_TRUE(combobox_->OnKeyPressed( | 651 EXPECT_TRUE(combobox_->OnKeyPressed( |
647 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, ui::EF_NONE))); | 652 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, ui::EF_NONE))); |
| 653 EXPECT_EQ(0, menu_show_count_); |
648 } | 654 } |
649 | 655 |
650 TEST_F(ComboboxTest, ContentWidth) { | 656 TEST_F(ComboboxTest, ContentWidth) { |
651 std::vector<std::string> values; | 657 std::vector<std::string> values; |
652 VectorComboboxModel model(&values); | 658 VectorComboboxModel model(&values); |
653 TestCombobox combobox(&model, Combobox::STYLE_NORMAL); | 659 TestCombobox combobox(&model, Combobox::STYLE_NORMAL); |
654 TestCombobox action_combobox(&model, Combobox::STYLE_ACTION); | 660 TestCombobox action_combobox(&model, Combobox::STYLE_ACTION); |
655 ComboboxTestApi test_api(&combobox); | 661 ComboboxTestApi test_api(&combobox); |
656 ComboboxTestApi action_test_api(&action_combobox); | 662 ComboboxTestApi action_test_api(&action_combobox); |
657 | 663 |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
818 EXPECT_EQ(ui::MenuModel::TYPE_COMMAND, menu_model->GetTypeAt(0)); | 824 EXPECT_EQ(ui::MenuModel::TYPE_COMMAND, menu_model->GetTypeAt(0)); |
819 EXPECT_EQ(ui::MenuModel::TYPE_COMMAND, menu_model->GetTypeAt(1)); | 825 EXPECT_EQ(ui::MenuModel::TYPE_COMMAND, menu_model->GetTypeAt(1)); |
820 | 826 |
821 EXPECT_EQ(ASCIIToUTF16("PEANUT BUTTER"), menu_model->GetLabelAt(0)); | 827 EXPECT_EQ(ASCIIToUTF16("PEANUT BUTTER"), menu_model->GetLabelAt(0)); |
822 EXPECT_EQ(ASCIIToUTF16("JELLY"), menu_model->GetLabelAt(1)); | 828 EXPECT_EQ(ASCIIToUTF16("JELLY"), menu_model->GetLabelAt(1)); |
823 EXPECT_FALSE(menu_model->IsVisibleAt(0)); | 829 EXPECT_FALSE(menu_model->IsVisibleAt(0)); |
824 EXPECT_TRUE(menu_model->IsVisibleAt(1)); | 830 EXPECT_TRUE(menu_model->IsVisibleAt(1)); |
825 } | 831 } |
826 | 832 |
827 } // namespace views | 833 } // namespace views |
OLD | NEW |