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/strings/utf_string_conversions.h"
8 #include "ui/aura/test/event_generator.h"
9 #include "ui/aura/window.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:
MenuButtonTest()19 MenuButtonTest() : widget_(NULL), button_(NULL) {}
~MenuButtonTest()20 virtual ~MenuButtonTest() {}
21
TearDown()22 virtual void TearDown() OVERRIDE {
23 if (widget_ && !widget_->IsClosed())
24 widget_->Close();
25
26 ViewsTestBase::TearDown();
27 }
28
widget()29 Widget* widget() { return widget_; }
button()30 MenuButton* button() { return button_; }
31
32 protected:
33 // Creates a MenuButton with a ButtonListener. In this case, the MenuButton
34 // acts like a regular button.
CreateMenuButtonWithButtonListener(ButtonListener * button_listener)35 void CreateMenuButtonWithButtonListener(ButtonListener* button_listener) {
36 CreateWidget();
37
38 const base::string16 label(ASCIIToUTF16("button"));
39 button_ = new MenuButton(button_listener, label, NULL, false);
40 button_->SetBoundsRect(gfx::Rect(0, 0, 200, 20));
41 widget_->SetContentsView(button_);
42
43 widget_->Show();
44 }
45
46 // Creates a MenuButton with a MenuButtonListener. In this case, when the
47 // MenuButton is pushed, it notifies the MenuButtonListener to open a
48 // drop-down menu.
CreateMenuButtonWithMenuButtonListener(MenuButtonListener * menu_button_listener)49 void CreateMenuButtonWithMenuButtonListener(
50 MenuButtonListener* menu_button_listener) {
51 CreateWidget();
52
53 const base::string16 label(ASCIIToUTF16("button"));
54 button_ = new MenuButton(NULL, label, menu_button_listener, false);
55 button_->SetBoundsRect(gfx::Rect(0, 0, 200, 20));
56 widget_->SetContentsView(button_);
57
58 widget_->Show();
59 }
60
61 private:
CreateWidget()62 void CreateWidget() {
63 DCHECK(!widget_);
64
65 widget_ = new Widget;
66 Widget::InitParams params =
67 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
68 params.bounds = gfx::Rect(0, 0, 200, 200);
69 widget_->Init(params);
70 }
71
72 Widget* widget_;
73 MenuButton* button_;
74 };
75
76 class TestButtonListener : public ButtonListener {
77 public:
TestButtonListener()78 TestButtonListener()
79 : last_sender_(NULL),
80 last_sender_state_(Button::STATE_NORMAL),
81 last_event_type_(ui::ET_UNKNOWN) {}
~TestButtonListener()82 virtual ~TestButtonListener() {}
83
ButtonPressed(Button * sender,const ui::Event & event)84 virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE {
85 last_sender_ = sender;
86 CustomButton* custom_button = CustomButton::AsCustomButton(sender);
87 DCHECK(custom_button);
88 last_sender_state_ = custom_button->state();
89 last_event_type_ = event.type();
90 }
91
last_sender()92 Button* last_sender() { return last_sender_; }
last_sender_state()93 Button::ButtonState last_sender_state() { return last_sender_state_; }
last_event_type()94 ui::EventType last_event_type() { return last_event_type_; }
95
96 private:
97 Button* last_sender_;
98 Button::ButtonState last_sender_state_;
99 ui::EventType last_event_type_;
100
101 DISALLOW_COPY_AND_ASSIGN(TestButtonListener);
102 };
103
104 class TestMenuButtonListener : public MenuButtonListener {
105 public:
TestMenuButtonListener()106 TestMenuButtonListener() {}
~TestMenuButtonListener()107 virtual ~TestMenuButtonListener() {}
108
OnMenuButtonClicked(View * source,const gfx::Point &)109 virtual void OnMenuButtonClicked(View* source,
110 const gfx::Point& /*point*/) OVERRIDE {
111 last_source_ = source;
112 CustomButton* custom_button = CustomButton::AsCustomButton(source);
113 DCHECK(custom_button);
114 last_source_state_ = custom_button->state();
115 }
116
last_source()117 View* last_source() { return last_source_; }
last_source_state()118 Button::ButtonState last_source_state() { return last_source_state_; }
119
120 private:
121 View* last_source_;
122 Button::ButtonState last_source_state_;
123 };
124
125 // Tests if the listener is notified correctly, when a mouse click happens on a
126 // MenuButton that has a regular ButtonListener.
TEST_F(MenuButtonTest,ActivateNonDropDownOnMouseClick)127 TEST_F(MenuButtonTest, ActivateNonDropDownOnMouseClick) {
128 scoped_ptr<TestButtonListener> button_listener(new TestButtonListener);
129 CreateMenuButtonWithButtonListener(button_listener.get());
130
131 aura::test::EventGenerator generator(
132 widget()->GetNativeView()->GetRootWindow());
133
134 generator.set_current_location(gfx::Point(10, 10));
135 generator.ClickLeftButton();
136
137 // Check that MenuButton has notified the listener on mouse-released event,
138 // while it was in hovered state.
139 EXPECT_EQ(button(), button_listener->last_sender());
140 EXPECT_EQ(ui::ET_MOUSE_RELEASED, button_listener->last_event_type());
141 EXPECT_EQ(Button::STATE_HOVERED, button_listener->last_sender_state());
142 }
143
144 // Tests if the listener is notified correctly when a gesture tap happens on a
145 // MenuButton that has a regular ButtonListener.
TEST_F(MenuButtonTest,ActivateNonDropDownOnGestureTap)146 TEST_F(MenuButtonTest, ActivateNonDropDownOnGestureTap) {
147 scoped_ptr<TestButtonListener> button_listener(new TestButtonListener);
148 CreateMenuButtonWithButtonListener(button_listener.get());
149
150 aura::test::EventGenerator generator(
151 widget()->GetNativeView()->GetRootWindow());
152
153 generator.GestureTapAt(gfx::Point(10, 10));
154
155 // Check that MenuButton has notified the listener on gesture tap event, while
156 // it was in hovered state.
157 EXPECT_EQ(button(), button_listener->last_sender());
158 EXPECT_EQ(ui::ET_GESTURE_TAP, button_listener->last_event_type());
159 EXPECT_EQ(Button::STATE_HOVERED, button_listener->last_sender_state());
160 }
161
162 // Tests if the listener is notified correctly when a mouse click happens on a
163 // MenuButton that has a MenuButtonListener.
TEST_F(MenuButtonTest,ActivateDropDownOnMouseClick)164 TEST_F(MenuButtonTest, ActivateDropDownOnMouseClick) {
165 scoped_ptr<TestMenuButtonListener> menu_button_listener(
166 new TestMenuButtonListener);
167 CreateMenuButtonWithMenuButtonListener(menu_button_listener.get());
168
169 aura::test::EventGenerator generator(
170 widget()->GetNativeView()->GetRootWindow());
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.
TEST_F(MenuButtonTest,ActivateDropDownOnGestureTap)183 TEST_F(MenuButtonTest, ActivateDropDownOnGestureTap) {
184 scoped_ptr<TestMenuButtonListener> menu_button_listener(
185 new TestMenuButtonListener);
186 CreateMenuButtonWithMenuButtonListener(menu_button_listener.get());
187
188 aura::test::EventGenerator generator(
189 widget()->GetNativeView()->GetRootWindow());
190
191 generator.GestureTapAt(gfx::Point(10, 10));
192
193 // Check that MenuButton has notified the listener, while it was in pressed
194 // state.
195 EXPECT_EQ(button(), menu_button_listener->last_source());
196 EXPECT_EQ(Button::STATE_PRESSED, menu_button_listener->last_source_state());
197 }
198
199 } // namespace views
200