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.
5 #include "ui/views/controls/button/label_button.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "third_party/skia/include/core/SkBitmap.h"
9 #include "ui/accessibility/ax_view_state.h"
10 #include "ui/gfx/canvas.h"
11 #include "ui/gfx/font_list.h"
12 #include "ui/gfx/geometry/size.h"
13 #include "ui/gfx/text_utils.h"
14 #include "ui/views/test/widget_test.h"
16 using base::ASCIIToUTF16
;
20 gfx::ImageSkia
CreateTestImage(int width
, int height
) {
22 bitmap
.allocN32Pixels(width
, height
);
23 return gfx::ImageSkia::CreateFrom1xBitmap(bitmap
);
30 class LabelButtonTest
: public test::WidgetTest
{
35 void SetUp() override
{
37 // Make a Widget to host the button. This ensures appropriate borders are
38 // used (which could be derived from the Widget's NativeTheme).
39 test_widget_
= CreateTopLevelPlatformWidget();
41 button_
= new LabelButton(nullptr, base::string16());
42 test_widget_
->GetContentsView()->AddChildView(button_
);
45 void TearDown() override
{
46 test_widget_
->CloseNow();
47 WidgetTest::TearDown();
51 LabelButton
* button_
= nullptr;
54 Widget
* test_widget_
= nullptr;
56 DISALLOW_COPY_AND_ASSIGN(LabelButtonTest
);
59 TEST_F(LabelButtonTest
, Init
) {
60 const base::string16
text(ASCIIToUTF16("abc"));
61 LabelButton
button(NULL
, text
);
63 EXPECT_TRUE(button
.GetImage(Button::STATE_NORMAL
).isNull());
64 EXPECT_TRUE(button
.GetImage(Button::STATE_HOVERED
).isNull());
65 EXPECT_TRUE(button
.GetImage(Button::STATE_PRESSED
).isNull());
66 EXPECT_TRUE(button
.GetImage(Button::STATE_DISABLED
).isNull());
68 EXPECT_EQ(text
, button
.GetText());
70 ui::AXViewState accessible_state
;
71 button
.GetAccessibleState(&accessible_state
);
72 EXPECT_EQ(ui::AX_ROLE_BUTTON
, accessible_state
.role
);
73 EXPECT_EQ(text
, accessible_state
.name
);
75 EXPECT_EQ(gfx::ALIGN_LEFT
, button
.GetHorizontalAlignment());
76 EXPECT_FALSE(button
.is_default());
77 EXPECT_EQ(button
.style(), Button::STYLE_TEXTBUTTON
);
78 EXPECT_EQ(Button::STATE_NORMAL
, button
.state());
80 EXPECT_EQ(button
.image_
->parent(), &button
);
81 EXPECT_EQ(button
.label_
->parent(), &button
);
84 TEST_F(LabelButtonTest
, Label
) {
85 EXPECT_TRUE(button_
->GetText().empty());
87 const gfx::FontList font_list
;
88 const base::string16
short_text(ASCIIToUTF16("abcdefghijklm"));
89 const base::string16
long_text(ASCIIToUTF16("abcdefghijklmnopqrstuvwxyz"));
90 const int short_text_width
= gfx::GetStringWidth(short_text
, font_list
);
91 const int long_text_width
= gfx::GetStringWidth(long_text
, font_list
);
93 // The width increases monotonically with string size (it does not shrink).
94 EXPECT_LT(button_
->GetPreferredSize().width(), short_text_width
);
95 button_
->SetText(short_text
);
96 EXPECT_GT(button_
->GetPreferredSize().height(), font_list
.GetHeight());
97 EXPECT_GT(button_
->GetPreferredSize().width(), short_text_width
);
98 EXPECT_LT(button_
->GetPreferredSize().width(), long_text_width
);
99 button_
->SetText(long_text
);
100 EXPECT_GT(button_
->GetPreferredSize().width(), long_text_width
);
101 button_
->SetText(short_text
);
102 EXPECT_GT(button_
->GetPreferredSize().width(), long_text_width
);
104 // Clamp the size to a maximum value.
105 button_
->SetMaxSize(gfx::Size(long_text_width
, 1));
106 EXPECT_EQ(button_
->GetPreferredSize(), gfx::Size(long_text_width
, 1));
108 // Clear the monotonically increasing minimum size.
109 button_
->SetMinSize(gfx::Size());
110 EXPECT_GT(button_
->GetPreferredSize().width(), short_text_width
);
111 EXPECT_LT(button_
->GetPreferredSize().width(), long_text_width
);
114 // Test behavior of View::GetAccessibleState() for buttons when setting a label.
115 TEST_F(LabelButtonTest
, AccessibleState
) {
116 ui::AXViewState accessible_state
;
118 button_
->GetAccessibleState(&accessible_state
);
119 EXPECT_EQ(ui::AX_ROLE_BUTTON
, accessible_state
.role
);
120 EXPECT_EQ(base::string16(), accessible_state
.name
);
122 // Without a label (e.g. image-only), the accessible name should automatically
123 // be set from the tooltip.
124 const base::string16 tooltip_text
= ASCIIToUTF16("abc");
125 button_
->SetTooltipText(tooltip_text
);
126 button_
->GetAccessibleState(&accessible_state
);
127 EXPECT_EQ(tooltip_text
, accessible_state
.name
);
128 EXPECT_EQ(base::string16(), button_
->GetText());
130 // Setting a label overrides the tooltip text.
131 const base::string16 label_text
= ASCIIToUTF16("def");
132 button_
->SetText(label_text
);
133 button_
->GetAccessibleState(&accessible_state
);
134 EXPECT_EQ(label_text
, accessible_state
.name
);
135 EXPECT_EQ(label_text
, button_
->GetText());
137 base::string16 tooltip
;
138 EXPECT_TRUE(button_
->GetTooltipText(gfx::Point(), &tooltip
));
139 EXPECT_EQ(tooltip_text
, tooltip
);
142 TEST_F(LabelButtonTest
, Image
) {
143 const int small_size
= 50, large_size
= 100;
144 const gfx::ImageSkia small_image
= CreateTestImage(small_size
, small_size
);
145 const gfx::ImageSkia large_image
= CreateTestImage(large_size
, large_size
);
147 // The width increases monotonically with image size (it does not shrink).
148 EXPECT_LT(button_
->GetPreferredSize().width(), small_size
);
149 EXPECT_LT(button_
->GetPreferredSize().height(), small_size
);
150 button_
->SetImage(Button::STATE_NORMAL
, small_image
);
151 EXPECT_GT(button_
->GetPreferredSize().width(), small_size
);
152 EXPECT_GT(button_
->GetPreferredSize().height(), small_size
);
153 EXPECT_LT(button_
->GetPreferredSize().width(), large_size
);
154 EXPECT_LT(button_
->GetPreferredSize().height(), large_size
);
155 button_
->SetImage(Button::STATE_NORMAL
, large_image
);
156 EXPECT_GT(button_
->GetPreferredSize().width(), large_size
);
157 EXPECT_GT(button_
->GetPreferredSize().height(), large_size
);
158 button_
->SetImage(Button::STATE_NORMAL
, small_image
);
159 EXPECT_GT(button_
->GetPreferredSize().width(), large_size
);
160 EXPECT_GT(button_
->GetPreferredSize().height(), large_size
);
162 // Clamp the size to a maximum value.
163 button_
->SetMaxSize(gfx::Size(large_size
, 1));
164 EXPECT_EQ(button_
->GetPreferredSize(), gfx::Size(large_size
, 1));
166 // Clear the monotonically increasing minimum size.
167 button_
->SetMinSize(gfx::Size());
168 EXPECT_GT(button_
->GetPreferredSize().width(), small_size
);
169 EXPECT_LT(button_
->GetPreferredSize().width(), large_size
);
172 TEST_F(LabelButtonTest
, LabelAndImage
) {
173 const gfx::FontList font_list
;
174 const base::string16
text(ASCIIToUTF16("abcdefghijklm"));
175 const int text_width
= gfx::GetStringWidth(text
, font_list
);
177 const int image_size
= 50;
178 const gfx::ImageSkia image
= CreateTestImage(image_size
, image_size
);
179 ASSERT_LT(font_list
.GetHeight(), image_size
);
181 // The width increases monotonically with content size (it does not shrink).
182 EXPECT_LT(button_
->GetPreferredSize().width(), text_width
);
183 EXPECT_LT(button_
->GetPreferredSize().width(), image_size
);
184 EXPECT_LT(button_
->GetPreferredSize().height(), image_size
);
185 button_
->SetText(text
);
186 EXPECT_GT(button_
->GetPreferredSize().width(), text_width
);
187 EXPECT_GT(button_
->GetPreferredSize().height(), font_list
.GetHeight());
188 EXPECT_LT(button_
->GetPreferredSize().width(), text_width
+ image_size
);
189 EXPECT_LT(button_
->GetPreferredSize().height(), image_size
);
190 button_
->SetImage(Button::STATE_NORMAL
, image
);
191 EXPECT_GT(button_
->GetPreferredSize().width(), text_width
+ image_size
);
192 EXPECT_GT(button_
->GetPreferredSize().height(), image_size
);
194 // Layout and ensure the image is left of the label except for ALIGN_RIGHT.
195 // (A proper parent view or layout manager would Layout on its invalidations).
196 button_
->SetSize(button_
->GetPreferredSize());
198 EXPECT_EQ(gfx::ALIGN_LEFT
, button_
->GetHorizontalAlignment());
199 EXPECT_LT(button_
->image_
->bounds().right(), button_
->label_
->bounds().x());
200 button_
->SetHorizontalAlignment(gfx::ALIGN_CENTER
);
202 EXPECT_EQ(gfx::ALIGN_CENTER
, button_
->GetHorizontalAlignment());
203 EXPECT_LT(button_
->image_
->bounds().right(), button_
->label_
->bounds().x());
204 button_
->SetHorizontalAlignment(gfx::ALIGN_RIGHT
);
206 EXPECT_EQ(gfx::ALIGN_RIGHT
, button_
->GetHorizontalAlignment());
207 EXPECT_LT(button_
->label_
->bounds().right(), button_
->image_
->bounds().x());
209 button_
->SetText(base::string16());
210 EXPECT_GT(button_
->GetPreferredSize().width(), text_width
+ image_size
);
211 EXPECT_GT(button_
->GetPreferredSize().height(), image_size
);
212 button_
->SetImage(Button::STATE_NORMAL
, gfx::ImageSkia());
213 EXPECT_GT(button_
->GetPreferredSize().width(), text_width
+ image_size
);
214 EXPECT_GT(button_
->GetPreferredSize().height(), image_size
);
216 // Clamp the size to a maximum value.
217 button_
->SetMaxSize(gfx::Size(image_size
, 1));
218 EXPECT_EQ(button_
->GetPreferredSize(), gfx::Size(image_size
, 1));
220 // Clear the monotonically increasing minimum size.
221 button_
->SetMinSize(gfx::Size());
222 EXPECT_LT(button_
->GetPreferredSize().width(), text_width
);
223 EXPECT_LT(button_
->GetPreferredSize().width(), image_size
);
224 EXPECT_LT(button_
->GetPreferredSize().height(), image_size
);
227 TEST_F(LabelButtonTest
, FontList
) {
228 button_
->SetText(base::ASCIIToUTF16("abc"));
230 const gfx::FontList original_font_list
= button_
->GetFontList();
231 const gfx::FontList large_font_list
=
232 original_font_list
.DeriveWithSizeDelta(100);
233 const int original_width
= button_
->GetPreferredSize().width();
234 const int original_height
= button_
->GetPreferredSize().height();
236 // The button size increases when the font size is increased.
237 button_
->SetFontList(large_font_list
);
238 EXPECT_GT(button_
->GetPreferredSize().width(), original_width
);
239 EXPECT_GT(button_
->GetPreferredSize().height(), original_height
);
241 // The button returns to its original size when the minimal size is cleared
242 // and the original font size is restored.
243 button_
->SetMinSize(gfx::Size());
244 button_
->SetFontList(original_font_list
);
245 EXPECT_EQ(original_width
, button_
->GetPreferredSize().width());
246 EXPECT_EQ(original_height
, button_
->GetPreferredSize().height());
249 TEST_F(LabelButtonTest
, ChangeTextSize
) {
250 const base::string16
text(ASCIIToUTF16("abc"));
251 const base::string16
longer_text(ASCIIToUTF16("abcdefghijklm"));
252 button_
->SetText(text
);
254 const int original_width
= button_
->GetPreferredSize().width();
256 // The button size increases when the text size is increased.
257 button_
->SetText(longer_text
);
258 EXPECT_GT(button_
->GetPreferredSize().width(), original_width
);
260 // The button returns to its original size when the original text is restored.
261 button_
->SetMinSize(gfx::Size());
262 button_
->SetText(text
);
263 EXPECT_EQ(original_width
, button_
->GetPreferredSize().width());
266 TEST_F(LabelButtonTest
, ChangeLabelImageSpacing
) {
267 button_
->SetText(ASCIIToUTF16("abc"));
268 button_
->SetImage(Button::STATE_NORMAL
, CreateTestImage(50, 50));
270 const int kOriginalSpacing
= 5;
271 button_
->SetImageLabelSpacing(kOriginalSpacing
);
272 const int original_width
= button_
->GetPreferredSize().width();
274 // Increasing the spacing between the text and label should increase the size.
275 button_
->SetImageLabelSpacing(2 * kOriginalSpacing
);
276 EXPECT_GT(button_
->GetPreferredSize().width(), original_width
);
278 // The button shrinks if the original spacing is restored.
279 button_
->SetMinSize(gfx::Size());
280 button_
->SetImageLabelSpacing(kOriginalSpacing
);
281 EXPECT_EQ(original_width
, button_
->GetPreferredSize().width());