Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ui / views / controls / label_unittest.cc
blob47cb37ae44a3dc0b65852b6dd462d5e4b09beeb6
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/canvas_painter.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;
21 namespace views {
23 typedef ViewsTestBase LabelTest;
25 class LabelFocusTest : public FocusManagerTest {
26 public:
27 LabelFocusTest() {}
28 ~LabelFocusTest() override {}
30 protected:
31 views::Label* label() { return label_; }
33 private:
34 // FocusManagerTest:
35 void InitContentView() override {
36 label_ = new views::Label();
37 GetContentsView()->AddChildView(label_);
40 views::Label* 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) {
54 Label label;
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) {
64 Label label;
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) {
74 Label label;
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) {
81 Label label;
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();
91 Label label;
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) {
119 Label label;
120 base::string16 text(ASCIIToUTF16("This is example text."));
121 label.SetText(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) {
136 Label label;
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) {
145 Label label;
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.
177 Label label;
178 base::string16 test_text = base::UTF8ToUTF16("\xF0\x9D\x84\x9E");
179 label.SetText(test_text);
180 label.SetObscured(true);
181 label.SizeToPreferredSize();
182 EXPECT_EQ(ASCIIToUTF16("*"), label.GetDisplayTextForTesting());
183 EXPECT_EQ(test_text, label.text());
186 // This test case verifies the label preferred size will change based on the
187 // current layout, which may seem wrong. However many of our code base assumes
188 // this behavior, therefore this behavior will have to be kept until the code
189 // with this assumption is fixed. See http://crbug.com/468494 and
190 // http://crbug.com/467526.
191 // TODO(mukai): fix the code assuming this behavior and then fix Label
192 // implementation, and remove this test case.
193 TEST_F(LabelTest, MultilinePreferredSizeTest) {
194 Label label;
195 label.SetText(ASCIIToUTF16("This is an example."));
197 gfx::Size single_line_size = label.GetPreferredSize();
199 label.SetMultiLine(true);
200 gfx::Size multi_line_size = label.GetPreferredSize();
201 EXPECT_EQ(single_line_size, multi_line_size);
203 int new_width = multi_line_size.width() / 2;
204 label.SetBounds(0, 0, new_width, label.GetHeightForWidth(new_width));
205 gfx::Size new_size = label.GetPreferredSize();
206 EXPECT_GT(multi_line_size.width(), new_size.width());
207 EXPECT_LT(multi_line_size.height(), new_size.height());
210 TEST_F(LabelTest, TooltipProperty) {
211 Label label;
212 label.SetText(ASCIIToUTF16("My cool string."));
214 // Initially, label has no bounds, its text does not fit, and therefore its
215 // text should be returned as the tooltip text.
216 base::string16 tooltip;
217 EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip));
218 EXPECT_EQ(label.text(), tooltip);
220 // While tooltip handling is disabled, GetTooltipText() should fail.
221 label.SetHandlesTooltips(false);
222 EXPECT_FALSE(label.GetTooltipText(gfx::Point(), &tooltip));
223 label.SetHandlesTooltips(true);
225 // When set, custom tooltip text should be returned instead of the label's
226 // text.
227 base::string16 tooltip_text(ASCIIToUTF16("The tooltip!"));
228 label.SetTooltipText(tooltip_text);
229 EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip));
230 EXPECT_EQ(tooltip_text, tooltip);
232 // While tooltip handling is disabled, GetTooltipText() should fail.
233 label.SetHandlesTooltips(false);
234 EXPECT_FALSE(label.GetTooltipText(gfx::Point(), &tooltip));
235 label.SetHandlesTooltips(true);
237 // When the tooltip text is set to an empty string, the original behavior is
238 // restored.
239 label.SetTooltipText(base::string16());
240 EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip));
241 EXPECT_EQ(label.text(), tooltip);
243 // While tooltip handling is disabled, GetTooltipText() should fail.
244 label.SetHandlesTooltips(false);
245 EXPECT_FALSE(label.GetTooltipText(gfx::Point(), &tooltip));
246 label.SetHandlesTooltips(true);
248 // Make the label big enough to hold the text
249 // and expect there to be no tooltip.
250 label.SetBounds(0, 0, 1000, 40);
251 EXPECT_FALSE(label.GetTooltipText(gfx::Point(), &tooltip));
253 // Shrinking the single-line label's height shouldn't trigger a tooltip.
254 label.SetBounds(0, 0, 1000, label.GetPreferredSize().height() / 2);
255 EXPECT_FALSE(label.GetTooltipText(gfx::Point(), &tooltip));
257 // Verify that explicitly set tooltip text is shown, regardless of size.
258 label.SetTooltipText(tooltip_text);
259 EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip));
260 EXPECT_EQ(tooltip_text, tooltip);
261 // Clear out the explicitly set tooltip text.
262 label.SetTooltipText(base::string16());
264 // Shrink the bounds and the tooltip should come back.
265 label.SetBounds(0, 0, 10, 10);
266 EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip));
268 // Make the label obscured and there is no tooltip.
269 label.SetObscured(true);
270 EXPECT_FALSE(label.GetTooltipText(gfx::Point(), &tooltip));
272 // Obscuring the text shouldn't permanently clobber the tooltip.
273 label.SetObscured(false);
274 EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip));
276 // Making the label multiline shouldn't eliminate the tooltip.
277 label.SetMultiLine(true);
278 EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip));
279 // Expanding the multiline label bounds should eliminate the tooltip.
280 label.SetBounds(0, 0, 1000, 1000);
281 EXPECT_FALSE(label.GetTooltipText(gfx::Point(), &tooltip));
283 // Verify that setting the tooltip still shows it.
284 label.SetTooltipText(tooltip_text);
285 EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip));
286 EXPECT_EQ(tooltip_text, tooltip);
287 // Clear out the tooltip.
288 label.SetTooltipText(base::string16());
291 TEST_F(LabelTest, Accessibility) {
292 Label label;
293 label.SetText(ASCIIToUTF16("My special text."));
295 ui::AXViewState state;
296 label.GetAccessibleState(&state);
297 EXPECT_EQ(ui::AX_ROLE_STATIC_TEXT, state.role);
298 EXPECT_EQ(label.text(), state.name);
299 EXPECT_TRUE(state.HasStateFlag(ui::AX_STATE_READ_ONLY));
302 TEST_F(LabelTest, TextChangeWithoutLayout) {
303 Label label;
304 label.SetText(ASCIIToUTF16("Example"));
305 label.SetBounds(0, 0, 200, 200);
307 gfx::Canvas canvas(gfx::Size(200, 200), 1.0f, true);
308 label.Paint(ui::CanvasPainter(&canvas, 1.f).context());
309 EXPECT_EQ(1u, label.lines_.size());
310 EXPECT_EQ(ASCIIToUTF16("Example"), label.lines_[0]->GetDisplayText());
312 label.SetText(ASCIIToUTF16("Altered"));
313 // The altered text should be painted even though Layout() or SetBounds() are
314 // not called.
315 label.Paint(ui::CanvasPainter(&canvas, 1.f).context());
316 EXPECT_EQ(1u, label.lines_.size());
317 EXPECT_EQ(ASCIIToUTF16("Altered"), label.lines_[0]->GetDisplayText());
320 TEST_F(LabelTest, EmptyLabelSizing) {
321 Label label;
322 const gfx::Size expected_size(0, gfx::FontList().GetHeight());
323 EXPECT_EQ(expected_size, label.GetPreferredSize());
324 label.SetMultiLine(!label.multi_line());
325 EXPECT_EQ(expected_size, label.GetPreferredSize());
328 TEST_F(LabelTest, SingleLineSizing) {
329 Label label;
330 label.SetText(ASCIIToUTF16("A not so random string in one line."));
331 const gfx::Size size = label.GetPreferredSize();
332 EXPECT_GT(size.height(), kMinTextDimension);
333 EXPECT_GT(size.width(), kMinTextDimension);
335 // Setting a size smaller than preferred should not change the preferred size.
336 label.SetSize(gfx::Size(size.width() / 2, size.height() / 2));
337 EXPECT_EQ(size, label.GetPreferredSize());
339 const gfx::Insets border(10, 20, 30, 40);
340 label.SetBorder(Border::CreateEmptyBorder(
341 border.top(), border.left(), border.bottom(), border.right()));
342 const gfx::Size size_with_border = label.GetPreferredSize();
343 EXPECT_EQ(size_with_border.height(), size.height() + border.height());
344 EXPECT_EQ(size_with_border.width(), size.width() + border.width());
345 EXPECT_EQ(size.height() + border.height(),
346 label.GetHeightForWidth(size_with_border.width()));
349 TEST_F(LabelTest, MultilineSmallAvailableWidthSizing) {
350 Label label;
351 label.SetMultiLine(true);
352 label.SetAllowCharacterBreak(true);
353 label.SetText(ASCIIToUTF16("Too Wide."));
355 // Check that Label can be laid out at a variety of small sizes,
356 // splitting the words into up to one character per line if necessary.
357 // Incorrect word splitting may cause infinite loops in text layout.
358 gfx::Size required_size = label.GetPreferredSize();
359 for (int i = 1; i < required_size.width(); ++i)
360 EXPECT_GT(label.GetHeightForWidth(i), 0);
363 // Verifies if SetAllowCharacterBreak(true) doesn't change the preferred size.
364 // See crbug.com/469559
365 TEST_F(LabelTest, PreferredSizeForAllowCharacterBreak) {
366 Label label(base::ASCIIToUTF16("Example"));
367 gfx::Size preferred_size = label.GetPreferredSize();
369 label.SetMultiLine(true);
370 label.SetAllowCharacterBreak(true);
371 EXPECT_EQ(preferred_size, label.GetPreferredSize());
374 TEST_F(LabelTest, MultiLineSizing) {
375 Label label;
376 label.SetFocusable(false);
377 label.SetText(
378 ASCIIToUTF16("A random string\nwith multiple lines\nand returns!"));
379 label.SetMultiLine(true);
381 // GetPreferredSize
382 gfx::Size required_size = label.GetPreferredSize();
383 EXPECT_GT(required_size.height(), kMinTextDimension);
384 EXPECT_GT(required_size.width(), kMinTextDimension);
386 // SizeToFit with unlimited width.
387 label.SizeToFit(0);
388 int required_width = label.GetLocalBounds().width();
389 EXPECT_GT(required_width, kMinTextDimension);
391 // SizeToFit with limited width.
392 label.SizeToFit(required_width - 1);
393 int constrained_width = label.GetLocalBounds().width();
394 #if defined(OS_WIN)
395 // Canvas::SizeStringInt (in ui/gfx/canvas_linux.cc)
396 // has to be fixed to return the size that fits to given width/height.
397 EXPECT_LT(constrained_width, required_width);
398 #endif
399 EXPECT_GT(constrained_width, kMinTextDimension);
401 // Change the width back to the desire width.
402 label.SizeToFit(required_width);
403 EXPECT_EQ(required_width, label.GetLocalBounds().width());
405 // General tests for GetHeightForWidth.
406 int required_height = label.GetHeightForWidth(required_width);
407 EXPECT_GT(required_height, kMinTextDimension);
408 int height_for_constrained_width = label.GetHeightForWidth(constrained_width);
409 #if defined(OS_WIN)
410 // Canvas::SizeStringInt (in ui/gfx/canvas_linux.cc)
411 // has to be fixed to return the size that fits to given width/height.
412 EXPECT_GT(height_for_constrained_width, required_height);
413 #endif
414 // Using the constrained width or the required_width - 1 should give the
415 // same result for the height because the constrainted width is the tight
416 // width when given "required_width - 1" as the max width.
417 EXPECT_EQ(height_for_constrained_width,
418 label.GetHeightForWidth(required_width - 1));
420 // Test everything with borders.
421 gfx::Insets border(10, 20, 30, 40);
422 label.SetBorder(Border::CreateEmptyBorder(
423 border.top(), border.left(), border.bottom(), border.right()));
425 // SizeToFit and borders.
426 label.SizeToFit(0);
427 int required_width_with_border = label.GetLocalBounds().width();
428 EXPECT_EQ(required_width_with_border, required_width + border.width());
430 // GetHeightForWidth and borders.
431 int required_height_with_border =
432 label.GetHeightForWidth(required_width_with_border);
433 EXPECT_EQ(required_height_with_border, required_height + border.height());
435 // Test that the border width is subtracted before doing the height
436 // calculation. If it is, then the height will grow when width
437 // is shrunk.
438 int height1 = label.GetHeightForWidth(required_width_with_border - 1);
439 #if defined(OS_WIN)
440 // Canvas::SizeStringInt (in ui/gfx/canvas_linux.cc)
441 // has to be fixed to return the size that fits to given width/height.
442 EXPECT_GT(height1, required_height_with_border);
443 #endif
444 EXPECT_EQ(height1, height_for_constrained_width + border.height());
446 // GetPreferredSize and borders.
447 label.SetBounds(0, 0, 0, 0);
448 gfx::Size required_size_with_border = label.GetPreferredSize();
449 EXPECT_EQ(required_size_with_border.height(),
450 required_size.height() + border.height());
451 EXPECT_EQ(required_size_with_border.width(),
452 required_size.width() + border.width());
455 // Verifies if the combination of text eliding and multiline doesn't cause
456 // any side effects of size / layout calculation.
457 TEST_F(LabelTest, MultiLineSizingWithElide) {
458 const base::string16 text =
459 ASCIIToUTF16("A random string\nwith multiple lines\nand returns!");
460 Label label;
461 label.SetFocusable(false);
462 label.SetText(text);
463 label.SetMultiLine(true);
465 gfx::Size required_size = label.GetPreferredSize();
466 EXPECT_GT(required_size.height(), kMinTextDimension);
467 EXPECT_GT(required_size.width(), kMinTextDimension);
468 label.SetBoundsRect(gfx::Rect(required_size));
470 label.SetElideBehavior(gfx::ELIDE_TAIL);
471 EXPECT_EQ(required_size.ToString(), label.GetPreferredSize().ToString());
472 EXPECT_EQ(text, label.GetDisplayTextForTesting());
474 label.SizeToFit(required_size.width() - 1);
475 gfx::Size narrow_size = label.GetPreferredSize();
476 EXPECT_GT(required_size.width(), narrow_size.width());
477 EXPECT_LT(required_size.height(), narrow_size.height());
479 // SetBounds() doesn't change the preferred size.
480 label.SetBounds(0, 0, narrow_size.width() - 1, narrow_size.height());
481 EXPECT_EQ(narrow_size.ToString(), label.GetPreferredSize().ToString());
483 // Paint() doesn't change the preferred size.
484 gfx::Canvas canvas;
485 label.Paint(ui::CanvasPainter(&canvas, 1.f).context());
486 EXPECT_EQ(narrow_size.ToString(), label.GetPreferredSize().ToString());
489 // Check that labels support GetTooltipHandlerForPoint.
490 TEST_F(LabelTest, GetTooltipHandlerForPoint) {
491 // A root view must be defined for this test because the hit-testing
492 // behaviour used by GetTooltipHandlerForPoint() is defined by
493 // the ViewTargeter installed on the root view.
494 Widget widget;
495 Widget::InitParams init_params =
496 CreateParams(Widget::InitParams::TYPE_POPUP);
497 init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
498 init_params.bounds = gfx::Rect(0, 0, 200, 200);
499 widget.Init(init_params);
501 Label label;
502 label.SetText(
503 ASCIIToUTF16("A string that's long enough to exceed the bounds"));
504 label.SetBounds(0, 0, 10, 10);
505 widget.SetContentsView(&label);
507 // By default, labels start out as tooltip handlers.
508 ASSERT_TRUE(label.handles_tooltips());
510 // There's a default tooltip if the text is too big to fit.
511 EXPECT_EQ(&label, label.GetTooltipHandlerForPoint(gfx::Point(2, 2)));
513 // If tooltip handling is disabled, the label should not provide a tooltip
514 // handler.
515 label.SetHandlesTooltips(false);
516 EXPECT_FALSE(label.GetTooltipHandlerForPoint(gfx::Point(2, 2)));
517 label.SetHandlesTooltips(true);
519 // If there's no default tooltip, this should return NULL.
520 label.SetBounds(0, 0, 500, 50);
521 EXPECT_FALSE(label.GetTooltipHandlerForPoint(gfx::Point(2, 2)));
523 label.SetTooltipText(ASCIIToUTF16("a tooltip"));
524 // If the point hits the label, and tooltip is set, the label should be
525 // returned as its tooltip handler.
526 EXPECT_EQ(&label, label.GetTooltipHandlerForPoint(gfx::Point(2, 2)));
528 // Additionally, GetTooltipHandlerForPoint should verify that the label
529 // actually contains the point.
530 EXPECT_FALSE(label.GetTooltipHandlerForPoint(gfx::Point(2, 51)));
531 EXPECT_FALSE(label.GetTooltipHandlerForPoint(gfx::Point(-1, 20)));
533 // Again, if tooltip handling is disabled, the label should not provide a
534 // tooltip handler.
535 label.SetHandlesTooltips(false);
536 EXPECT_FALSE(label.GetTooltipHandlerForPoint(gfx::Point(2, 2)));
537 EXPECT_FALSE(label.GetTooltipHandlerForPoint(gfx::Point(2, 51)));
538 EXPECT_FALSE(label.GetTooltipHandlerForPoint(gfx::Point(-1, 20)));
539 label.SetHandlesTooltips(true);
541 // GetTooltipHandlerForPoint works should work in child bounds.
542 label.SetBounds(2, 2, 10, 10);
543 EXPECT_EQ(&label, label.GetTooltipHandlerForPoint(gfx::Point(1, 5)));
544 EXPECT_FALSE(label.GetTooltipHandlerForPoint(gfx::Point(3, 11)));
547 // Check that label releases its internal layout data when it's unnecessary.
548 TEST_F(LabelTest, ResetRenderTextData) {
549 Label label;
550 label.SetText(ASCIIToUTF16("Example"));
551 label.SizeToPreferredSize();
552 gfx::Size preferred_size = label.GetPreferredSize();
554 EXPECT_NE(gfx::Size().ToString(), preferred_size.ToString());
555 EXPECT_EQ(0u, label.lines_.size());
557 gfx::Canvas canvas(preferred_size, 1.0f, true);
558 label.Paint(ui::CanvasPainter(&canvas, 1.f).context());
559 EXPECT_EQ(1u, label.lines_.size());
561 // Label should recreate its RenderText object when it's invisible, to release
562 // the layout structures and data.
563 label.SetVisible(false);
564 EXPECT_EQ(0u, label.lines_.size());
566 // Querying fields or size information should not recompute the layout
567 // unnecessarily.
568 EXPECT_EQ(ASCIIToUTF16("Example"), label.text());
569 EXPECT_EQ(0u, label.lines_.size());
571 EXPECT_EQ(preferred_size.ToString(), label.GetPreferredSize().ToString());
572 EXPECT_EQ(0u, label.lines_.size());
574 // RenderText data should be back when it's necessary.
575 label.SetVisible(true);
576 EXPECT_EQ(0u, label.lines_.size());
578 label.Paint(ui::CanvasPainter(&canvas, 1.f).context());
579 EXPECT_EQ(1u, label.lines_.size());
581 // Changing layout just resets |lines_|. It'll recover next time it's drawn.
582 label.SetBounds(0, 0, 10, 10);
583 EXPECT_EQ(0u, label.lines_.size());
585 label.Paint(ui::CanvasPainter(&canvas, 1.f).context());
586 EXPECT_EQ(1u, label.lines_.size());
589 #if !defined(OS_MACOSX)
590 TEST_F(LabelTest, MultilineSupportedRenderText) {
591 scoped_ptr<gfx::RenderText> render_text(gfx::RenderText::CreateInstance());
592 ASSERT_TRUE(render_text->MultilineSupported());
594 Label label;
595 label.SetText(ASCIIToUTF16("Example of\nmultilined label"));
596 label.SetMultiLine(true);
597 label.SizeToPreferredSize();
599 gfx::Canvas canvas(label.GetPreferredSize(), 1.0f, true);
600 label.Paint(ui::CanvasPainter(&canvas, 1.f).context());
602 // There's only one 'line', RenderText itself supports multiple lines.
603 EXPECT_EQ(1u, label.lines_.size());
605 #endif
607 TEST_F(LabelFocusTest, FocusBounds) {
608 label()->SetText(ASCIIToUTF16("Example"));
609 gfx::Size normal_size = label()->GetPreferredSize();
611 label()->SetFocusable(true);
612 label()->RequestFocus();
613 gfx::Size focusable_size = label()->GetPreferredSize();
614 // Focusable label requires larger size to paint the focus rectangle.
615 EXPECT_GT(focusable_size.width(), normal_size.width());
616 EXPECT_GT(focusable_size.height(), normal_size.height());
618 label()->SizeToPreferredSize();
619 gfx::Rect focus_bounds = label()->GetFocusBounds();
620 EXPECT_EQ(label()->GetLocalBounds().ToString(), focus_bounds.ToString());
622 label()->SetBounds(
623 0, 0, focusable_size.width() * 2, focusable_size.height() * 2);
624 label()->SetHorizontalAlignment(gfx::ALIGN_LEFT);
625 focus_bounds = label()->GetFocusBounds();
626 EXPECT_EQ(0, focus_bounds.x());
627 EXPECT_LT(0, focus_bounds.y());
628 EXPECT_GT(label()->bounds().bottom(), focus_bounds.bottom());
629 EXPECT_EQ(focusable_size.ToString(), focus_bounds.size().ToString());
631 label()->SetHorizontalAlignment(gfx::ALIGN_RIGHT);
632 focus_bounds = label()->GetFocusBounds();
633 EXPECT_LT(0, focus_bounds.x());
634 EXPECT_EQ(label()->bounds().right(), focus_bounds.right());
635 EXPECT_LT(0, focus_bounds.y());
636 EXPECT_GT(label()->bounds().bottom(), focus_bounds.bottom());
637 EXPECT_EQ(focusable_size.ToString(), focus_bounds.size().ToString());
639 label()->SetHorizontalAlignment(gfx::ALIGN_LEFT);
640 label()->SetElideBehavior(gfx::FADE_TAIL);
641 label()->SetBounds(0, 0, focusable_size.width() / 2, focusable_size.height());
642 focus_bounds = label()->GetFocusBounds();
643 EXPECT_EQ(0, focus_bounds.x());
644 EXPECT_EQ(focusable_size.width() / 2, focus_bounds.width());
647 TEST_F(LabelFocusTest, EmptyLabel) {
648 label()->SetFocusable(true);
649 label()->RequestFocus();
650 label()->SizeToPreferredSize();
652 gfx::Rect focus_bounds = label()->GetFocusBounds();
653 EXPECT_FALSE(focus_bounds.IsEmpty());
654 EXPECT_LT(label()->font_list().GetHeight(), focus_bounds.height());
657 } // namespace views