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/label_button.h"
6
7#include "base/strings/utf_string_conversions.h"
8#include "third_party/skia/include/core/SkBitmap.h"
9#include "ui/gfx/canvas.h"
10#include "ui/gfx/font_list.h"
11#include "ui/gfx/size.h"
12#include "ui/gfx/text_utils.h"
13#include "ui/views/test/views_test_base.h"
14
15using base::ASCIIToUTF16;
16
17namespace {
18
19gfx::ImageSkia CreateTestImage(int width, int height) {
20  SkBitmap bitmap;
21  bitmap.allocN32Pixels(width, height);
22  return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
23}
24
25}  // namespace
26
27namespace views {
28
29typedef ViewsTestBase LabelButtonTest;
30
31TEST_F(LabelButtonTest, Init) {
32  const base::string16 text(ASCIIToUTF16("abc"));
33  LabelButton button(NULL, text);
34
35  EXPECT_TRUE(button.GetImage(Button::STATE_NORMAL).isNull());
36  EXPECT_TRUE(button.GetImage(Button::STATE_HOVERED).isNull());
37  EXPECT_TRUE(button.GetImage(Button::STATE_PRESSED).isNull());
38  EXPECT_TRUE(button.GetImage(Button::STATE_DISABLED).isNull());
39
40  EXPECT_EQ(text, button.GetText());
41  EXPECT_EQ(gfx::ALIGN_LEFT, button.GetHorizontalAlignment());
42  EXPECT_FALSE(button.is_default());
43  EXPECT_EQ(button.style(), Button::STYLE_TEXTBUTTON);
44  EXPECT_EQ(Button::STATE_NORMAL, button.state());
45
46  EXPECT_EQ(button.image_->parent(), &button);
47  EXPECT_EQ(button.label_->parent(), &button);
48}
49
50TEST_F(LabelButtonTest, Label) {
51  LabelButton button(NULL, base::string16());
52  EXPECT_TRUE(button.GetText().empty());
53
54  const gfx::FontList font_list;
55  const base::string16 short_text(ASCIIToUTF16("abcdefghijklm"));
56  const base::string16 long_text(ASCIIToUTF16("abcdefghijklmnopqrstuvwxyz"));
57  const int short_text_width = gfx::GetStringWidth(short_text, font_list);
58  const int long_text_width = gfx::GetStringWidth(long_text, font_list);
59
60  // The width increases monotonically with string size (it does not shrink).
61  EXPECT_LT(button.GetPreferredSize().width(), short_text_width);
62  button.SetText(short_text);
63  EXPECT_GT(button.GetPreferredSize().height(), font_list.GetHeight());
64  EXPECT_GT(button.GetPreferredSize().width(), short_text_width);
65  EXPECT_LT(button.GetPreferredSize().width(), long_text_width);
66  button.SetText(long_text);
67  EXPECT_GT(button.GetPreferredSize().width(), long_text_width);
68  button.SetText(short_text);
69  EXPECT_GT(button.GetPreferredSize().width(), long_text_width);
70
71  // Clamp the size to a maximum value.
72  button.SetMaxSize(gfx::Size(long_text_width, 1));
73  EXPECT_EQ(button.GetPreferredSize(), gfx::Size(long_text_width, 1));
74
75  // Clear the monotonically increasing minimum size.
76  button.SetMinSize(gfx::Size());
77  EXPECT_GT(button.GetPreferredSize().width(), short_text_width);
78  EXPECT_LT(button.GetPreferredSize().width(), long_text_width);
79}
80
81TEST_F(LabelButtonTest, Image) {
82  LabelButton button(NULL, base::string16());
83
84  const int small_size = 50, large_size = 100;
85  const gfx::ImageSkia small_image = CreateTestImage(small_size, small_size);
86  const gfx::ImageSkia large_image = CreateTestImage(large_size, large_size);
87
88  // The width increases monotonically with image size (it does not shrink).
89  EXPECT_LT(button.GetPreferredSize().width(), small_size);
90  EXPECT_LT(button.GetPreferredSize().height(), small_size);
91  button.SetImage(Button::STATE_NORMAL, small_image);
92  EXPECT_GT(button.GetPreferredSize().width(), small_size);
93  EXPECT_GT(button.GetPreferredSize().height(), small_size);
94  EXPECT_LT(button.GetPreferredSize().width(), large_size);
95  EXPECT_LT(button.GetPreferredSize().height(), large_size);
96  button.SetImage(Button::STATE_NORMAL, large_image);
97  EXPECT_GT(button.GetPreferredSize().width(), large_size);
98  EXPECT_GT(button.GetPreferredSize().height(), large_size);
99  button.SetImage(Button::STATE_NORMAL, small_image);
100  EXPECT_GT(button.GetPreferredSize().width(), large_size);
101  EXPECT_GT(button.GetPreferredSize().height(), large_size);
102
103  // Clamp the size to a maximum value.
104  button.SetMaxSize(gfx::Size(large_size, 1));
105  EXPECT_EQ(button.GetPreferredSize(), gfx::Size(large_size, 1));
106
107  // Clear the monotonically increasing minimum size.
108  button.SetMinSize(gfx::Size());
109  EXPECT_GT(button.GetPreferredSize().width(), small_size);
110  EXPECT_LT(button.GetPreferredSize().width(), large_size);
111}
112
113TEST_F(LabelButtonTest, LabelAndImage) {
114  LabelButton button(NULL, base::string16());
115
116  const gfx::FontList font_list;
117  const base::string16 text(ASCIIToUTF16("abcdefghijklm"));
118  const int text_width = gfx::GetStringWidth(text, font_list);
119
120  const int image_size = 50;
121  const gfx::ImageSkia image = CreateTestImage(image_size, image_size);
122  ASSERT_LT(font_list.GetHeight(), image_size);
123
124  // The width increases monotonically with content size (it does not shrink).
125  EXPECT_LT(button.GetPreferredSize().width(), text_width);
126  EXPECT_LT(button.GetPreferredSize().width(), image_size);
127  EXPECT_LT(button.GetPreferredSize().height(), image_size);
128  button.SetText(text);
129  EXPECT_GT(button.GetPreferredSize().width(), text_width);
130  EXPECT_GT(button.GetPreferredSize().height(), font_list.GetHeight());
131  EXPECT_LT(button.GetPreferredSize().width(), text_width + image_size);
132  EXPECT_LT(button.GetPreferredSize().height(), image_size);
133  button.SetImage(Button::STATE_NORMAL, image);
134  EXPECT_GT(button.GetPreferredSize().width(), text_width + image_size);
135  EXPECT_GT(button.GetPreferredSize().height(), image_size);
136
137  // Layout and ensure the image is left of the label except for ALIGN_RIGHT.
138  // (A proper parent view or layout manager would Layout on its invalidations).
139  button.SetSize(button.GetPreferredSize());
140  button.Layout();
141  EXPECT_EQ(gfx::ALIGN_LEFT, button.GetHorizontalAlignment());
142  EXPECT_LT(button.image_->bounds().right(), button.label_->bounds().x());
143  button.SetHorizontalAlignment(gfx::ALIGN_CENTER);
144  button.Layout();
145  EXPECT_EQ(gfx::ALIGN_CENTER, button.GetHorizontalAlignment());
146  EXPECT_LT(button.image_->bounds().right(), button.label_->bounds().x());
147  button.SetHorizontalAlignment(gfx::ALIGN_RIGHT);
148  button.Layout();
149  EXPECT_EQ(gfx::ALIGN_RIGHT, button.GetHorizontalAlignment());
150  EXPECT_LT(button.label_->bounds().right(), button.image_->bounds().x());
151
152  button.SetText(base::string16());
153  EXPECT_GT(button.GetPreferredSize().width(), text_width + image_size);
154  EXPECT_GT(button.GetPreferredSize().height(), image_size);
155  button.SetImage(Button::STATE_NORMAL, gfx::ImageSkia());
156  EXPECT_GT(button.GetPreferredSize().width(), text_width + image_size);
157  EXPECT_GT(button.GetPreferredSize().height(), image_size);
158
159  // Clamp the size to a maximum value.
160  button.SetMaxSize(gfx::Size(image_size, 1));
161  EXPECT_EQ(button.GetPreferredSize(), gfx::Size(image_size, 1));
162
163  // Clear the monotonically increasing minimum size.
164  button.SetMinSize(gfx::Size());
165  EXPECT_LT(button.GetPreferredSize().width(), text_width);
166  EXPECT_LT(button.GetPreferredSize().width(), image_size);
167  EXPECT_LT(button.GetPreferredSize().height(), image_size);
168}
169
170TEST_F(LabelButtonTest, FontList) {
171  const base::string16 text(ASCIIToUTF16("abc"));
172  LabelButton button(NULL, text);
173
174  const gfx::FontList original_font_list = button.GetFontList();
175  const gfx::FontList large_font_list =
176      original_font_list.DeriveWithSizeDelta(100);
177  const int original_width = button.GetPreferredSize().width();
178  const int original_height = button.GetPreferredSize().height();
179
180  // The button size increases when the font size is increased.
181  button.SetFontList(large_font_list);
182  EXPECT_GT(button.GetPreferredSize().width(), original_width);
183  EXPECT_GT(button.GetPreferredSize().height(), original_height);
184
185  // The button returns to its original size when the minimal size is cleared
186  // and the original font size is restored.
187  button.SetMinSize(gfx::Size());
188  button.SetFontList(original_font_list);
189  EXPECT_EQ(original_width, button.GetPreferredSize().width());
190  EXPECT_EQ(original_height, button.GetPreferredSize().height());
191}
192
193TEST_F(LabelButtonTest, ChangeTextSize) {
194  const base::string16 text(ASCIIToUTF16("abc"));
195  const base::string16 longer_text(ASCIIToUTF16("abcdefghijklm"));
196  LabelButton button(NULL, text);
197
198  const int original_width = button.GetPreferredSize().width();
199
200  // The button size increases when the text size is increased.
201  button.SetText(longer_text);
202  EXPECT_GT(button.GetPreferredSize().width(), original_width);
203
204  // The button returns to its original size when the original text is restored.
205  button.SetMinSize(gfx::Size());
206  button.SetText(text);
207  EXPECT_EQ(original_width, button.GetPreferredSize().width());
208}
209
210TEST_F(LabelButtonTest, ChangeLabelImageSpacing) {
211  LabelButton button(NULL, ASCIIToUTF16("abc"));
212  button.SetImage(Button::STATE_NORMAL, CreateTestImage(50, 50));
213
214  const int kOriginalSpacing = 5;
215  button.SetImageLabelSpacing(kOriginalSpacing);
216  const int original_width = button.GetPreferredSize().width();
217
218  // Increasing the spacing between the text and label should increase the size.
219  button.SetImageLabelSpacing(2 * kOriginalSpacing);
220  EXPECT_GT(button.GetPreferredSize().width(), original_width);
221
222  // The button shrinks if the original spacing is restored.
223  button.SetMinSize(gfx::Size());
224  button.SetImageLabelSpacing(kOriginalSpacing);
225  EXPECT_EQ(original_width, button.GetPreferredSize().width());
226}
227
228}  // namespace views
229