Drive: Add BatchableRequest subclass.
[chromium-blink-merge.git] / ui / views / controls / label_unittest.cc
blobb73083ed7c11567a0a82870c78f33de278cb18b0
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;
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.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) {
195 Label label;
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) {
212 Label label;
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
227 // text.
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
239 // restored.
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) {
293 Label label;
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) {
304 Label label;
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
315 // not called.
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) {
322 Label label;
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) {
330 Label label;
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) {
351 Label label;
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) {
376 Label label;
377 label.SetFocusable(false);
378 label.SetText(
379 ASCIIToUTF16("A random string\nwith multiple lines\nand returns!"));
380 label.SetMultiLine(true);
382 // GetPreferredSize
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.
388 label.SizeToFit(0);
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();
395 #if defined(OS_WIN)
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);
399 #endif
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);
410 #if defined(OS_WIN)
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);
414 #endif
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.
427 label.SizeToFit(0);
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
438 // is shrunk.
439 int height1 = label.GetHeightForWidth(required_width_with_border - 1);
440 #if defined(OS_WIN)
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);
444 #endif
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!");
461 Label label;
462 label.SetFocusable(false);
463 label.SetText(text);
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.
485 gfx::Canvas canvas;
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.
495 Widget widget;
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);
502 Label label;
503 label.SetText(
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
515 // handler.
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
535 // tooltip handler.
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) {
550 Label label;
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
568 // unnecessarily.
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());
595 Label label;
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());
606 #endif
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());
623 label()->SetBounds(
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());
658 } // namespace views