| OLD | NEW |
| (Empty) |
| 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 | |
| OLD | NEW |