Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / ui / views / controls / styled_label_unittest.cc
1 // Copyright 2013 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 <string>
6
7 #include "base/basictypes.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "third_party/skia/include/core/SkColor.h"
12 #include "ui/gfx/font_list.h"
13 #include "ui/views/border.h"
14 #include "ui/views/controls/link.h"
15 #include "ui/views/controls/styled_label.h"
16 #include "ui/views/controls/styled_label_listener.h"
17 #include "ui/views/test/views_test_base.h"
18 #include "ui/views/widget/widget.h"
19
20 using base::ASCIIToUTF16;
21
22 namespace views {
23
24 class StyledLabelTest : public ViewsTestBase, public StyledLabelListener {
25  public:
26   StyledLabelTest() {}
27   virtual ~StyledLabelTest() {}
28
29   // StyledLabelListener implementation.
30   virtual void StyledLabelLinkClicked(const gfx::Range& range,
31                                       int event_flags) OVERRIDE {}
32
33  protected:
34   StyledLabel* styled() { return styled_.get(); }
35
36   void InitStyledLabel(const std::string& ascii_text) {
37     styled_.reset(new StyledLabel(ASCIIToUTF16(ascii_text), this));
38     styled_->set_owned_by_client();
39   }
40
41   int StyledLabelContentHeightForWidth(int w) {
42     return styled_->GetHeightForWidth(w) - styled_->GetInsets().height();
43   }
44
45  private:
46   scoped_ptr<StyledLabel> styled_;
47
48   DISALLOW_COPY_AND_ASSIGN(StyledLabelTest);
49 };
50
51 TEST_F(StyledLabelTest, NoWrapping) {
52   const std::string text("This is a test block of text");
53   InitStyledLabel(text);
54   Label label(ASCIIToUTF16(text));
55   const gfx::Size label_preferred_size = label.GetPreferredSize();
56   EXPECT_EQ(label_preferred_size.height(),
57             StyledLabelContentHeightForWidth(label_preferred_size.width() * 2));
58 }
59
60 TEST_F(StyledLabelTest, TrailingWhitespaceiIgnored) {
61   const std::string text("This is a test block of text   ");
62   InitStyledLabel(text);
63
64   styled()->SetBounds(0, 0, 1000, 1000);
65   styled()->Layout();
66
67   ASSERT_EQ(1, styled()->child_count());
68   ASSERT_EQ(std::string(Label::kViewClassName),
69             styled()->child_at(0)->GetClassName());
70   EXPECT_EQ(ASCIIToUTF16("This is a test block of text"),
71             static_cast<Label*>(styled()->child_at(0))->text());
72 }
73
74 TEST_F(StyledLabelTest, RespectLeadingWhitespace) {
75   const std::string text("   This is a test block of text");
76   InitStyledLabel(text);
77
78   styled()->SetBounds(0, 0, 1000, 1000);
79   styled()->Layout();
80
81   ASSERT_EQ(1, styled()->child_count());
82   ASSERT_EQ(std::string(Label::kViewClassName),
83             styled()->child_at(0)->GetClassName());
84   EXPECT_EQ(ASCIIToUTF16("   This is a test block of text"),
85             static_cast<Label*>(styled()->child_at(0))->text());
86 }
87
88 TEST_F(StyledLabelTest, FirstLineNotEmptyWhenLeadingWhitespaceTooLong) {
89   const std::string text("                                     a");
90   InitStyledLabel(text);
91
92   Label label(ASCIIToUTF16(text));
93   gfx::Size label_preferred_size = label.GetPreferredSize();
94
95   styled()->SetBounds(0, 0, label_preferred_size.width() / 2, 1000);
96   styled()->Layout();
97
98   ASSERT_EQ(1, styled()->child_count());
99   ASSERT_EQ(std::string(Label::kViewClassName),
100             styled()->child_at(0)->GetClassName());
101   EXPECT_EQ(ASCIIToUTF16("a"),
102             static_cast<Label*>(styled()->child_at(0))->text());
103 }
104
105 TEST_F(StyledLabelTest, BasicWrapping) {
106   const std::string text("This is a test block of text");
107   InitStyledLabel(text);
108   Label label(ASCIIToUTF16(text.substr(0, text.size() * 2 / 3)));
109   gfx::Size label_preferred_size = label.GetPreferredSize();
110   EXPECT_EQ(label_preferred_size.height() * 2,
111             StyledLabelContentHeightForWidth(label_preferred_size.width()));
112
113   // Also respect the border.
114   styled()->SetBorder(Border::CreateEmptyBorder(3, 3, 3, 3));
115   styled()->SetBounds(
116       0,
117       0,
118       styled()->GetInsets().width() + label_preferred_size.width(),
119       styled()->GetInsets().height() + 2 * label_preferred_size.height());
120   styled()->Layout();
121   ASSERT_EQ(2, styled()->child_count());
122   EXPECT_EQ(3, styled()->child_at(0)->x());
123   EXPECT_EQ(3, styled()->child_at(0)->y());
124   EXPECT_EQ(styled()->height() - 3, styled()->child_at(1)->bounds().bottom());
125 }
126
127 TEST_F(StyledLabelTest, CreateLinks) {
128   const std::string text("This is a test block of text.");
129   InitStyledLabel(text);
130
131   // Without links, there should be no focus border.
132   EXPECT_TRUE(styled()->GetInsets().empty());
133
134   // Now let's add some links.
135   styled()->AddStyleRange(gfx::Range(0, 1),
136                           StyledLabel::RangeStyleInfo::CreateForLink());
137   styled()->AddStyleRange(gfx::Range(1, 2),
138                           StyledLabel::RangeStyleInfo::CreateForLink());
139   styled()->AddStyleRange(gfx::Range(10, 11),
140                           StyledLabel::RangeStyleInfo::CreateForLink());
141   styled()->AddStyleRange(gfx::Range(12, 13),
142                           StyledLabel::RangeStyleInfo::CreateForLink());
143
144   // Now there should be a focus border because there are non-empty Links.
145   EXPECT_FALSE(styled()->GetInsets().empty());
146
147   // Verify layout creates the right number of children.
148   styled()->SetBounds(0, 0, 1000, 1000);
149   styled()->Layout();
150   EXPECT_EQ(7, styled()->child_count());
151 }
152
153 TEST_F(StyledLabelTest, DontBreakLinks) {
154   const std::string text("This is a test block of text, ");
155   const std::string link_text("and this should be a link");
156   InitStyledLabel(text + link_text);
157   styled()->AddStyleRange(
158       gfx::Range(text.size(), text.size() + link_text.size()),
159       StyledLabel::RangeStyleInfo::CreateForLink());
160
161   Label label(ASCIIToUTF16(text + link_text.substr(0, link_text.size() / 2)));
162   gfx::Size label_preferred_size = label.GetPreferredSize();
163   int pref_height = styled()->GetHeightForWidth(label_preferred_size.width());
164   EXPECT_EQ(label_preferred_size.height() * 2,
165             pref_height - styled()->GetInsets().height());
166
167   styled()->SetBounds(0, 0, label_preferred_size.width(), pref_height);
168   styled()->Layout();
169   ASSERT_EQ(2, styled()->child_count());
170   // The label has no focus border while the link (and thus overall styled
171   // label) does, so the label should be inset by the width of the focus border.
172   EXPECT_EQ(Label::kFocusBorderPadding, styled()->child_at(0)->x());
173   EXPECT_EQ(0, styled()->child_at(1)->x());
174 }
175
176 TEST_F(StyledLabelTest, StyledRangeWithDisabledLineWrapping) {
177   const std::string text("This is a test block of text, ");
178   const std::string unbreakable_text("and this should not be broken");
179   InitStyledLabel(text + unbreakable_text);
180   StyledLabel::RangeStyleInfo style_info;
181   style_info.disable_line_wrapping = true;
182   styled()->AddStyleRange(
183       gfx::Range(text.size(), text.size() + unbreakable_text.size()),
184       style_info);
185
186   Label label(ASCIIToUTF16(
187       text + unbreakable_text.substr(0, unbreakable_text.size() / 2)));
188   gfx::Size label_preferred_size = label.GetPreferredSize();
189   int pref_height = styled()->GetHeightForWidth(label_preferred_size.width());
190   EXPECT_EQ(label_preferred_size.height() * 2,
191             pref_height - styled()->GetInsets().height());
192
193   styled()->SetBounds(0, 0, label_preferred_size.width(), pref_height);
194   styled()->Layout();
195   ASSERT_EQ(2, styled()->child_count());
196   EXPECT_EQ(0, styled()->child_at(0)->x());
197   EXPECT_EQ(0, styled()->child_at(1)->x());
198 }
199
200 TEST_F(StyledLabelTest, StyledRangeUnderlined) {
201   const std::string text("This is a test block of text, ");
202   const std::string underlined_text("and this should be undelined");
203   InitStyledLabel(text + underlined_text);
204   StyledLabel::RangeStyleInfo style_info;
205   style_info.font_style = gfx::Font::UNDERLINE;
206   styled()->AddStyleRange(
207       gfx::Range(text.size(), text.size() + underlined_text.size()),
208       style_info);
209
210   styled()->SetBounds(0, 0, 1000, 1000);
211   styled()->Layout();
212
213   ASSERT_EQ(2, styled()->child_count());
214   ASSERT_EQ(std::string(Label::kViewClassName),
215             styled()->child_at(1)->GetClassName());
216   EXPECT_EQ(
217       gfx::Font::UNDERLINE,
218       static_cast<Label*>(styled()->child_at(1))->font_list().GetFontStyle());
219 }
220
221 TEST_F(StyledLabelTest, StyledRangeBold) {
222   const std::string bold_text(
223       "This is a block of text whose style will be set to BOLD in the test");
224   const std::string text(" normal text");
225   InitStyledLabel(bold_text + text);
226
227   StyledLabel::RangeStyleInfo style_info;
228   style_info.font_style = gfx::Font::BOLD;
229   styled()->AddStyleRange(gfx::Range(0, bold_text.size()), style_info);
230
231   // Calculate the bold text width if it were a pure label view, both with bold
232   // and normal style.
233   Label label(ASCIIToUTF16(bold_text));
234   const gfx::Size normal_label_size = label.GetPreferredSize();
235   label.SetFontList(label.font_list().DeriveWithStyle(gfx::Font::BOLD));
236   const gfx::Size bold_label_size = label.GetPreferredSize();
237
238   ASSERT_GE(bold_label_size.width(), normal_label_size.width());
239
240   // Set the width so |bold_text| doesn't fit on a single line with bold style,
241   // but does with normal font style.
242   int styled_width = (normal_label_size.width() + bold_label_size.width()) / 2;
243   int pref_height = styled()->GetHeightForWidth(styled_width);
244
245   // Sanity check that |bold_text| with normal font style would fit on a single
246   // line in a styled label with width |styled_width|.
247   StyledLabel unstyled(ASCIIToUTF16(bold_text), this);
248   unstyled.SetBounds(0, 0, styled_width, pref_height);
249   unstyled.Layout();
250   EXPECT_EQ(1, unstyled.child_count());
251
252   styled()->SetBounds(0, 0, styled_width, pref_height);
253   styled()->Layout();
254
255   ASSERT_EQ(3, styled()->child_count());
256
257   // The bold text should be broken up into two parts.
258   ASSERT_EQ(std::string(Label::kViewClassName),
259             styled()->child_at(0)->GetClassName());
260   EXPECT_EQ(
261       gfx::Font::BOLD,
262       static_cast<Label*>(styled()->child_at(0))->font_list().GetFontStyle());
263   ASSERT_EQ(std::string(Label::kViewClassName),
264             styled()->child_at(1)->GetClassName());
265   EXPECT_EQ(
266       gfx::Font::BOLD,
267       static_cast<Label*>(styled()->child_at(1))->font_list().GetFontStyle());
268   ASSERT_EQ(std::string(Label::kViewClassName),
269             styled()->child_at(2)->GetClassName());
270   EXPECT_EQ(
271       gfx::Font::NORMAL,
272       static_cast<Label*>(styled()->child_at(2))->font_list().GetFontStyle());
273
274   // The second bold part should start on a new line.
275   EXPECT_EQ(0, styled()->child_at(0)->x());
276   EXPECT_EQ(0, styled()->child_at(1)->x());
277   EXPECT_EQ(styled()->child_at(1)->bounds().right(),
278             styled()->child_at(2)->x());
279 }
280
281 TEST_F(StyledLabelTest, Color) {
282   const std::string text_red("RED");
283   const std::string text_link("link");
284   const std::string text("word");
285   InitStyledLabel(text_red + text_link + text);
286
287   StyledLabel::RangeStyleInfo style_info_red;
288   style_info_red.color = SK_ColorRED;
289   styled()->AddStyleRange(gfx::Range(0, text_red.size()), style_info_red);
290
291   StyledLabel::RangeStyleInfo style_info_link =
292       StyledLabel::RangeStyleInfo::CreateForLink();
293   styled()->AddStyleRange(gfx::Range(text_red.size(),
294                                     text_red.size() + text_link.size()),
295                           style_info_link);
296
297   styled()->SetBounds(0, 0, 1000, 1000);
298   styled()->Layout();
299
300   Widget* widget = new Widget();
301   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
302   widget->Init(params);
303   View* container = new View();
304   widget->SetContentsView(container);
305   container->AddChildView(styled());
306
307   // Obtain the default text color for a label.
308   Label* label = new Label(ASCIIToUTF16(text));
309   container->AddChildView(label);
310   const SkColor kDefaultTextColor = label->enabled_color();
311
312   // Obtain the default text color for a link;
313   Link* link = new Link(ASCIIToUTF16(text_link));
314   container->AddChildView(link);
315   const SkColor kDefaultLinkColor = link->enabled_color();
316
317   EXPECT_EQ(SK_ColorRED,
318             static_cast<Label*>(styled()->child_at(0))->enabled_color());
319   EXPECT_EQ(kDefaultLinkColor,
320             static_cast<Label*>(styled()->child_at(1))->enabled_color());
321   EXPECT_EQ(kDefaultTextColor,
322             static_cast<Label*>(styled()->child_at(2))->enabled_color());
323
324   // Test adjusted color readability.
325   styled()->SetDisplayedOnBackgroundColor(SK_ColorBLACK);
326   styled()->Layout();
327   label->SetBackgroundColor(SK_ColorBLACK);
328
329   const SkColor kAdjustedTextColor = label->enabled_color();
330   EXPECT_NE(kAdjustedTextColor, kDefaultTextColor);
331   EXPECT_EQ(kAdjustedTextColor,
332             static_cast<Label*>(styled()->child_at(2))->enabled_color());
333
334   widget->CloseNow();
335 }
336
337 TEST_F(StyledLabelTest, StyledRangeWithTooltip) {
338   const std::string text("This is a test block of text, ");
339   const std::string tooltip_text("this should have a tooltip,");
340   const std::string normal_text(" this should not have a tooltip, ");
341   const std::string link_text("and this should be a link");
342
343   const size_t tooltip_start = text.size();
344   const size_t link_start =
345       text.size() + tooltip_text.size() + normal_text.size();
346
347   InitStyledLabel(text + tooltip_text + normal_text + link_text);
348   StyledLabel::RangeStyleInfo tooltip_style;
349   tooltip_style.tooltip = ASCIIToUTF16("tooltip");
350   styled()->AddStyleRange(
351       gfx::Range(tooltip_start, tooltip_start + tooltip_text.size()),
352       tooltip_style);
353   styled()->AddStyleRange(gfx::Range(link_start, link_start + link_text.size()),
354                           StyledLabel::RangeStyleInfo::CreateForLink());
355
356   // Break line inside the range with the tooltip.
357   Label label(ASCIIToUTF16(
358        text + tooltip_text.substr(0, tooltip_text.size() - 3)));
359   gfx::Size label_preferred_size = label.GetPreferredSize();
360   int pref_height = styled()->GetHeightForWidth(label_preferred_size.width());
361   EXPECT_EQ(label_preferred_size.height() * 3,
362             pref_height - styled()->GetInsets().height());
363
364   styled()->SetBounds(0, 0, label_preferred_size.width(), pref_height);
365   styled()->Layout();
366
367   EXPECT_EQ(label_preferred_size.width(), styled()->width());
368
369   ASSERT_EQ(5, styled()->child_count());
370   // The labels have no focus border while the link (and thus overall styled
371   // label) does, so the labels should be inset by the width of the focus
372   // border.
373   EXPECT_EQ(Label::kFocusBorderPadding, styled()->child_at(0)->x());
374   EXPECT_EQ(styled()->child_at(0)->bounds().right(),
375             styled()->child_at(1)->x());
376   EXPECT_EQ(Label::kFocusBorderPadding, styled()->child_at(2)->x());
377   EXPECT_EQ(styled()->child_at(2)->bounds().right(),
378             styled()->child_at(3)->x());
379   EXPECT_EQ(0, styled()->child_at(4)->x());
380
381   base::string16 tooltip;
382   EXPECT_TRUE(
383       styled()->child_at(1)->GetTooltipText(gfx::Point(1, 1), &tooltip));
384   EXPECT_EQ(ASCIIToUTF16("tooltip"), tooltip);
385   EXPECT_TRUE(
386       styled()->child_at(2)->GetTooltipText(gfx::Point(1, 1), &tooltip));
387   EXPECT_EQ(ASCIIToUTF16("tooltip"), tooltip);
388 }
389
390 TEST_F(StyledLabelTest, SetBaseFontList) {
391   const std::string text("This is a test block of text.");
392   InitStyledLabel(text);
393   std::string font_name("arial");
394   gfx::Font font(font_name, 30);
395   styled()->SetBaseFontList(gfx::FontList(font));
396   Label label(ASCIIToUTF16(text), gfx::FontList(font));
397
398   styled()->SetBounds(0,
399                       0,
400                       label.GetPreferredSize().width(),
401                       label.GetPreferredSize().height());
402
403   // Make sure we have the same sizing as a label.
404   EXPECT_EQ(label.GetPreferredSize().height(), styled()->height());
405   EXPECT_EQ(label.GetPreferredSize().width(), styled()->width());
406 }
407
408 TEST_F(StyledLabelTest, LineHeight) {
409   const std::string text("one");
410   InitStyledLabel(text);
411   int default_height = styled()->GetHeightForWidth(100);
412   const std::string newline_text("one\ntwo\nthree");
413   InitStyledLabel(newline_text);
414   styled()->SetLineHeight(18);
415   EXPECT_EQ(18 * 2 + default_height, styled()->GetHeightForWidth(100));
416 }
417
418 TEST_F(StyledLabelTest, HandleEmptyLayout) {
419   const std::string text("This is a test block of text.");
420   InitStyledLabel(text);
421   styled()->Layout();
422   EXPECT_EQ(0, styled()->child_count());
423 }
424
425 }  // namespace views