1// Copyright (c) 2012 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/custom_button.h"
6
7#include "testing/gtest/include/gtest/gtest.h"
8#include "ui/aura/test/test_cursor_client.h"
9#include "ui/aura/window.h"
10#include "ui/aura/window_event_dispatcher.h"
11#include "ui/base/layout.h"
12#include "ui/gfx/screen.h"
13#include "ui/views/controls/button/checkbox.h"
14#include "ui/views/controls/button/image_button.h"
15#include "ui/views/controls/button/label_button.h"
16#include "ui/views/controls/button/menu_button.h"
17#include "ui/views/controls/button/radio_button.h"
18#include "ui/views/controls/link.h"
19#include "ui/views/controls/textfield/textfield.h"
20#include "ui/views/test/views_test_base.h"
21
22namespace views {
23
24namespace {
25
26class TestCustomButton : public CustomButton {
27 public:
28  explicit TestCustomButton(ButtonListener* listener)
29      : CustomButton(listener) {
30  }
31
32  virtual ~TestCustomButton() {}
33
34 private:
35  DISALLOW_COPY_AND_ASSIGN(TestCustomButton);
36};
37
38void PerformGesture(CustomButton* button, ui::EventType event_type) {
39  ui::GestureEventDetails gesture_details(event_type);
40  base::TimeDelta time_stamp = base::TimeDelta::FromMicroseconds(0);
41  ui::GestureEvent gesture_event(0, 0, 0, time_stamp, gesture_details);
42  button->OnGestureEvent(&gesture_event);
43}
44
45}  // namespace
46
47typedef ViewsTestBase CustomButtonTest;
48
49// Tests that hover state changes correctly when visiblity/enableness changes.
50TEST_F(CustomButtonTest, HoverStateOnVisibilityChange) {
51  // Create a widget so that the CustomButton can query the hover state
52  // correctly.
53  scoped_ptr<Widget> widget(new Widget);
54  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
55  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
56  params.bounds = gfx::Rect(0, 0, 650, 650);
57  widget->Init(params);
58  widget->Show();
59
60  aura::test::TestCursorClient cursor_client(
61      widget->GetNativeView()->GetRootWindow());
62
63  // Position the widget in a way so that it is under the cursor.
64  gfx::Point cursor = gfx::Screen::GetScreenFor(
65      widget->GetNativeView())->GetCursorScreenPoint();
66  gfx::Rect widget_bounds = widget->GetWindowBoundsInScreen();
67  widget_bounds.set_origin(cursor);
68  widget->SetBounds(widget_bounds);
69
70  TestCustomButton* button = new TestCustomButton(NULL);
71  widget->SetContentsView(button);
72
73  gfx::Point center(10, 10);
74  button->OnMousePressed(ui::MouseEvent(ui::ET_MOUSE_PRESSED, center, center,
75                                        ui::EF_LEFT_MOUSE_BUTTON,
76                                        ui::EF_LEFT_MOUSE_BUTTON));
77  EXPECT_EQ(CustomButton::STATE_PRESSED, button->state());
78
79  button->OnMouseReleased(ui::MouseEvent(ui::ET_MOUSE_RELEASED, center, center,
80                                         ui::EF_LEFT_MOUSE_BUTTON,
81                                         ui::EF_LEFT_MOUSE_BUTTON));
82  EXPECT_EQ(CustomButton::STATE_HOVERED, button->state());
83
84  button->SetEnabled(false);
85  EXPECT_EQ(CustomButton::STATE_DISABLED, button->state());
86
87  button->SetEnabled(true);
88  EXPECT_EQ(CustomButton::STATE_HOVERED, button->state());
89
90  button->SetVisible(false);
91  EXPECT_EQ(CustomButton::STATE_NORMAL, button->state());
92
93  button->SetVisible(true);
94  EXPECT_EQ(CustomButton::STATE_HOVERED, button->state());
95
96  // In Aura views, no new hover effects are invoked if mouse events
97  // are disabled.
98  cursor_client.DisableMouseEvents();
99
100  button->SetEnabled(false);
101  EXPECT_EQ(CustomButton::STATE_DISABLED, button->state());
102
103  button->SetEnabled(true);
104  EXPECT_EQ(CustomButton::STATE_NORMAL, button->state());
105
106  button->SetVisible(false);
107  EXPECT_EQ(CustomButton::STATE_NORMAL, button->state());
108
109  button->SetVisible(true);
110  EXPECT_EQ(CustomButton::STATE_NORMAL, button->state());
111}
112
113// Tests that gesture events correctly change the button state.
114TEST_F(CustomButtonTest, GestureEventsSetState) {
115  // Create a widget so that the CustomButton can query the hover state
116  // correctly.
117  scoped_ptr<Widget> widget(new Widget);
118  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
119  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
120  params.bounds = gfx::Rect(0, 0, 650, 650);
121  widget->Init(params);
122  widget->Show();
123
124  aura::test::TestCursorClient cursor_client(
125      widget->GetNativeView()->GetRootWindow());
126
127  TestCustomButton* button = new TestCustomButton(NULL);
128  widget->SetContentsView(button);
129
130  EXPECT_EQ(CustomButton::STATE_NORMAL, button->state());
131
132  PerformGesture(button, ui::ET_GESTURE_TAP_DOWN);
133  EXPECT_EQ(CustomButton::STATE_PRESSED, button->state());
134
135  PerformGesture(button, ui::ET_GESTURE_SHOW_PRESS);
136  EXPECT_EQ(CustomButton::STATE_PRESSED, button->state());
137
138  PerformGesture(button, ui::ET_GESTURE_TAP_CANCEL);
139  EXPECT_EQ(CustomButton::STATE_NORMAL, button->state());
140}
141
142// Ensure subclasses of CustomButton are correctly recognized as CustomButton.
143TEST_F(CustomButtonTest, AsCustomButton) {
144  base::string16 text;
145
146  LabelButton label_button(NULL, text);
147  EXPECT_TRUE(CustomButton::AsCustomButton(&label_button));
148
149  ImageButton image_button(NULL);
150  EXPECT_TRUE(CustomButton::AsCustomButton(&image_button));
151
152  Checkbox checkbox(text);
153  EXPECT_TRUE(CustomButton::AsCustomButton(&checkbox));
154
155  RadioButton radio_button(text, 0);
156  EXPECT_TRUE(CustomButton::AsCustomButton(&radio_button));
157
158  MenuButton menu_button(NULL, text, NULL, false);
159  EXPECT_TRUE(CustomButton::AsCustomButton(&menu_button));
160
161  Label label;
162  EXPECT_FALSE(CustomButton::AsCustomButton(&label));
163
164  Link link(text);
165  EXPECT_FALSE(CustomButton::AsCustomButton(&link));
166
167  Textfield textfield;
168  EXPECT_FALSE(CustomButton::AsCustomButton(&textfield));
169}
170
171}  // namespace views
172