| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ui/views/controls/button/menu_button.h" | |
| 6 | |
| 7 #include "base/memory/scoped_ptr.h" | |
| 8 #include "base/strings/utf_string_conversions.h" | |
| 9 #include "ui/events/test/event_generator.h" | |
| 10 #include "ui/views/controls/button/menu_button_listener.h" | |
| 11 #include "ui/views/test/views_test_base.h" | |
| 12 | |
| 13 using base::ASCIIToUTF16; | |
| 14 | |
| 15 namespace views { | |
| 16 | |
| 17 class MenuButtonTest : public ViewsTestBase { | |
| 18 public: | |
| 19 MenuButtonTest() : widget_(NULL), button_(NULL) {} | |
| 20 virtual ~MenuButtonTest() {} | |
| 21 | |
| 22 virtual void TearDown() override { | |
| 23 if (widget_ && !widget_->IsClosed()) | |
| 24 widget_->Close(); | |
| 25 | |
| 26 ViewsTestBase::TearDown(); | |
| 27 } | |
| 28 | |
| 29 Widget* widget() { return widget_; } | |
| 30 MenuButton* button() { return button_; } | |
| 31 | |
| 32 protected: | |
| 33 // Creates a MenuButton with no button listener. | |
| 34 void CreateMenuButtonWithNoListener() { | |
| 35 CreateMenuButton(NULL, NULL); | |
| 36 } | |
| 37 | |
| 38 // Creates a MenuButton with a ButtonListener. In this case, the MenuButton | |
| 39 // acts like a regular button. | |
| 40 void CreateMenuButtonWithButtonListener(ButtonListener* button_listener) { | |
| 41 CreateMenuButton(button_listener, NULL); | |
| 42 } | |
| 43 | |
| 44 // Creates a MenuButton with a MenuButtonListener. In this case, when the | |
| 45 // MenuButton is pushed, it notifies the MenuButtonListener to open a | |
| 46 // drop-down menu. | |
| 47 void CreateMenuButtonWithMenuButtonListener( | |
| 48 MenuButtonListener* menu_button_listener) { | |
| 49 CreateMenuButton(NULL, menu_button_listener); | |
| 50 } | |
| 51 | |
| 52 private: | |
| 53 void CreateMenuButton(ButtonListener* button_listener, | |
| 54 MenuButtonListener* menu_button_listener) { | |
| 55 CreateWidget(); | |
| 56 | |
| 57 const base::string16 label(ASCIIToUTF16("button")); | |
| 58 button_ = | |
| 59 new MenuButton(button_listener, label, menu_button_listener, false); | |
| 60 button_->SetBoundsRect(gfx::Rect(0, 0, 200, 20)); | |
| 61 widget_->SetContentsView(button_); | |
| 62 | |
| 63 widget_->Show(); | |
| 64 } | |
| 65 | |
| 66 void CreateWidget() { | |
| 67 DCHECK(!widget_); | |
| 68 | |
| 69 widget_ = new Widget; | |
| 70 Widget::InitParams params = | |
| 71 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); | |
| 72 params.bounds = gfx::Rect(0, 0, 200, 200); | |
| 73 widget_->Init(params); | |
| 74 } | |
| 75 | |
| 76 Widget* widget_; | |
| 77 MenuButton* button_; | |
| 78 }; | |
| 79 | |
| 80 class TestButtonListener : public ButtonListener { | |
| 81 public: | |
| 82 TestButtonListener() | |
| 83 : last_sender_(NULL), | |
| 84 last_sender_state_(Button::STATE_NORMAL), | |
| 85 last_event_type_(ui::ET_UNKNOWN) {} | |
| 86 virtual ~TestButtonListener() {} | |
| 87 | |
| 88 virtual void ButtonPressed(Button* sender, const ui::Event& event) override { | |
| 89 last_sender_ = sender; | |
| 90 CustomButton* custom_button = CustomButton::AsCustomButton(sender); | |
| 91 DCHECK(custom_button); | |
| 92 last_sender_state_ = custom_button->state(); | |
| 93 last_event_type_ = event.type(); | |
| 94 } | |
| 95 | |
| 96 Button* last_sender() { return last_sender_; } | |
| 97 Button::ButtonState last_sender_state() { return last_sender_state_; } | |
| 98 ui::EventType last_event_type() { return last_event_type_; } | |
| 99 | |
| 100 private: | |
| 101 Button* last_sender_; | |
| 102 Button::ButtonState last_sender_state_; | |
| 103 ui::EventType last_event_type_; | |
| 104 | |
| 105 DISALLOW_COPY_AND_ASSIGN(TestButtonListener); | |
| 106 }; | |
| 107 | |
| 108 class TestMenuButtonListener : public MenuButtonListener { | |
| 109 public: | |
| 110 TestMenuButtonListener() {} | |
| 111 virtual ~TestMenuButtonListener() {} | |
| 112 | |
| 113 virtual void OnMenuButtonClicked(View* source, | |
| 114 const gfx::Point& /*point*/) override { | |
| 115 last_source_ = source; | |
| 116 CustomButton* custom_button = CustomButton::AsCustomButton(source); | |
| 117 DCHECK(custom_button); | |
| 118 last_source_state_ = custom_button->state(); | |
| 119 } | |
| 120 | |
| 121 View* last_source() { return last_source_; } | |
| 122 Button::ButtonState last_source_state() { return last_source_state_; } | |
| 123 | |
| 124 private: | |
| 125 View* last_source_; | |
| 126 Button::ButtonState last_source_state_; | |
| 127 }; | |
| 128 | |
| 129 // Tests if the listener is notified correctly, when a mouse click happens on a | |
| 130 // MenuButton that has a regular ButtonListener. | |
| 131 TEST_F(MenuButtonTest, ActivateNonDropDownOnMouseClick) { | |
| 132 scoped_ptr<TestButtonListener> button_listener(new TestButtonListener); | |
| 133 CreateMenuButtonWithButtonListener(button_listener.get()); | |
| 134 | |
| 135 ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow()); | |
| 136 | |
| 137 generator.set_current_location(gfx::Point(10, 10)); | |
| 138 generator.ClickLeftButton(); | |
| 139 | |
| 140 // Check that MenuButton has notified the listener on mouse-released event, | |
| 141 // while it was in hovered state. | |
| 142 EXPECT_EQ(button(), button_listener->last_sender()); | |
| 143 EXPECT_EQ(ui::ET_MOUSE_RELEASED, button_listener->last_event_type()); | |
| 144 EXPECT_EQ(Button::STATE_HOVERED, button_listener->last_sender_state()); | |
| 145 } | |
| 146 | |
| 147 // Tests if the listener is notified correctly when a gesture tap happens on a | |
| 148 // MenuButton that has a regular ButtonListener. | |
| 149 TEST_F(MenuButtonTest, ActivateNonDropDownOnGestureTap) { | |
| 150 scoped_ptr<TestButtonListener> button_listener(new TestButtonListener); | |
| 151 CreateMenuButtonWithButtonListener(button_listener.get()); | |
| 152 | |
| 153 ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow()); | |
| 154 generator.GestureTapAt(gfx::Point(10, 10)); | |
| 155 | |
| 156 // Check that MenuButton has notified the listener on gesture tap event, while | |
| 157 // it was in hovered state. | |
| 158 EXPECT_EQ(button(), button_listener->last_sender()); | |
| 159 EXPECT_EQ(ui::ET_GESTURE_TAP, button_listener->last_event_type()); | |
| 160 EXPECT_EQ(Button::STATE_HOVERED, button_listener->last_sender_state()); | |
| 161 } | |
| 162 | |
| 163 // Tests if the listener is notified correctly when a mouse click happens on a | |
| 164 // MenuButton that has a MenuButtonListener. | |
| 165 TEST_F(MenuButtonTest, ActivateDropDownOnMouseClick) { | |
| 166 scoped_ptr<TestMenuButtonListener> menu_button_listener( | |
| 167 new TestMenuButtonListener); | |
| 168 CreateMenuButtonWithMenuButtonListener(menu_button_listener.get()); | |
| 169 | |
| 170 ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow()); | |
| 171 | |
| 172 generator.set_current_location(gfx::Point(10, 10)); | |
| 173 generator.ClickLeftButton(); | |
| 174 | |
| 175 // Check that MenuButton has notified the listener, while it was in pressed | |
| 176 // state. | |
| 177 EXPECT_EQ(button(), menu_button_listener->last_source()); | |
| 178 EXPECT_EQ(Button::STATE_PRESSED, menu_button_listener->last_source_state()); | |
| 179 } | |
| 180 | |
| 181 // Tests if the listener is notified correctly when a gesture tap happens on a | |
| 182 // MenuButton that has a MenuButtonListener. | |
| 183 TEST_F(MenuButtonTest, ActivateDropDownOnGestureTap) { | |
| 184 scoped_ptr<TestMenuButtonListener> menu_button_listener( | |
| 185 new TestMenuButtonListener); | |
| 186 CreateMenuButtonWithMenuButtonListener(menu_button_listener.get()); | |
| 187 | |
| 188 ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow()); | |
| 189 generator.GestureTapAt(gfx::Point(10, 10)); | |
| 190 | |
| 191 // Check that MenuButton has notified the listener, while it was in pressed | |
| 192 // state. | |
| 193 EXPECT_EQ(button(), menu_button_listener->last_source()); | |
| 194 EXPECT_EQ(Button::STATE_PRESSED, menu_button_listener->last_source_state()); | |
| 195 } | |
| 196 | |
| 197 // Test that the MenuButton stays pressed while there are any PressedLocks. | |
| 198 TEST_F(MenuButtonTest, MenuButtonPressedLock) { | |
| 199 CreateMenuButtonWithNoListener(); | |
| 200 | |
| 201 // Move the mouse over the button; the button should be in a hovered state. | |
| 202 ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow()); | |
| 203 generator.MoveMouseTo(gfx::Point(10, 10)); | |
| 204 EXPECT_EQ(Button::STATE_HOVERED, button()->state()); | |
| 205 | |
| 206 // Introduce a PressedLock, which should make the button pressed. | |
| 207 scoped_ptr<MenuButton::PressedLock> pressed_lock1( | |
| 208 new MenuButton::PressedLock(button())); | |
| 209 EXPECT_EQ(Button::STATE_PRESSED, button()->state()); | |
| 210 | |
| 211 // Even if we move the mouse outside of the button, it should remain pressed. | |
| 212 generator.MoveMouseTo(gfx::Point(300, 10)); | |
| 213 EXPECT_EQ(Button::STATE_PRESSED, button()->state()); | |
| 214 | |
| 215 // Creating a new lock should obviously keep the button pressed. | |
| 216 scoped_ptr<MenuButton::PressedLock> pressed_lock2( | |
| 217 new MenuButton::PressedLock(button())); | |
| 218 EXPECT_EQ(Button::STATE_PRESSED, button()->state()); | |
| 219 | |
| 220 // The button should remain pressed while any locks are active. | |
| 221 pressed_lock1.reset(); | |
| 222 EXPECT_EQ(Button::STATE_PRESSED, button()->state()); | |
| 223 | |
| 224 // Reseting the final lock should return the button's state to normal... | |
| 225 pressed_lock2.reset(); | |
| 226 EXPECT_EQ(Button::STATE_NORMAL, button()->state()); | |
| 227 | |
| 228 // ...And it should respond to mouse movement again. | |
| 229 generator.MoveMouseTo(gfx::Point(10, 10)); | |
| 230 EXPECT_EQ(Button::STATE_HOVERED, button()->state()); | |
| 231 } | |
| 232 | |
| 233 } // namespace views | |
| OLD | NEW |