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/label.h"
7 #include "base/i18n/rtl.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "ui/accessibility/ax_view_state.h"
11 #include "ui/base/l10n/l10n_util.h"
12 #include "ui/compositor/paint_context.h"
13 #include "ui/gfx/canvas.h"
14 #include "ui/views/border.h"
15 #include "ui/views/test/focus_manager_test.h"
16 #include "ui/views/test/views_test_base.h"
17 #include "ui/views/widget/widget.h"
19 using base::ASCIIToUTF16
;
23 typedef ViewsTestBase LabelTest
;
25 class LabelFocusTest
: public FocusManagerTest
{
28 ~LabelFocusTest() override
{}
31 views::Label
* label() { return label_
; }
35 void InitContentView() override
{
36 label_
= new views::Label();
37 GetContentsView()->AddChildView(label_
);
43 // All text sizing measurements (width and height) should be greater than this.
44 const int kMinTextDimension
= 4;
46 // A test utility function to set the application default text direction.
47 void SetRTL(bool rtl
) {
48 // Override the current locale/direction.
49 base::i18n::SetICUDefaultLocale(rtl
? "he" : "en");
50 EXPECT_EQ(rtl
, base::i18n::IsRTL());
53 TEST_F(LabelTest
, FontPropertySymbol
) {
55 std::string
font_name("symbol");
56 gfx::Font
font(font_name
, 26);
57 label
.SetFontList(gfx::FontList(font
));
58 gfx::Font font_used
= label
.font_list().GetPrimaryFont();
59 EXPECT_EQ(font_name
, font_used
.GetFontName());
60 EXPECT_EQ(26, font_used
.GetFontSize());
63 TEST_F(LabelTest
, FontPropertyArial
) {
65 std::string
font_name("arial");
66 gfx::Font
font(font_name
, 30);
67 label
.SetFontList(gfx::FontList(font
));
68 gfx::Font font_used
= label
.font_list().GetPrimaryFont();
69 EXPECT_EQ(font_name
, font_used
.GetFontName());
70 EXPECT_EQ(30, font_used
.GetFontSize());
73 TEST_F(LabelTest
, TextProperty
) {
75 base::string16
test_text(ASCIIToUTF16("A random string."));
76 label
.SetText(test_text
);
77 EXPECT_EQ(test_text
, label
.text());
80 TEST_F(LabelTest
, ColorProperty
) {
82 SkColor color
= SkColorSetARGB(20, 40, 10, 5);
83 label
.SetAutoColorReadabilityEnabled(false);
84 label
.SetEnabledColor(color
);
85 EXPECT_EQ(color
, label
.enabled_color());
88 TEST_F(LabelTest
, AlignmentProperty
) {
89 const bool was_rtl
= base::i18n::IsRTL();
92 for (size_t i
= 0; i
< 2; ++i
) {
93 // Toggle the application default text direction (to try each direction).
94 SetRTL(!base::i18n::IsRTL());
95 bool reverse_alignment
= base::i18n::IsRTL();
97 // The alignment should be flipped in RTL UI.
98 label
.SetHorizontalAlignment(gfx::ALIGN_RIGHT
);
99 EXPECT_EQ(reverse_alignment
? gfx::ALIGN_LEFT
: gfx::ALIGN_RIGHT
,
100 label
.horizontal_alignment());
101 label
.SetHorizontalAlignment(gfx::ALIGN_LEFT
);
102 EXPECT_EQ(reverse_alignment
? gfx::ALIGN_RIGHT
: gfx::ALIGN_LEFT
,
103 label
.horizontal_alignment());
104 label
.SetHorizontalAlignment(gfx::ALIGN_CENTER
);
105 EXPECT_EQ(gfx::ALIGN_CENTER
, label
.horizontal_alignment());
107 for (size_t j
= 0; j
< 2; ++j
) {
108 label
.SetHorizontalAlignment(gfx::ALIGN_TO_HEAD
);
109 const bool rtl
= j
== 0;
110 label
.SetText(rtl
? base::WideToUTF16(L
"\x5d0") : ASCIIToUTF16("A"));
111 EXPECT_EQ(gfx::ALIGN_TO_HEAD
, label
.horizontal_alignment());
115 EXPECT_EQ(was_rtl
, base::i18n::IsRTL());
118 TEST_F(LabelTest
, ElideBehavior
) {
120 base::string16
text(ASCIIToUTF16("This is example text."));
122 EXPECT_EQ(gfx::ELIDE_TAIL
, label
.elide_behavior());
123 gfx::Size size
= label
.GetPreferredSize();
124 label
.SetBoundsRect(gfx::Rect(size
));
125 EXPECT_EQ(text
, label
.GetDisplayTextForTesting());
127 size
.set_width(size
.width() / 2);
128 label
.SetBoundsRect(gfx::Rect(size
));
129 EXPECT_GT(text
.size(), label
.GetDisplayTextForTesting().size());
131 label
.SetElideBehavior(gfx::NO_ELIDE
);
132 EXPECT_EQ(text
, label
.GetDisplayTextForTesting());
135 TEST_F(LabelTest
, MultiLineProperty
) {
137 EXPECT_FALSE(label
.multi_line());
138 label
.SetMultiLine(true);
139 EXPECT_TRUE(label
.multi_line());
140 label
.SetMultiLine(false);
141 EXPECT_FALSE(label
.multi_line());
144 TEST_F(LabelTest
, ObscuredProperty
) {
146 base::string16
test_text(ASCIIToUTF16("Password!"));
147 label
.SetText(test_text
);
148 label
.SizeToPreferredSize();
150 // The text should be unobscured by default.
151 EXPECT_FALSE(label
.obscured());
152 EXPECT_EQ(test_text
, label
.GetDisplayTextForTesting());
153 EXPECT_EQ(test_text
, label
.text());
155 label
.SetObscured(true);
156 label
.SizeToPreferredSize();
157 EXPECT_TRUE(label
.obscured());
158 EXPECT_EQ(ASCIIToUTF16("*********"), label
.GetDisplayTextForTesting());
159 EXPECT_EQ(test_text
, label
.text());
161 label
.SetText(test_text
+ test_text
);
162 label
.SizeToPreferredSize();
163 EXPECT_EQ(ASCIIToUTF16("******************"),
164 label
.GetDisplayTextForTesting());
165 EXPECT_EQ(test_text
+ test_text
, label
.text());
167 label
.SetObscured(false);
168 label
.SizeToPreferredSize();
169 EXPECT_FALSE(label
.obscured());
170 EXPECT_EQ(test_text
+ test_text
, label
.GetDisplayTextForTesting());
171 EXPECT_EQ(test_text
+ test_text
, label
.text());
174 TEST_F(LabelTest
, ObscuredSurrogatePair
) {
175 // 'MUSICAL SYMBOL G CLEF': represented in UTF-16 as two characters
176 // forming the surrogate pair 0x0001D11E.
178 base::string16 test_text
= base::UTF8ToUTF16("\xF0\x9D\x84\x9E");
179 label
.SetText(test_text
);
180 label
.SizeToPreferredSize();
182 label
.SetObscured(true);
183 EXPECT_EQ(ASCIIToUTF16("*"), label
.GetDisplayTextForTesting());
184 EXPECT_EQ(test_text
, label
.text());
187 // This test case verifies the label preferred size will change based on the
188 // current layout, which may seem wrong. However many of our code base assumes
189 // this behavior, therefore this behavior will have to be kept until the code
190 // with this assumption is fixed. See http://crbug.com/468494 and
191 // http://crbug.com/467526.
192 // TODO(mukai): fix the code assuming this behavior and then fix Label
193 // implementation, and remove this test case.
194 TEST_F(LabelTest
, MultilinePreferredSizeTest
) {
196 label
.SetText(ASCIIToUTF16("This is an example."));
198 gfx::Size single_line_size
= label
.GetPreferredSize();
200 label
.SetMultiLine(true);
201 gfx::Size multi_line_size
= label
.GetPreferredSize();
202 EXPECT_EQ(single_line_size
, multi_line_size
);
204 int new_width
= multi_line_size
.width() / 2;
205 label
.SetBounds(0, 0, new_width
, label
.GetHeightForWidth(new_width
));
206 gfx::Size new_size
= label
.GetPreferredSize();
207 EXPECT_GT(multi_line_size
.width(), new_size
.width());
208 EXPECT_LT(multi_line_size
.height(), new_size
.height());
211 TEST_F(LabelTest
, TooltipProperty
) {
213 label
.SetText(ASCIIToUTF16("My cool string."));
215 // Initially, label has no bounds, its text does not fit, and therefore its
216 // text should be returned as the tooltip text.
217 base::string16 tooltip
;
218 EXPECT_TRUE(label
.GetTooltipText(gfx::Point(), &tooltip
));
219 EXPECT_EQ(label
.text(), tooltip
);
221 // While tooltip handling is disabled, GetTooltipText() should fail.
222 label
.SetHandlesTooltips(false);
223 EXPECT_FALSE(label
.GetTooltipText(gfx::Point(), &tooltip
));
224 label
.SetHandlesTooltips(true);
226 // When set, custom tooltip text should be returned instead of the label's
228 base::string16
tooltip_text(ASCIIToUTF16("The tooltip!"));
229 label
.SetTooltipText(tooltip_text
);
230 EXPECT_TRUE(label
.GetTooltipText(gfx::Point(), &tooltip
));
231 EXPECT_EQ(tooltip_text
, tooltip
);
233 // While tooltip handling is disabled, GetTooltipText() should fail.
234 label
.SetHandlesTooltips(false);
235 EXPECT_FALSE(label
.GetTooltipText(gfx::Point(), &tooltip
));
236 label
.SetHandlesTooltips(true);
238 // When the tooltip text is set to an empty string, the original behavior is
240 label
.SetTooltipText(base::string16());
241 EXPECT_TRUE(label
.GetTooltipText(gfx::Point(), &tooltip
));
242 EXPECT_EQ(label
.text(), tooltip
);
244 // While tooltip handling is disabled, GetTooltipText() should fail.
245 label
.SetHandlesTooltips(false);
246 EXPECT_FALSE(label
.GetTooltipText(gfx::Point(), &tooltip
));
247 label
.SetHandlesTooltips(true);
249 // Make the label big enough to hold the text
250 // and expect there to be no tooltip.
251 label
.SetBounds(0, 0, 1000, 40);
252 EXPECT_FALSE(label
.GetTooltipText(gfx::Point(), &tooltip
));
254 // Shrinking the single-line label's height shouldn't trigger a tooltip.
255 label
.SetBounds(0, 0, 1000, label
.GetPreferredSize().height() / 2);
256 EXPECT_FALSE(label
.GetTooltipText(gfx::Point(), &tooltip
));
258 // Verify that explicitly set tooltip text is shown, regardless of size.
259 label
.SetTooltipText(tooltip_text
);
260 EXPECT_TRUE(label
.GetTooltipText(gfx::Point(), &tooltip
));
261 EXPECT_EQ(tooltip_text
, tooltip
);
262 // Clear out the explicitly set tooltip text.
263 label
.SetTooltipText(base::string16());
265 // Shrink the bounds and the tooltip should come back.
266 label
.SetBounds(0, 0, 10, 10);
267 EXPECT_TRUE(label
.GetTooltipText(gfx::Point(), &tooltip
));
269 // Make the label obscured and there is no tooltip.
270 label
.SetObscured(true);
271 EXPECT_FALSE(label
.GetTooltipText(gfx::Point(), &tooltip
));
273 // Obscuring the text shouldn't permanently clobber the tooltip.
274 label
.SetObscured(false);
275 EXPECT_TRUE(label
.GetTooltipText(gfx::Point(), &tooltip
));
277 // Making the label multiline shouldn't eliminate the tooltip.
278 label
.SetMultiLine(true);
279 EXPECT_TRUE(label
.GetTooltipText(gfx::Point(), &tooltip
));
280 // Expanding the multiline label bounds should eliminate the tooltip.
281 label
.SetBounds(0, 0, 1000, 1000);
282 EXPECT_FALSE(label
.GetTooltipText(gfx::Point(), &tooltip
));
284 // Verify that setting the tooltip still shows it.
285 label
.SetTooltipText(tooltip_text
);
286 EXPECT_TRUE(label
.GetTooltipText(gfx::Point(), &tooltip
));
287 EXPECT_EQ(tooltip_text
, tooltip
);
288 // Clear out the tooltip.
289 label
.SetTooltipText(base::string16());
292 TEST_F(LabelTest
, Accessibility
) {
294 label
.SetText(ASCIIToUTF16("My special text."));
296 ui::AXViewState state
;
297 label
.GetAccessibleState(&state
);
298 EXPECT_EQ(ui::AX_ROLE_STATIC_TEXT
, state
.role
);
299 EXPECT_EQ(label
.text(), state
.name
);
300 EXPECT_TRUE(state
.HasStateFlag(ui::AX_STATE_READ_ONLY
));
303 TEST_F(LabelTest
, TextChangeWithoutLayout
) {
305 label
.SetText(ASCIIToUTF16("Example"));
306 label
.SetBounds(0, 0, 200, 200);
308 gfx::Canvas
canvas(gfx::Size(200, 200), 1.0f
, true);
309 label
.Paint(ui::PaintContext(&canvas
));
310 EXPECT_EQ(1u, label
.lines_
.size());
311 EXPECT_EQ(ASCIIToUTF16("Example"), label
.lines_
[0]->GetDisplayText());
313 label
.SetText(ASCIIToUTF16("Altered"));
314 // The altered text should be painted even though Layout() or SetBounds() are
316 label
.Paint(ui::PaintContext(&canvas
));
317 EXPECT_EQ(1u, label
.lines_
.size());
318 EXPECT_EQ(ASCIIToUTF16("Altered"), label
.lines_
[0]->GetDisplayText());
321 TEST_F(LabelTest
, EmptyLabelSizing
) {
323 const gfx::Size
expected_size(0, gfx::FontList().GetHeight());
324 EXPECT_EQ(expected_size
, label
.GetPreferredSize());
325 label
.SetMultiLine(!label
.multi_line());
326 EXPECT_EQ(expected_size
, label
.GetPreferredSize());
329 TEST_F(LabelTest
, SingleLineSizing
) {
331 label
.SetText(ASCIIToUTF16("A not so random string in one line."));
332 const gfx::Size size
= label
.GetPreferredSize();
333 EXPECT_GT(size
.height(), kMinTextDimension
);
334 EXPECT_GT(size
.width(), kMinTextDimension
);
336 // Setting a size smaller than preferred should not change the preferred size.
337 label
.SetSize(gfx::Size(size
.width() / 2, size
.height() / 2));
338 EXPECT_EQ(size
, label
.GetPreferredSize());
340 const gfx::Insets
border(10, 20, 30, 40);
341 label
.SetBorder(Border::CreateEmptyBorder(
342 border
.top(), border
.left(), border
.bottom(), border
.right()));
343 const gfx::Size size_with_border
= label
.GetPreferredSize();
344 EXPECT_EQ(size_with_border
.height(), size
.height() + border
.height());
345 EXPECT_EQ(size_with_border
.width(), size
.width() + border
.width());
346 EXPECT_EQ(size
.height() + border
.height(),
347 label
.GetHeightForWidth(size_with_border
.width()));
350 TEST_F(LabelTest
, MultilineSmallAvailableWidthSizing
) {
352 label
.SetMultiLine(true);
353 label
.SetAllowCharacterBreak(true);
354 label
.SetText(ASCIIToUTF16("Too Wide."));
356 // Check that Label can be laid out at a variety of small sizes,
357 // splitting the words into up to one character per line if necessary.
358 // Incorrect word splitting may cause infinite loops in text layout.
359 gfx::Size required_size
= label
.GetPreferredSize();
360 for (int i
= 1; i
< required_size
.width(); ++i
)
361 EXPECT_GT(label
.GetHeightForWidth(i
), 0);
364 // Verifies if SetAllowCharacterBreak(true) doesn't change the preferred size.
365 // See crbug.com/469559
366 TEST_F(LabelTest
, PreferredSizeForAllowCharacterBreak
) {
367 Label
label(base::ASCIIToUTF16("Example"));
368 gfx::Size preferred_size
= label
.GetPreferredSize();
370 label
.SetMultiLine(true);
371 label
.SetAllowCharacterBreak(true);
372 EXPECT_EQ(preferred_size
, label
.GetPreferredSize());
375 TEST_F(LabelTest
, MultiLineSizing
) {
377 label
.SetFocusable(false);
379 ASCIIToUTF16("A random string\nwith multiple lines\nand returns!"));
380 label
.SetMultiLine(true);
383 gfx::Size required_size
= label
.GetPreferredSize();
384 EXPECT_GT(required_size
.height(), kMinTextDimension
);
385 EXPECT_GT(required_size
.width(), kMinTextDimension
);
387 // SizeToFit with unlimited width.
389 int required_width
= label
.GetLocalBounds().width();
390 EXPECT_GT(required_width
, kMinTextDimension
);
392 // SizeToFit with limited width.
393 label
.SizeToFit(required_width
- 1);
394 int constrained_width
= label
.GetLocalBounds().width();
396 // Canvas::SizeStringInt (in ui/gfx/canvas_linux.cc)
397 // has to be fixed to return the size that fits to given width/height.
398 EXPECT_LT(constrained_width
, required_width
);
400 EXPECT_GT(constrained_width
, kMinTextDimension
);
402 // Change the width back to the desire width.
403 label
.SizeToFit(required_width
);
404 EXPECT_EQ(required_width
, label
.GetLocalBounds().width());
406 // General tests for GetHeightForWidth.
407 int required_height
= label
.GetHeightForWidth(required_width
);
408 EXPECT_GT(required_height
, kMinTextDimension
);
409 int height_for_constrained_width
= label
.GetHeightForWidth(constrained_width
);
411 // Canvas::SizeStringInt (in ui/gfx/canvas_linux.cc)
412 // has to be fixed to return the size that fits to given width/height.
413 EXPECT_GT(height_for_constrained_width
, required_height
);
415 // Using the constrained width or the required_width - 1 should give the
416 // same result for the height because the constrainted width is the tight
417 // width when given "required_width - 1" as the max width.
418 EXPECT_EQ(height_for_constrained_width
,
419 label
.GetHeightForWidth(required_width
- 1));
421 // Test everything with borders.
422 gfx::Insets
border(10, 20, 30, 40);
423 label
.SetBorder(Border::CreateEmptyBorder(
424 border
.top(), border
.left(), border
.bottom(), border
.right()));
426 // SizeToFit and borders.
428 int required_width_with_border
= label
.GetLocalBounds().width();
429 EXPECT_EQ(required_width_with_border
, required_width
+ border
.width());
431 // GetHeightForWidth and borders.
432 int required_height_with_border
=
433 label
.GetHeightForWidth(required_width_with_border
);
434 EXPECT_EQ(required_height_with_border
, required_height
+ border
.height());
436 // Test that the border width is subtracted before doing the height
437 // calculation. If it is, then the height will grow when width
439 int height1
= label
.GetHeightForWidth(required_width_with_border
- 1);
441 // Canvas::SizeStringInt (in ui/gfx/canvas_linux.cc)
442 // has to be fixed to return the size that fits to given width/height.
443 EXPECT_GT(height1
, required_height_with_border
);
445 EXPECT_EQ(height1
, height_for_constrained_width
+ border
.height());
447 // GetPreferredSize and borders.
448 label
.SetBounds(0, 0, 0, 0);
449 gfx::Size required_size_with_border
= label
.GetPreferredSize();
450 EXPECT_EQ(required_size_with_border
.height(),
451 required_size
.height() + border
.height());
452 EXPECT_EQ(required_size_with_border
.width(),
453 required_size
.width() + border
.width());
456 // Verifies if the combination of text eliding and multiline doesn't cause
457 // any side effects of size / layout calculation.
458 TEST_F(LabelTest
, MultiLineSizingWithElide
) {
459 const base::string16 text
=
460 ASCIIToUTF16("A random string\nwith multiple lines\nand returns!");
462 label
.SetFocusable(false);
464 label
.SetMultiLine(true);
466 gfx::Size required_size
= label
.GetPreferredSize();
467 EXPECT_GT(required_size
.height(), kMinTextDimension
);
468 EXPECT_GT(required_size
.width(), kMinTextDimension
);
469 label
.SetBoundsRect(gfx::Rect(required_size
));
471 label
.SetElideBehavior(gfx::ELIDE_TAIL
);
472 EXPECT_EQ(required_size
.ToString(), label
.GetPreferredSize().ToString());
473 EXPECT_EQ(text
, label
.GetDisplayTextForTesting());
475 label
.SizeToFit(required_size
.width() - 1);
476 gfx::Size narrow_size
= label
.GetPreferredSize();
477 EXPECT_GT(required_size
.width(), narrow_size
.width());
478 EXPECT_LT(required_size
.height(), narrow_size
.height());
480 // SetBounds() doesn't change the preferred size.
481 label
.SetBounds(0, 0, narrow_size
.width() - 1, narrow_size
.height());
482 EXPECT_EQ(narrow_size
.ToString(), label
.GetPreferredSize().ToString());
484 // Paint() doesn't change the preferred size.
486 label
.Paint(ui::PaintContext(&canvas
));
487 EXPECT_EQ(narrow_size
.ToString(), label
.GetPreferredSize().ToString());
490 // Check that labels support GetTooltipHandlerForPoint.
491 TEST_F(LabelTest
, GetTooltipHandlerForPoint
) {
492 // A root view must be defined for this test because the hit-testing
493 // behaviour used by GetTooltipHandlerForPoint() is defined by
494 // the ViewTargeter installed on the root view.
496 Widget::InitParams init_params
=
497 CreateParams(Widget::InitParams::TYPE_POPUP
);
498 init_params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
499 init_params
.bounds
= gfx::Rect(0, 0, 200, 200);
500 widget
.Init(init_params
);
504 ASCIIToUTF16("A string that's long enough to exceed the bounds"));
505 label
.SetBounds(0, 0, 10, 10);
506 widget
.SetContentsView(&label
);
508 // By default, labels start out as tooltip handlers.
509 ASSERT_TRUE(label
.handles_tooltips());
511 // There's a default tooltip if the text is too big to fit.
512 EXPECT_EQ(&label
, label
.GetTooltipHandlerForPoint(gfx::Point(2, 2)));
514 // If tooltip handling is disabled, the label should not provide a tooltip
516 label
.SetHandlesTooltips(false);
517 EXPECT_FALSE(label
.GetTooltipHandlerForPoint(gfx::Point(2, 2)));
518 label
.SetHandlesTooltips(true);
520 // If there's no default tooltip, this should return NULL.
521 label
.SetBounds(0, 0, 500, 50);
522 EXPECT_FALSE(label
.GetTooltipHandlerForPoint(gfx::Point(2, 2)));
524 label
.SetTooltipText(ASCIIToUTF16("a tooltip"));
525 // If the point hits the label, and tooltip is set, the label should be
526 // returned as its tooltip handler.
527 EXPECT_EQ(&label
, label
.GetTooltipHandlerForPoint(gfx::Point(2, 2)));
529 // Additionally, GetTooltipHandlerForPoint should verify that the label
530 // actually contains the point.
531 EXPECT_FALSE(label
.GetTooltipHandlerForPoint(gfx::Point(2, 51)));
532 EXPECT_FALSE(label
.GetTooltipHandlerForPoint(gfx::Point(-1, 20)));
534 // Again, if tooltip handling is disabled, the label should not provide a
536 label
.SetHandlesTooltips(false);
537 EXPECT_FALSE(label
.GetTooltipHandlerForPoint(gfx::Point(2, 2)));
538 EXPECT_FALSE(label
.GetTooltipHandlerForPoint(gfx::Point(2, 51)));
539 EXPECT_FALSE(label
.GetTooltipHandlerForPoint(gfx::Point(-1, 20)));
540 label
.SetHandlesTooltips(true);
542 // GetTooltipHandlerForPoint works should work in child bounds.
543 label
.SetBounds(2, 2, 10, 10);
544 EXPECT_EQ(&label
, label
.GetTooltipHandlerForPoint(gfx::Point(1, 5)));
545 EXPECT_FALSE(label
.GetTooltipHandlerForPoint(gfx::Point(3, 11)));
548 // Check that label releases its internal layout data when it's unnecessary.
549 TEST_F(LabelTest
, ResetRenderTextData
) {
551 label
.SetText(ASCIIToUTF16("Example"));
552 label
.SizeToPreferredSize();
553 gfx::Size preferred_size
= label
.GetPreferredSize();
555 EXPECT_NE(gfx::Size().ToString(), preferred_size
.ToString());
556 EXPECT_EQ(0u, label
.lines_
.size());
558 gfx::Canvas
canvas(preferred_size
, 1.0f
, true);
559 label
.Paint(ui::PaintContext(&canvas
));
560 EXPECT_EQ(1u, label
.lines_
.size());
562 // Label should recreate its RenderText object when it's invisible, to release
563 // the layout structures and data.
564 label
.SetVisible(false);
565 EXPECT_EQ(0u, label
.lines_
.size());
567 // Querying fields or size information should not recompute the layout
569 EXPECT_EQ(ASCIIToUTF16("Example"), label
.text());
570 EXPECT_EQ(0u, label
.lines_
.size());
572 EXPECT_EQ(preferred_size
.ToString(), label
.GetPreferredSize().ToString());
573 EXPECT_EQ(0u, label
.lines_
.size());
575 // RenderText data should be back when it's necessary.
576 label
.SetVisible(true);
577 EXPECT_EQ(0u, label
.lines_
.size());
579 label
.Paint(ui::PaintContext(&canvas
));
580 EXPECT_EQ(1u, label
.lines_
.size());
582 // Changing layout just resets |lines_|. It'll recover next time it's drawn.
583 label
.SetBounds(0, 0, 10, 10);
584 EXPECT_EQ(0u, label
.lines_
.size());
586 label
.Paint(ui::PaintContext(&canvas
));
587 EXPECT_EQ(1u, label
.lines_
.size());
590 #if !defined(OS_MACOSX)
591 TEST_F(LabelTest
, MultilineSupportedRenderText
) {
592 scoped_ptr
<gfx::RenderText
> render_text(gfx::RenderText::CreateInstance());
593 ASSERT_TRUE(render_text
->MultilineSupported());
596 label
.SetText(ASCIIToUTF16("Example of\nmultilined label"));
597 label
.SetMultiLine(true);
598 label
.SizeToPreferredSize();
600 gfx::Canvas
canvas(label
.GetPreferredSize(), 1.0f
, true);
601 label
.Paint(ui::PaintContext(&canvas
));
603 // There's only one 'line', RenderText itself supports multiple lines.
604 EXPECT_EQ(1u, label
.lines_
.size());
608 TEST_F(LabelFocusTest
, FocusBounds
) {
609 label()->SetText(ASCIIToUTF16("Example"));
610 gfx::Size normal_size
= label()->GetPreferredSize();
612 label()->SetFocusable(true);
613 label()->RequestFocus();
614 gfx::Size focusable_size
= label()->GetPreferredSize();
615 // Focusable label requires larger size to paint the focus rectangle.
616 EXPECT_GT(focusable_size
.width(), normal_size
.width());
617 EXPECT_GT(focusable_size
.height(), normal_size
.height());
619 label()->SizeToPreferredSize();
620 gfx::Rect focus_bounds
= label()->GetFocusBounds();
621 EXPECT_EQ(label()->GetLocalBounds().ToString(), focus_bounds
.ToString());
624 0, 0, focusable_size
.width() * 2, focusable_size
.height() * 2);
625 label()->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
626 focus_bounds
= label()->GetFocusBounds();
627 EXPECT_EQ(0, focus_bounds
.x());
628 EXPECT_LT(0, focus_bounds
.y());
629 EXPECT_GT(label()->bounds().bottom(), focus_bounds
.bottom());
630 EXPECT_EQ(focusable_size
.ToString(), focus_bounds
.size().ToString());
632 label()->SetHorizontalAlignment(gfx::ALIGN_RIGHT
);
633 focus_bounds
= label()->GetFocusBounds();
634 EXPECT_LT(0, focus_bounds
.x());
635 EXPECT_EQ(label()->bounds().right(), focus_bounds
.right());
636 EXPECT_LT(0, focus_bounds
.y());
637 EXPECT_GT(label()->bounds().bottom(), focus_bounds
.bottom());
638 EXPECT_EQ(focusable_size
.ToString(), focus_bounds
.size().ToString());
640 label()->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
641 label()->SetElideBehavior(gfx::FADE_TAIL
);
642 label()->SetBounds(0, 0, focusable_size
.width() / 2, focusable_size
.height());
643 focus_bounds
= label()->GetFocusBounds();
644 EXPECT_EQ(0, focus_bounds
.x());
645 EXPECT_EQ(focusable_size
.width() / 2, focus_bounds
.width());
648 TEST_F(LabelFocusTest
, EmptyLabel
) {
649 label()->SetFocusable(true);
650 label()->RequestFocus();
651 label()->SizeToPreferredSize();
653 gfx::Rect focus_bounds
= label()->GetFocusBounds();
654 EXPECT_FALSE(focus_bounds
.IsEmpty());
655 EXPECT_LT(label()->font_list().GetHeight(), focus_bounds
.height());