OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/views/corewm/tooltip_aura.h" | 5 #include "ui/views/corewm/tooltip_aura.h" |
6 | 6 |
| 7 #include "base/strings/string_split.h" |
7 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
8 #include "ui/aura/test/aura_test_base.h" | 9 #include "ui/aura/test/aura_test_base.h" |
9 #include "ui/base/resource/resource_bundle.h" | |
10 #include "ui/gfx/font_list.h" | 10 #include "ui/gfx/font_list.h" |
11 #include "ui/gfx/text_elider.h" | 11 #include "ui/gfx/text_elider.h" |
12 #include "ui/gfx/text_utils.h" | 12 #include "ui/gfx/text_utils.h" |
13 | 13 |
14 using base::ASCIIToUTF16; | |
15 using base::UTF8ToUTF16; | |
16 | |
17 namespace views { | 14 namespace views { |
18 namespace corewm { | 15 namespace corewm { |
19 | 16 |
| 17 namespace { |
| 18 |
| 19 // Generates a string consisting of repeated copies of |word| separated by |
| 20 // |separator|. The string will be long enough to fill |num_lines| lines wrapped |
| 21 // at |max_width| pixels. |
| 22 base::string16 FillLines(const base::string16& word, |
| 23 const base::string16& separator, |
| 24 int max_width, |
| 25 int num_lines, |
| 26 const gfx::FontList& font_list) { |
| 27 base::string16 text; |
| 28 for (int lines = 0; lines < num_lines; ++lines) { |
| 29 base::string16 line = word; |
| 30 while (gfx::GetStringWidth(line + separator + word, font_list) <= max_width) |
| 31 line += separator + word; |
| 32 |
| 33 if (lines != 0) |
| 34 text += separator; |
| 35 text += line; |
| 36 } |
| 37 return text; |
| 38 } |
| 39 |
| 40 } // namespace |
| 41 |
20 typedef aura::test::AuraTestBase TooltipAuraTest; | 42 typedef aura::test::AuraTestBase TooltipAuraTest; |
21 | 43 |
22 TEST_F(TooltipAuraTest, TrimTooltipToFitTests) { | 44 TEST_F(TooltipAuraTest, TrimTooltipToFit) { |
23 const gfx::FontList font_list; | 45 const gfx::FontList kFontList; |
24 const int max_width = 4000; | 46 const gfx::Size kMaxSize(2000, 1500); |
25 base::string16 tooltip; | 47 const base::string16 kWord = base::ASCIIToUTF16("word"); |
26 int width, line_count, expect_lines; | 48 const base::string16 kSpace = base::ASCIIToUTF16(" "); |
27 int max_pixel_width = 400; // copied from constants in tooltip_controller.cc | 49 const base::string16 kNewline = base::ASCIIToUTF16("\n"); |
28 int max_lines = 10; // copied from constants in tooltip_controller.cc | |
29 size_t tooltip_len; | |
30 | 50 |
31 // Error in computed size vs. expected size should not be greater than the | 51 // Long tooltips should wrap to the next line. |
32 // size of the longest word. | 52 base::string16 text = FillLines(kWord, kSpace, |
33 int error_in_pixel_width = gfx::GetStringWidth(ASCIIToUTF16("tooltip"), | 53 TooltipAura::kPreferredWidthPixels, 1, kFontList); |
34 font_list); | 54 text += kSpace + kWord; |
| 55 // The last space should be replaced by a newline. |
| 56 base::string16 expected_text = text; |
| 57 expected_text[expected_text.find_last_of(L' ')] = L'\n'; |
| 58 int width = 0, line_count = 0; |
| 59 TooltipAura::TrimTooltipToFit(kFontList, kMaxSize, &text, &width, |
| 60 &line_count); |
| 61 EXPECT_LE(width, TooltipAura::kPreferredWidthPixels); |
| 62 EXPECT_EQ(2, line_count); |
| 63 EXPECT_EQ(expected_text, text); |
35 | 64 |
36 // Long tooltips should wrap to next line | 65 // The tooltip should be truncated to the number of lines that fit in the |
37 tooltip.clear(); | 66 // passed-in maximum size. |
38 width = line_count = -1; | 67 int max_lines = kMaxSize.height() / kFontList.GetHeight(); |
39 expect_lines = 3; | 68 text = FillLines( |
40 for (; gfx::GetStringWidth(tooltip, font_list) <= | 69 kWord, kSpace, TooltipAura::kPreferredWidthPixels, max_lines, kFontList); |
41 (expect_lines - 1) * max_pixel_width;) | 70 text += kSpace + kWord; |
42 tooltip.append(ASCIIToUTF16("This is part of the tooltip")); | 71 size_t orig_length = text.size(); |
43 tooltip_len = tooltip.length(); | 72 TooltipAura::TrimTooltipToFit(kFontList, kMaxSize, &text, &width, |
44 TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, | |
45 &line_count); | 73 &line_count); |
46 EXPECT_NEAR(max_pixel_width, width, error_in_pixel_width); | 74 EXPECT_LE(width, TooltipAura::kPreferredWidthPixels); |
47 EXPECT_EQ(expect_lines, line_count); | 75 EXPECT_EQ(max_lines, line_count); |
48 EXPECT_EQ(tooltip_len + expect_lines - 1, tooltip.length()); | 76 EXPECT_LT(text.size(), orig_length); |
49 | 77 |
50 // More than |max_lines| lines should get truncated at 10 lines. | 78 // When the original string contains two long lines, each line should be |
51 tooltip.clear(); | 79 // wrapped individually. |
52 width = line_count = -1; | 80 base::string16 line = FillLines( |
53 expect_lines = 13; | 81 kWord, kSpace, TooltipAura::kPreferredWidthPixels, 1, kFontList); |
54 for (; gfx::GetStringWidth(tooltip, font_list) <= | 82 text = line + kSpace + kWord + kNewline + line + kSpace + kWord; |
55 (expect_lines - 1) * max_pixel_width;) | 83 orig_length = text.size(); |
56 tooltip.append(ASCIIToUTF16("This is part of the tooltip")); | 84 TooltipAura::TrimTooltipToFit(kFontList, kMaxSize, &text, &width, |
57 TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, | |
58 &line_count); | 85 &line_count); |
59 EXPECT_NEAR(max_pixel_width, width, error_in_pixel_width); | 86 EXPECT_LE(width, TooltipAura::kPreferredWidthPixels); |
60 EXPECT_EQ(max_lines, line_count); | 87 EXPECT_EQ(4, line_count); |
| 88 std::vector<base::string16> lines; |
| 89 base::SplitString(text, L'\n', &lines); |
| 90 ASSERT_EQ(4U, lines.size()); |
| 91 EXPECT_EQ(line, lines[0]); |
| 92 EXPECT_EQ(kWord, lines[1]); |
| 93 EXPECT_EQ(line, lines[2]); |
| 94 EXPECT_EQ(kWord, lines[3]); |
61 | 95 |
62 // Long multi line tooltips should wrap individual lines. | 96 // The preferred width should be exceeded if there's a long word. |
63 tooltip.clear(); | 97 text = FillLines(kWord, base::string16(), |
64 width = line_count = -1; | 98 TooltipAura::kPreferredWidthPixels, 1, kFontList); |
65 expect_lines = 4; | 99 text += kWord; |
66 for (; gfx::GetStringWidth(tooltip, font_list) <= | 100 expected_text = text; |
67 (expect_lines - 2) * max_pixel_width;) | 101 TooltipAura::TrimTooltipToFit(kFontList, kMaxSize, &text, &width, |
68 tooltip.append(ASCIIToUTF16("This is part of the tooltip")); | |
69 tooltip.insert(tooltip.length() / 2, ASCIIToUTF16("\n")); | |
70 tooltip_len = tooltip.length(); | |
71 TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, | |
72 &line_count); | 102 &line_count); |
73 EXPECT_NEAR(max_pixel_width, width, error_in_pixel_width); | 103 EXPECT_GT(width, TooltipAura::kPreferredWidthPixels); |
74 EXPECT_EQ(expect_lines, line_count); | 104 EXPECT_LT(width, kMaxSize.width()); |
75 // We may have inserted the line break above near a space which will get | 105 EXPECT_EQ(1, line_count); |
76 // trimmed. Hence we may be off by 1 in the final tooltip length calculation. | 106 EXPECT_EQ(expected_text, text); |
77 EXPECT_NEAR(tooltip_len + expect_lines - 2, tooltip.length(), 1); | |
78 | 107 |
79 #if !defined(OS_WIN) | 108 // If a word exceeds the maximum width, it should be elided. |
80 // Tooltip with really long word gets elided. | 109 const base::string16 kLongWord = |
81 tooltip.clear(); | 110 FillLines(kWord, base::string16(), kMaxSize.width(), 1, kFontList) + |
82 width = line_count = -1; | 111 kWord; |
83 tooltip = UTF8ToUTF16(std::string('a', max_pixel_width)); | 112 text = kLongWord; |
84 TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, | 113 expected_text = gfx::ElideText( |
| 114 text, kFontList, kMaxSize.width(), gfx::ELIDE_TAIL); |
| 115 TooltipAura::TrimTooltipToFit(kFontList, kMaxSize, &text, &width, |
85 &line_count); | 116 &line_count); |
86 EXPECT_NEAR(max_pixel_width, width, 5); | 117 EXPECT_GT(width, TooltipAura::kPreferredWidthPixels); |
| 118 EXPECT_LE(width, kMaxSize.width()); |
87 EXPECT_EQ(1, line_count); | 119 EXPECT_EQ(1, line_count); |
88 EXPECT_EQ(gfx::ElideText(UTF8ToUTF16(std::string('a', max_pixel_width)), | 120 EXPECT_EQ(expected_text, text); |
89 font_list, max_pixel_width, gfx::ELIDE_TAIL), | |
90 tooltip); | |
91 #endif | |
92 | 121 |
93 // Normal small tooltip should stay as is. | 122 // When a long word makes the tooltip wider than the preferred width, |
94 tooltip.clear(); | 123 // other lines should be wrapped at the new, longer size. |
95 width = line_count = -1; | 124 text = FillLines(kWord, kSpace, kMaxSize.width(), 1, kFontList); |
96 tooltip = ASCIIToUTF16("Small Tooltip"); | 125 text += kNewline + kLongWord; |
97 TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, | 126 text += kNewline + FillLines(kWord, kSpace, kMaxSize.width(), 1, kFontList); |
| 127 TooltipAura::TrimTooltipToFit(kFontList, kMaxSize, &text, &width, |
98 &line_count); | 128 &line_count); |
99 EXPECT_EQ(gfx::GetStringWidth(ASCIIToUTF16("Small Tooltip"), font_list), | 129 EXPECT_GT(width, TooltipAura::kPreferredWidthPixels); |
100 width); | 130 EXPECT_LE(width, kMaxSize.width()); |
| 131 EXPECT_EQ(3, line_count); |
| 132 |
| 133 // A normal small tooltip should stay as is. |
| 134 text = base::ASCIIToUTF16("Small Tooltip"); |
| 135 expected_text = text; |
| 136 TooltipAura::TrimTooltipToFit(kFontList, kMaxSize, &text, &width, |
| 137 &line_count); |
| 138 EXPECT_LE(width, TooltipAura::kPreferredWidthPixels); |
101 EXPECT_EQ(1, line_count); | 139 EXPECT_EQ(1, line_count); |
102 EXPECT_EQ(ASCIIToUTF16("Small Tooltip"), tooltip); | 140 EXPECT_EQ(expected_text, text); |
103 | 141 |
104 // Normal small multi-line tooltip should stay as is. | 142 // A normal small multi-line tooltip should stay as is. |
105 tooltip.clear(); | 143 text = base::ASCIIToUTF16("Multi line\nTooltip"); |
106 width = line_count = -1; | 144 expected_text = text; |
107 tooltip = ASCIIToUTF16("Multi line\nTooltip"); | 145 TooltipAura::TrimTooltipToFit(kFontList, kMaxSize, &text, &width, |
108 TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, | |
109 &line_count); | 146 &line_count); |
110 int expected_width = gfx::GetStringWidth(ASCIIToUTF16("Multi line"), | 147 EXPECT_LE(width, TooltipAura::kPreferredWidthPixels); |
111 font_list); | |
112 expected_width = std::max(expected_width, | |
113 gfx::GetStringWidth(ASCIIToUTF16("Tooltip"), | |
114 font_list)); | |
115 EXPECT_EQ(expected_width, width); | |
116 EXPECT_EQ(2, line_count); | 148 EXPECT_EQ(2, line_count); |
117 EXPECT_EQ(ASCIIToUTF16("Multi line\nTooltip"), tooltip); | 149 EXPECT_EQ(expected_text, text); |
118 | 150 |
119 // Whitespaces in tooltips are preserved. | 151 // Whitespace in the middle of tooltips should be preserved. |
120 tooltip.clear(); | 152 text = base::ASCIIToUTF16("Small Tool t\tip"); |
121 width = line_count = -1; | 153 expected_text = text; |
122 tooltip = ASCIIToUTF16("Small Tool t\tip"); | 154 TooltipAura::TrimTooltipToFit(kFontList, kMaxSize, &text, &width, |
123 TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, | |
124 &line_count); | 155 &line_count); |
125 EXPECT_EQ(gfx::GetStringWidth(ASCIIToUTF16("Small Tool t\tip"), font_list), | 156 EXPECT_LE(width, TooltipAura::kPreferredWidthPixels); |
126 width); | |
127 EXPECT_EQ(1, line_count); | 157 EXPECT_EQ(1, line_count); |
128 EXPECT_EQ(ASCIIToUTF16("Small Tool t\tip"), tooltip); | 158 EXPECT_EQ(expected_text, text); |
129 } | 159 } |
130 | 160 |
131 } // namespace corewm | 161 } // namespace corewm |
132 } // namespace views | 162 } // namespace views |
OLD | NEW |