| 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 |