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/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
11 #include "ui/base/ime/input_method.h" | 11 #include "ui/base/ime/input_method.h" |
12 #include "ui/base/ime/text_input_client.h" | 12 #include "ui/base/ime/text_input_client.h" |
13 #include "ui/base/models/combobox_model.h" | 13 #include "ui/base/models/combobox_model.h" |
| 14 #include "ui/base/models/menu_model.h" |
14 #include "ui/events/event.h" | 15 #include "ui/events/event.h" |
15 #include "ui/events/event_constants.h" | 16 #include "ui/events/event_constants.h" |
16 #include "ui/events/event_utils.h" | 17 #include "ui/events/event_utils.h" |
17 #include "ui/events/keycodes/keyboard_codes.h" | 18 #include "ui/events/keycodes/keyboard_codes.h" |
18 #include "ui/views/controls/combobox/combobox_listener.h" | 19 #include "ui/views/controls/combobox/combobox_listener.h" |
19 #include "ui/views/controls/menu/menu_runner.h" | 20 #include "ui/views/controls/menu/menu_runner.h" |
20 #include "ui/views/controls/menu/menu_runner_handler.h" | 21 #include "ui/views/controls/menu/menu_runner_handler.h" |
21 #include "ui/views/test/menu_runner_test_api.h" | 22 #include "ui/views/test/menu_runner_test_api.h" |
22 #include "ui/views/test/views_test_base.h" | 23 #include "ui/views/test/views_test_base.h" |
23 #include "ui/views/widget/widget.h" | 24 #include "ui/views/widget/widget.h" |
24 | 25 |
25 using base::ASCIIToUTF16; | 26 using base::ASCIIToUTF16; |
26 | 27 |
27 namespace views { | 28 namespace views { |
| 29 namespace test { |
| 30 |
| 31 class ComboboxTestApi { |
| 32 public: |
| 33 explicit ComboboxTestApi(Combobox* combobox) : combobox_(combobox) {} |
| 34 |
| 35 void PerformActionAt(int index) { menu_model()->ActivatedAt(index); } |
| 36 void InstallTestMenuRunner(int* menu_show_count); |
| 37 |
| 38 gfx::Size content_size() { return combobox_->content_size_; } |
| 39 ui::MenuModel* menu_model() { return combobox_->menu_model_adapter_.get(); } |
| 40 |
| 41 private: |
| 42 Combobox* combobox_; |
| 43 |
| 44 DISALLOW_COPY_AND_ASSIGN(ComboboxTestApi); |
| 45 }; |
| 46 |
| 47 } // namespace test |
| 48 |
| 49 using test::ComboboxTestApi; |
28 | 50 |
29 namespace { | 51 namespace { |
30 | 52 |
31 // An dummy implementation of MenuRunnerHandler to check if the dropdown menu is | 53 // An dummy implementation of MenuRunnerHandler to check if the dropdown menu is |
32 // shown or not. | 54 // shown or not. |
33 class TestMenuRunnerHandler : public MenuRunnerHandler { | 55 class TestMenuRunnerHandler : public MenuRunnerHandler { |
34 public: | 56 public: |
35 TestMenuRunnerHandler() : executed_(false) {} | 57 explicit TestMenuRunnerHandler(int* show_counter) |
36 | 58 : show_counter_(show_counter) {} |
37 bool executed() const { return executed_; } | |
38 | |
39 MenuRunner::RunResult RunMenuAt(Widget* parent, | 59 MenuRunner::RunResult RunMenuAt(Widget* parent, |
40 MenuButton* button, | 60 MenuButton* button, |
41 const gfx::Rect& bounds, | 61 const gfx::Rect& bounds, |
42 MenuAnchorPosition anchor, | 62 MenuAnchorPosition anchor, |
43 ui::MenuSourceType source_type, | 63 ui::MenuSourceType source_type, |
44 int32 types) override { | 64 int32 types) override { |
45 executed_ = true; | 65 *show_counter_ += 1; |
46 return MenuRunner::NORMAL_EXIT; | 66 return MenuRunner::NORMAL_EXIT; |
47 } | 67 } |
48 | 68 |
49 private: | 69 private: |
50 bool executed_; | 70 int* show_counter_; |
51 | 71 |
52 DISALLOW_COPY_AND_ASSIGN(TestMenuRunnerHandler); | 72 DISALLOW_COPY_AND_ASSIGN(TestMenuRunnerHandler); |
53 }; | 73 }; |
54 | 74 |
55 // A wrapper of Combobox to intercept the result of OnKeyPressed() and | 75 // A wrapper of Combobox to intercept the result of OnKeyPressed() and |
56 // OnKeyReleased() methods. | 76 // OnKeyReleased() methods. |
57 class TestCombobox : public Combobox { | 77 class TestCombobox : public Combobox { |
58 public: | 78 public: |
59 explicit TestCombobox(ui::ComboboxModel* model) | 79 explicit TestCombobox(ui::ComboboxModel* model) |
60 : Combobox(model), | 80 : Combobox(model), |
(...skipping 25 matching lines...) Expand all Loading... |
86 | 106 |
87 DISALLOW_COPY_AND_ASSIGN(TestCombobox); | 107 DISALLOW_COPY_AND_ASSIGN(TestCombobox); |
88 }; | 108 }; |
89 | 109 |
90 // A concrete class is needed to test the combobox. | 110 // A concrete class is needed to test the combobox. |
91 class TestComboboxModel : public ui::ComboboxModel { | 111 class TestComboboxModel : public ui::ComboboxModel { |
92 public: | 112 public: |
93 TestComboboxModel() {} | 113 TestComboboxModel() {} |
94 ~TestComboboxModel() override {} | 114 ~TestComboboxModel() override {} |
95 | 115 |
96 static const int kItemCount = 10; | 116 enum { kItemCount = 10 }; |
97 | 117 |
98 // ui::ComboboxModel: | 118 // ui::ComboboxModel: |
99 int GetItemCount() const override { return kItemCount; } | 119 int GetItemCount() const override { return item_count_; } |
100 base::string16 GetItemAt(int index) override { | 120 base::string16 GetItemAt(int index) override { |
101 if (IsItemSeparatorAt(index)) { | 121 if (IsItemSeparatorAt(index)) { |
102 NOTREACHED(); | 122 NOTREACHED(); |
103 return ASCIIToUTF16("SEPARATOR"); | 123 return ASCIIToUTF16("SEPARATOR"); |
104 } | 124 } |
105 return ASCIIToUTF16(index % 2 == 0 ? "PEANUT BUTTER" : "JELLY"); | 125 return ASCIIToUTF16(index % 2 == 0 ? "PEANUT BUTTER" : "JELLY"); |
106 } | 126 } |
107 bool IsItemSeparatorAt(int index) override { | 127 bool IsItemSeparatorAt(int index) override { |
108 return separators_.find(index) != separators_.end(); | 128 return separators_.find(index) != separators_.end(); |
109 } | 129 } |
110 | 130 |
111 int GetDefaultIndex() const override { | 131 int GetDefaultIndex() const override { |
112 // Return the first index that is not a separator. | 132 // Return the first index that is not a separator. |
113 for (int index = 0; index < kItemCount; ++index) { | 133 for (int index = 0; index < kItemCount; ++index) { |
114 if (separators_.find(index) == separators_.end()) | 134 if (separators_.find(index) == separators_.end()) |
115 return index; | 135 return index; |
116 } | 136 } |
117 NOTREACHED(); | 137 NOTREACHED(); |
118 return 0; | 138 return 0; |
119 } | 139 } |
120 | 140 |
121 void SetSeparators(const std::set<int>& separators) { | 141 void SetSeparators(const std::set<int>& separators) { |
122 separators_ = separators; | 142 separators_ = separators; |
123 } | 143 } |
124 | 144 |
| 145 void set_item_count(int item_count) { item_count_ = item_count; } |
| 146 |
125 private: | 147 private: |
126 std::set<int> separators_; | 148 std::set<int> separators_; |
| 149 int item_count_ = kItemCount; |
127 | 150 |
128 DISALLOW_COPY_AND_ASSIGN(TestComboboxModel); | 151 DISALLOW_COPY_AND_ASSIGN(TestComboboxModel); |
129 }; | 152 }; |
130 | 153 |
131 // A combobox model which refers to a vector. | 154 // A combobox model which refers to a vector. |
132 class VectorComboboxModel : public ui::ComboboxModel { | 155 class VectorComboboxModel : public ui::ComboboxModel { |
133 public: | 156 public: |
134 explicit VectorComboboxModel(std::vector<std::string>* values) | 157 explicit VectorComboboxModel(std::vector<std::string>* values) |
135 : values_(values) {} | 158 : values_(values) {} |
136 ~VectorComboboxModel() override {} | 159 ~VectorComboboxModel() override {} |
137 | 160 |
| 161 void set_default_index(int default_index) { default_index_ = default_index; } |
| 162 |
138 // ui::ComboboxModel: | 163 // ui::ComboboxModel: |
139 int GetItemCount() const override { return (int)values_->size(); } | 164 int GetItemCount() const override { return (int)values_->size(); } |
140 base::string16 GetItemAt(int index) override { | 165 base::string16 GetItemAt(int index) override { |
141 return ASCIIToUTF16(values_->at(index)); | 166 return ASCIIToUTF16(values_->at(index)); |
142 } | 167 } |
143 bool IsItemSeparatorAt(int index) override { return false; } | 168 bool IsItemSeparatorAt(int index) override { return false; } |
| 169 int GetDefaultIndex() const override { return default_index_; } |
144 | 170 |
145 private: | 171 private: |
146 std::vector<std::string>* values_; | 172 std::vector<std::string>* values_; |
| 173 int default_index_ = 0; |
| 174 |
| 175 DISALLOW_COPY_AND_ASSIGN(VectorComboboxModel); |
147 }; | 176 }; |
148 | 177 |
149 class EvilListener : public ComboboxListener { | 178 class EvilListener : public ComboboxListener { |
150 public: | 179 public: |
151 EvilListener() : deleted_(false) {} | 180 EvilListener() : deleted_(false) {} |
152 ~EvilListener() override{}; | 181 ~EvilListener() override{}; |
153 | 182 |
154 // ComboboxListener: | 183 // ComboboxListener: |
155 void OnPerformAction(Combobox* combobox) override { | 184 void OnPerformAction(Combobox* combobox) override { |
156 delete combobox; | 185 delete combobox; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 private: | 219 private: |
191 int perform_action_index_; | 220 int perform_action_index_; |
192 int actions_performed_; | 221 int actions_performed_; |
193 | 222 |
194 private: | 223 private: |
195 DISALLOW_COPY_AND_ASSIGN(TestComboboxListener); | 224 DISALLOW_COPY_AND_ASSIGN(TestComboboxListener); |
196 }; | 225 }; |
197 | 226 |
198 } // namespace | 227 } // namespace |
199 | 228 |
| 229 void ComboboxTestApi::InstallTestMenuRunner(int* menu_show_count) { |
| 230 combobox_->menu_runner_.reset( |
| 231 new MenuRunner(menu_model(), MenuRunner::COMBOBOX)); |
| 232 test::MenuRunnerTestAPI test_api(combobox_->menu_runner_.get()); |
| 233 test_api.SetMenuRunnerHandler( |
| 234 make_scoped_ptr(new TestMenuRunnerHandler(menu_show_count))); |
| 235 } |
| 236 |
200 class ComboboxTest : public ViewsTestBase { | 237 class ComboboxTest : public ViewsTestBase { |
201 public: | 238 public: |
202 ComboboxTest() : widget_(NULL), combobox_(NULL) {} | 239 ComboboxTest() : widget_(NULL), combobox_(NULL) {} |
203 | 240 |
204 void TearDown() override { | 241 void TearDown() override { |
205 if (widget_) | 242 if (widget_) |
206 widget_->Close(); | 243 widget_->Close(); |
207 ViewsTestBase::TearDown(); | 244 ViewsTestBase::TearDown(); |
208 } | 245 } |
209 | 246 |
210 void InitCombobox(const std::set<int>* separators) { | 247 void InitCombobox(const std::set<int>* separators) { |
211 model_.reset(new TestComboboxModel()); | 248 model_.reset(new TestComboboxModel()); |
212 | 249 |
213 if (separators) | 250 if (separators) |
214 model_->SetSeparators(*separators); | 251 model_->SetSeparators(*separators); |
215 | 252 |
216 ASSERT_FALSE(combobox_); | 253 ASSERT_FALSE(combobox_); |
217 combobox_ = new TestCombobox(model_.get()); | 254 combobox_ = new TestCombobox(model_.get()); |
| 255 test_api_.reset(new ComboboxTestApi(combobox_)); |
218 combobox_->set_id(1); | 256 combobox_->set_id(1); |
219 | 257 |
220 widget_ = new Widget; | 258 widget_ = new Widget; |
221 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); | 259 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); |
222 params.bounds = gfx::Rect(200, 200, 200, 200); | 260 params.bounds = gfx::Rect(200, 200, 200, 200); |
223 widget_->Init(params); | 261 widget_->Init(params); |
224 View* container = new View(); | 262 View* container = new View(); |
225 widget_->SetContentsView(container); | 263 widget_->SetContentsView(container); |
226 container->AddChildView(combobox_); | 264 container->AddChildView(combobox_); |
227 | 265 |
(...skipping 27 matching lines...) Expand all Loading... |
255 ui::ET_MOUSE_RELEASED, point, point, ui::EventTimeForNow(), | 293 ui::ET_MOUSE_RELEASED, point, point, ui::EventTimeForNow(), |
256 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | 294 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); |
257 widget_->OnMouseEvent(&released_event); | 295 widget_->OnMouseEvent(&released_event); |
258 } | 296 } |
259 | 297 |
260 // We need widget to populate wrapper class. | 298 // We need widget to populate wrapper class. |
261 Widget* widget_; | 299 Widget* widget_; |
262 | 300 |
263 // |combobox_| will be allocated InitCombobox() and then owned by |widget_|. | 301 // |combobox_| will be allocated InitCombobox() and then owned by |widget_|. |
264 TestCombobox* combobox_; | 302 TestCombobox* combobox_; |
| 303 scoped_ptr<ComboboxTestApi> test_api_; |
265 | 304 |
266 // Combobox does not take ownership of the model, hence it needs to be scoped. | 305 // Combobox does not take ownership of the model, hence it needs to be scoped. |
267 scoped_ptr<TestComboboxModel> model_; | 306 scoped_ptr<TestComboboxModel> model_; |
| 307 |
| 308 private: |
| 309 DISALLOW_COPY_AND_ASSIGN(ComboboxTest); |
268 }; | 310 }; |
269 | 311 |
270 TEST_F(ComboboxTest, KeyTest) { | 312 TEST_F(ComboboxTest, KeyTest) { |
271 InitCombobox(NULL); | 313 InitCombobox(NULL); |
272 SendKeyEvent(ui::VKEY_END); | 314 SendKeyEvent(ui::VKEY_END); |
273 EXPECT_EQ(combobox_->selected_index() + 1, model_->GetItemCount()); | 315 EXPECT_EQ(combobox_->selected_index() + 1, model_->GetItemCount()); |
274 SendKeyEvent(ui::VKEY_HOME); | 316 SendKeyEvent(ui::VKEY_HOME); |
275 EXPECT_EQ(combobox_->selected_index(), 0); | 317 EXPECT_EQ(combobox_->selected_index(), 0); |
276 SendKeyEvent(ui::VKEY_DOWN); | 318 SendKeyEvent(ui::VKEY_DOWN); |
277 SendKeyEvent(ui::VKEY_DOWN); | 319 SendKeyEvent(ui::VKEY_DOWN); |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 EXPECT_EQ(0, combobox_->selected_index()); | 520 EXPECT_EQ(0, combobox_->selected_index()); |
479 } | 521 } |
480 | 522 |
481 TEST_F(ComboboxTest, ListenerHandlesDelete) { | 523 TEST_F(ComboboxTest, ListenerHandlesDelete) { |
482 TestComboboxModel model; | 524 TestComboboxModel model; |
483 | 525 |
484 // |combobox| will be deleted on change. | 526 // |combobox| will be deleted on change. |
485 TestCombobox* combobox = new TestCombobox(&model); | 527 TestCombobox* combobox = new TestCombobox(&model); |
486 scoped_ptr<EvilListener> evil_listener(new EvilListener()); | 528 scoped_ptr<EvilListener> evil_listener(new EvilListener()); |
487 combobox->set_listener(evil_listener.get()); | 529 combobox->set_listener(evil_listener.get()); |
488 ASSERT_NO_FATAL_FAILURE(combobox->ExecuteCommand(2)); | 530 ASSERT_NO_FATAL_FAILURE(ComboboxTestApi(combobox).PerformActionAt(2)); |
489 EXPECT_TRUE(evil_listener->deleted()); | 531 EXPECT_TRUE(evil_listener->deleted()); |
490 | 532 |
491 // With STYLE_ACTION | 533 // With STYLE_ACTION |
492 // |combobox| will be deleted on change. | 534 // |combobox| will be deleted on change. |
493 combobox = new TestCombobox(&model); | 535 combobox = new TestCombobox(&model); |
494 evil_listener.reset(new EvilListener()); | 536 evil_listener.reset(new EvilListener()); |
495 combobox->set_listener(evil_listener.get()); | 537 combobox->set_listener(evil_listener.get()); |
496 combobox->SetStyle(Combobox::STYLE_ACTION); | 538 combobox->SetStyle(Combobox::STYLE_ACTION); |
497 ASSERT_NO_FATAL_FAILURE(combobox->ExecuteCommand(2)); | 539 ASSERT_NO_FATAL_FAILURE(ComboboxTestApi(combobox).PerformActionAt(2)); |
498 EXPECT_TRUE(evil_listener->deleted()); | 540 EXPECT_TRUE(evil_listener->deleted()); |
499 } | 541 } |
500 | 542 |
501 TEST_F(ComboboxTest, Click) { | 543 TEST_F(ComboboxTest, Click) { |
502 InitCombobox(NULL); | 544 InitCombobox(NULL); |
503 | 545 |
504 TestComboboxListener listener; | 546 TestComboboxListener listener; |
505 combobox_->set_listener(&listener); | 547 combobox_->set_listener(&listener); |
506 | 548 |
507 combobox_->Layout(); | 549 combobox_->Layout(); |
| 550 int menu_show_count = 0; |
| 551 test_api_->InstallTestMenuRunner(&menu_show_count); |
508 | 552 |
509 // Click the left side. The menu is shown. | 553 // Click the left side. The menu is shown. |
510 TestMenuRunnerHandler* test_menu_runner_handler = new TestMenuRunnerHandler(); | 554 EXPECT_EQ(0, menu_show_count); |
511 scoped_ptr<MenuRunnerHandler> menu_runner_handler(test_menu_runner_handler); | |
512 test::MenuRunnerTestAPI test_api( | |
513 combobox_->dropdown_list_menu_runner_.get()); | |
514 test_api.SetMenuRunnerHandler(menu_runner_handler.Pass()); | |
515 PerformClick(gfx::Point(combobox_->x() + 1, | 555 PerformClick(gfx::Point(combobox_->x() + 1, |
516 combobox_->y() + combobox_->height() / 2)); | 556 combobox_->y() + combobox_->height() / 2)); |
517 EXPECT_FALSE(listener.on_perform_action_called()); | 557 EXPECT_FALSE(listener.on_perform_action_called()); |
518 EXPECT_TRUE(test_menu_runner_handler->executed()); | 558 EXPECT_EQ(1, menu_show_count); |
519 } | 559 } |
520 | 560 |
521 TEST_F(ComboboxTest, ClickButDisabled) { | 561 TEST_F(ComboboxTest, ClickButDisabled) { |
522 InitCombobox(NULL); | 562 InitCombobox(NULL); |
523 | 563 |
524 TestComboboxListener listener; | 564 TestComboboxListener listener; |
525 combobox_->set_listener(&listener); | 565 combobox_->set_listener(&listener); |
526 | 566 |
527 combobox_->Layout(); | 567 combobox_->Layout(); |
528 combobox_->SetEnabled(false); | 568 combobox_->SetEnabled(false); |
529 | 569 |
530 // Click the left side, but nothing happens since the combobox is disabled. | 570 // Click the left side, but nothing happens since the combobox is disabled. |
531 TestMenuRunnerHandler* test_menu_runner_handler = new TestMenuRunnerHandler(); | 571 int menu_show_count = 0; |
532 scoped_ptr<MenuRunnerHandler> menu_runner_handler(test_menu_runner_handler); | 572 test_api_->InstallTestMenuRunner(&menu_show_count); |
533 test::MenuRunnerTestAPI test_api( | |
534 combobox_->dropdown_list_menu_runner_.get()); | |
535 test_api.SetMenuRunnerHandler(menu_runner_handler.Pass()); | |
536 PerformClick(gfx::Point(combobox_->x() + 1, | 573 PerformClick(gfx::Point(combobox_->x() + 1, |
537 combobox_->y() + combobox_->height() / 2)); | 574 combobox_->y() + combobox_->height() / 2)); |
538 EXPECT_FALSE(listener.on_perform_action_called()); | 575 EXPECT_FALSE(listener.on_perform_action_called()); |
539 EXPECT_FALSE(test_menu_runner_handler->executed()); | 576 EXPECT_EQ(0, menu_show_count); |
540 } | 577 } |
541 | 578 |
542 TEST_F(ComboboxTest, NotifyOnClickWithReturnKey) { | 579 TEST_F(ComboboxTest, NotifyOnClickWithReturnKey) { |
543 InitCombobox(NULL); | 580 InitCombobox(NULL); |
544 | 581 |
545 TestComboboxListener listener; | 582 TestComboboxListener listener; |
546 combobox_->set_listener(&listener); | 583 combobox_->set_listener(&listener); |
547 | 584 |
548 // With STYLE_NORMAL, the click event is ignored. | 585 // With STYLE_NORMAL, the click event is ignored. |
549 SendKeyEvent(ui::VKEY_RETURN); | 586 SendKeyEvent(ui::VKEY_RETURN); |
(...skipping 30 matching lines...) Expand all Loading... |
580 TEST_F(ComboboxTest, NotifyOnClickWithMouse) { | 617 TEST_F(ComboboxTest, NotifyOnClickWithMouse) { |
581 InitCombobox(NULL); | 618 InitCombobox(NULL); |
582 | 619 |
583 TestComboboxListener listener; | 620 TestComboboxListener listener; |
584 combobox_->set_listener(&listener); | 621 combobox_->set_listener(&listener); |
585 | 622 |
586 combobox_->SetStyle(Combobox::STYLE_ACTION); | 623 combobox_->SetStyle(Combobox::STYLE_ACTION); |
587 combobox_->Layout(); | 624 combobox_->Layout(); |
588 | 625 |
589 // Click the right side (arrow button). The menu is shown. | 626 // Click the right side (arrow button). The menu is shown. |
590 TestMenuRunnerHandler* test_menu_runner_handler = new TestMenuRunnerHandler(); | 627 int menu_show_count = 0; |
591 scoped_ptr<MenuRunnerHandler> menu_runner_handler(test_menu_runner_handler); | 628 test_api_->InstallTestMenuRunner(&menu_show_count); |
592 scoped_ptr<test::MenuRunnerTestAPI> test_api( | 629 EXPECT_EQ(0, menu_show_count); |
593 new test::MenuRunnerTestAPI(combobox_->dropdown_list_menu_runner_.get())); | |
594 test_api->SetMenuRunnerHandler(menu_runner_handler.Pass()); | |
595 | |
596 PerformClick(gfx::Point(combobox_->x() + combobox_->width() - 1, | 630 PerformClick(gfx::Point(combobox_->x() + combobox_->width() - 1, |
597 combobox_->y() + combobox_->height() / 2)); | 631 combobox_->y() + combobox_->height() / 2)); |
598 EXPECT_FALSE(listener.on_perform_action_called()); | 632 EXPECT_FALSE(listener.on_perform_action_called()); |
599 EXPECT_TRUE(test_menu_runner_handler->executed()); | 633 EXPECT_EQ(1, menu_show_count); |
600 | 634 |
601 // Click the left side (text button). The click event is notified. | 635 // Click the left side (text button). The click event is notified. |
602 test_menu_runner_handler = new TestMenuRunnerHandler(); | 636 test_api_->InstallTestMenuRunner(&menu_show_count); |
603 menu_runner_handler.reset(test_menu_runner_handler); | |
604 test_api.reset( | |
605 new test::MenuRunnerTestAPI(combobox_->dropdown_list_menu_runner_.get())); | |
606 test_api->SetMenuRunnerHandler(menu_runner_handler.Pass()); | |
607 PerformClick(gfx::Point(combobox_->x() + 1, | 637 PerformClick(gfx::Point(combobox_->x() + 1, |
608 combobox_->y() + combobox_->height() / 2)); | 638 combobox_->y() + combobox_->height() / 2)); |
609 EXPECT_TRUE(listener.on_perform_action_called()); | 639 EXPECT_TRUE(listener.on_perform_action_called()); |
610 EXPECT_FALSE(test_menu_runner_handler->executed()); | 640 EXPECT_EQ(1, menu_show_count); // Unchanged. |
611 EXPECT_EQ(0, listener.perform_action_index()); | 641 EXPECT_EQ(0, listener.perform_action_index()); |
612 } | 642 } |
613 | 643 |
614 TEST_F(ComboboxTest, ConsumingPressKeyEvents) { | 644 TEST_F(ComboboxTest, ConsumingPressKeyEvents) { |
615 InitCombobox(NULL); | 645 InitCombobox(NULL); |
616 | 646 |
617 EXPECT_FALSE(combobox_->OnKeyPressed( | 647 EXPECT_FALSE(combobox_->OnKeyPressed( |
618 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::EF_NONE))); | 648 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::EF_NONE))); |
619 EXPECT_FALSE(combobox_->OnKeyPressed( | 649 EXPECT_FALSE(combobox_->OnKeyPressed( |
620 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, ui::EF_NONE))); | 650 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, ui::EF_NONE))); |
621 | 651 |
622 // When the combobox's style is STYLE_ACTION, pressing events of a space key | 652 // When the combobox's style is STYLE_ACTION, pressing events of a space key |
623 // or an enter key will be consumed. | 653 // or an enter key will be consumed. |
624 combobox_->SetStyle(Combobox::STYLE_ACTION); | 654 combobox_->SetStyle(Combobox::STYLE_ACTION); |
625 EXPECT_TRUE(combobox_->OnKeyPressed( | 655 EXPECT_TRUE(combobox_->OnKeyPressed( |
626 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::EF_NONE))); | 656 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::EF_NONE))); |
627 EXPECT_TRUE(combobox_->OnKeyPressed( | 657 EXPECT_TRUE(combobox_->OnKeyPressed( |
628 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, ui::EF_NONE))); | 658 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, ui::EF_NONE))); |
629 } | 659 } |
630 | 660 |
631 TEST_F(ComboboxTest, ContentWidth) { | 661 TEST_F(ComboboxTest, ContentWidth) { |
632 std::vector<std::string> values; | 662 std::vector<std::string> values; |
633 VectorComboboxModel model(&values); | 663 VectorComboboxModel model(&values); |
634 TestCombobox combobox(&model); | 664 TestCombobox combobox(&model); |
| 665 ComboboxTestApi test_api(&combobox); |
635 | 666 |
636 std::string long_item = "this is the long item"; | 667 std::string long_item = "this is the long item"; |
637 std::string short_item = "s"; | 668 std::string short_item = "s"; |
638 | 669 |
639 values.resize(1); | 670 values.resize(1); |
640 values[0] = long_item; | 671 values[0] = long_item; |
641 combobox.ModelChanged(); | 672 combobox.ModelChanged(); |
642 | 673 |
643 const int long_item_width = combobox.content_size_.width(); | 674 const int long_item_width = test_api.content_size().width(); |
644 | 675 |
645 values[0] = short_item; | 676 values[0] = short_item; |
646 combobox.ModelChanged(); | 677 combobox.ModelChanged(); |
647 | 678 |
648 const int short_item_width = combobox.content_size_.width(); | 679 const int short_item_width = test_api.content_size().width(); |
649 | 680 |
650 values.resize(2); | 681 values.resize(2); |
651 values[0] = short_item; | 682 values[0] = short_item; |
652 values[1] = long_item; | 683 values[1] = long_item; |
653 combobox.ModelChanged(); | 684 combobox.ModelChanged(); |
654 | 685 |
655 // When the style is STYLE_NORMAL, the width will fit with the longest item. | 686 // When the style is STYLE_NORMAL, the width will fit with the longest item. |
656 combobox.SetStyle(Combobox::STYLE_NORMAL); | 687 combobox.SetStyle(Combobox::STYLE_NORMAL); |
657 EXPECT_EQ(long_item_width, combobox.content_size_.width()); | 688 EXPECT_EQ(long_item_width, test_api.content_size().width()); |
658 | 689 |
659 // When the style is STYLE_ACTION, the width will fit with the first items' | 690 // When the style is STYLE_ACTION, the width will fit with the selected item's |
660 // width. | 691 // width. |
661 combobox.SetStyle(Combobox::STYLE_ACTION); | 692 combobox.SetStyle(Combobox::STYLE_ACTION); |
662 EXPECT_EQ(short_item_width, combobox.content_size_.width()); | 693 EXPECT_EQ(short_item_width, test_api.content_size().width()); |
| 694 } |
| 695 |
| 696 // Test that model updates preserve the selected index, so long as it is in |
| 697 // range. |
| 698 TEST_F(ComboboxTest, ModelChanged) { |
| 699 InitCombobox(nullptr); |
| 700 |
| 701 EXPECT_EQ(0, combobox_->GetSelectedRow()); |
| 702 EXPECT_EQ(10, combobox_->GetRowCount()); |
| 703 |
| 704 combobox_->SetSelectedIndex(4); |
| 705 EXPECT_EQ(4, combobox_->GetSelectedRow()); |
| 706 |
| 707 model_->set_item_count(5); |
| 708 combobox_->ModelChanged(); |
| 709 EXPECT_EQ(5, combobox_->GetRowCount()); |
| 710 EXPECT_EQ(4, combobox_->GetSelectedRow()); // Unchanged. |
| 711 |
| 712 model_->set_item_count(4); |
| 713 combobox_->ModelChanged(); |
| 714 EXPECT_EQ(4, combobox_->GetRowCount()); |
| 715 EXPECT_EQ(0, combobox_->GetSelectedRow()); // Resets. |
| 716 |
| 717 // Restore a non-zero selection. |
| 718 combobox_->SetSelectedIndex(2); |
| 719 EXPECT_EQ(2, combobox_->GetSelectedRow()); |
| 720 |
| 721 // Make the selected index a separator. |
| 722 std::set<int> separators; |
| 723 separators.insert(2); |
| 724 model_->SetSeparators(separators); |
| 725 combobox_->ModelChanged(); |
| 726 EXPECT_EQ(4, combobox_->GetRowCount()); |
| 727 EXPECT_EQ(0, combobox_->GetSelectedRow()); // Resets. |
| 728 |
| 729 // Restore a non-zero selection. |
| 730 combobox_->SetSelectedIndex(1); |
| 731 EXPECT_EQ(1, combobox_->GetSelectedRow()); |
| 732 |
| 733 // Test an empty model. |
| 734 model_->set_item_count(0); |
| 735 combobox_->ModelChanged(); |
| 736 EXPECT_EQ(0, combobox_->GetRowCount()); |
| 737 EXPECT_EQ(0, combobox_->GetSelectedRow()); // Resets. |
663 } | 738 } |
664 | 739 |
665 TEST_F(ComboboxTest, TypingPrefixNotifiesListener) { | 740 TEST_F(ComboboxTest, TypingPrefixNotifiesListener) { |
666 InitCombobox(NULL); | 741 InitCombobox(NULL); |
667 | 742 |
668 TestComboboxListener listener; | 743 TestComboboxListener listener; |
669 combobox_->set_listener(&listener); | 744 combobox_->set_listener(&listener); |
670 ui::TextInputClient* input_client = | 745 ui::TextInputClient* input_client = |
671 widget_->GetInputMethod()->GetTextInputClient(); | 746 widget_->GetInputMethod()->GetTextInputClient(); |
672 | 747 |
(...skipping 12 matching lines...) Expand all Loading... |
685 combobox_->OnBlur(); | 760 combobox_->OnBlur(); |
686 combobox_->RequestFocus(); | 761 combobox_->RequestFocus(); |
687 | 762 |
688 // Type the first character of "PEANUT BUTTER", which should change the | 763 // Type the first character of "PEANUT BUTTER", which should change the |
689 // selected index and perform an action. | 764 // selected index and perform an action. |
690 input_client->InsertChar('P', ui::EF_NONE); | 765 input_client->InsertChar('P', ui::EF_NONE); |
691 EXPECT_EQ(2, listener.actions_performed()); | 766 EXPECT_EQ(2, listener.actions_performed()); |
692 EXPECT_EQ(2, listener.perform_action_index()); | 767 EXPECT_EQ(2, listener.perform_action_index()); |
693 } | 768 } |
694 | 769 |
| 770 // Test properties on the Combobox menu model. |
| 771 TEST_F(ComboboxTest, MenuModel) { |
| 772 const int kSeparatorIndex = 3; |
| 773 std::set<int> separators; |
| 774 separators.insert(kSeparatorIndex); |
| 775 InitCombobox(&separators); |
| 776 |
| 777 ui::MenuModel* menu_model = test_api_->menu_model(); |
| 778 |
| 779 EXPECT_EQ(TestComboboxModel::kItemCount, menu_model->GetItemCount()); |
| 780 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, |
| 781 menu_model->GetTypeAt(kSeparatorIndex)); |
| 782 |
| 783 #if defined(OS_MACOSX) |
| 784 // Comboboxes on Mac should have checkmarks, with the selected item checked, |
| 785 EXPECT_EQ(ui::MenuModel::TYPE_CHECK, menu_model->GetTypeAt(0)); |
| 786 EXPECT_EQ(ui::MenuModel::TYPE_CHECK, menu_model->GetTypeAt(1)); |
| 787 EXPECT_TRUE(menu_model->IsItemCheckedAt(0)); |
| 788 EXPECT_FALSE(menu_model->IsItemCheckedAt(1)); |
| 789 |
| 790 combobox_->SetSelectedIndex(1); |
| 791 EXPECT_FALSE(menu_model->IsItemCheckedAt(0)); |
| 792 EXPECT_TRUE(menu_model->IsItemCheckedAt(1)); |
| 793 #else |
| 794 EXPECT_EQ(ui::MenuModel::TYPE_COMMAND, menu_model->GetTypeAt(0)); |
| 795 EXPECT_EQ(ui::MenuModel::TYPE_COMMAND, menu_model->GetTypeAt(1)); |
| 796 #endif |
| 797 |
| 798 EXPECT_EQ(ASCIIToUTF16("PEANUT BUTTER"), menu_model->GetLabelAt(0)); |
| 799 EXPECT_EQ(ASCIIToUTF16("JELLY"), menu_model->GetLabelAt(1)); |
| 800 |
| 801 // Check that with STYLE_ACTION, the first item (only) is not shown. |
| 802 EXPECT_TRUE(menu_model->IsVisibleAt(0)); |
| 803 combobox_->SetStyle(Combobox::STYLE_ACTION); |
| 804 EXPECT_FALSE(menu_model->IsVisibleAt(0)); |
| 805 EXPECT_TRUE(menu_model->IsVisibleAt(1)); |
| 806 } |
| 807 |
695 } // namespace views | 808 } // namespace views |
OLD | NEW |