| 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/controls/styled_label.h" | 5 #include "ui/views/controls/styled_label.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <limits> | 9 #include <limits> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 13 #include "ui/gfx/font_list.h" | 13 #include "ui/gfx/font_list.h" |
| 14 #include "ui/gfx/text_elider.h" | 14 #include "ui/gfx/text_elider.h" |
| 15 #include "ui/native_theme/native_theme.h" | 15 #include "ui/native_theme/native_theme.h" |
| 16 #include "ui/views/controls/label.h" | 16 #include "ui/views/controls/label.h" |
| 17 #include "ui/views/controls/link.h" | 17 #include "ui/views/controls/link.h" |
| 18 #include "ui/views/controls/styled_label_listener.h" | 18 #include "ui/views/controls/styled_label_listener.h" |
| 19 | 19 |
| 20 namespace views { | 20 namespace views { |
| 21 | 21 |
| 22 | |
| 23 // Helpers -------------------------------------------------------------------- | 22 // Helpers -------------------------------------------------------------------- |
| 24 | 23 |
| 25 namespace { | 24 namespace { |
| 26 | 25 |
| 26 gfx::Insets FocusBorderInsets(const Label& label) { |
| 27 // StyledLabel never adds a border, so the only Insets added are for the |
| 28 // possible focus ring. |
| 29 DCHECK(label.View::GetInsets().IsEmpty()); |
| 30 return label.GetInsets(); |
| 31 } |
| 32 |
| 27 // Calculates the height of a line of text. Currently returns the height of | 33 // Calculates the height of a line of text. Currently returns the height of |
| 28 // a label. | 34 // a label. |
| 29 int CalculateLineHeight(const gfx::FontList& font_list) { | 35 int CalculateLineHeight(const gfx::FontList& font_list) { |
| 30 Label label; | 36 Label label; |
| 31 label.SetFontList(font_list); | 37 label.SetFontList(font_list); |
| 32 return label.GetPreferredSize().height(); | 38 return label.GetPreferredSize().height(); |
| 33 } | 39 } |
| 34 | 40 |
| 35 std::unique_ptr<Label> CreateLabelRange( | 41 std::unique_ptr<Label> CreateLabelRange( |
| 36 const base::string16& text, | 42 const base::string16& text, |
| 37 const gfx::FontList& font_list, | 43 const gfx::FontList& font_list, |
| 38 const StyledLabel::RangeStyleInfo& style_info, | 44 const StyledLabel::RangeStyleInfo& style_info, |
| 39 views::LinkListener* link_listener) { | 45 views::LinkListener* link_listener) { |
| 40 std::unique_ptr<Label> result; | 46 std::unique_ptr<Label> result; |
| 41 | 47 |
| 42 if (style_info.is_link) { | 48 if (style_info.is_link) { |
| 43 Link* link = new Link(text); | 49 Link* link = new Link(text); |
| 44 link->set_listener(link_listener); | 50 link->set_listener(link_listener); |
| 45 link->SetUnderline((style_info.font_style & gfx::Font::UNDERLINE) != 0); | 51 |
| 52 // StyledLabel makes assumptions about how to inset the entire View based on |
| 53 // the default focus style: If focus rings are not the default, nothing is |
| 54 // inset. So an individual range can't deviate from that. |
| 55 if (Link::GetDefaultFocusStyle() == Link::FocusStyle::UNDERLINE) { |
| 56 // Nothing should (and nothing does) request underlines for links with MD. |
| 57 DCHECK_EQ(0, style_info.font_style & gfx::Font::UNDERLINE); |
| 58 link->SetUnderline(false); // Override what Link::Init() does. |
| 59 } else { |
| 60 link->SetUnderline((style_info.font_style & gfx::Font::UNDERLINE) != 0); |
| 61 } |
| 62 |
| 46 result.reset(link); | 63 result.reset(link); |
| 47 } else { | 64 } else { |
| 48 result.reset(new Label(text)); | 65 result.reset(new Label(text)); |
| 49 } | 66 } |
| 50 | 67 |
| 51 if (style_info.color != SK_ColorTRANSPARENT) | 68 if (style_info.color != SK_ColorTRANSPARENT) |
| 52 result->SetEnabledColor(style_info.color); | 69 result->SetEnabledColor(style_info.color); |
| 53 result->SetFontList(font_list); | 70 result->SetFontList(font_list); |
| 54 | 71 |
| 55 if (!style_info.tooltip.empty()) | 72 if (!style_info.tooltip.empty()) |
| 56 result->SetTooltipText(style_info.tooltip); | 73 result->SetTooltipText(style_info.tooltip); |
| 57 if (style_info.font_style != gfx::Font::NORMAL || | 74 if (style_info.font_style != gfx::Font::NORMAL || |
| 58 style_info.weight != gfx::Font::Weight::NORMAL) { | 75 style_info.weight != gfx::Font::Weight::NORMAL) { |
| 59 result->SetFontList(result->font_list().Derive(0, style_info.font_style, | 76 result->SetFontList(result->font_list().Derive(0, style_info.font_style, |
| 60 style_info.weight)); | 77 style_info.weight)); |
| 61 } | 78 } |
| 62 | 79 |
| 63 return result; | 80 return result; |
| 64 } | 81 } |
| 65 | 82 |
| 66 } // namespace | 83 } // namespace |
| 67 | 84 |
| 68 | |
| 69 // StyledLabel::RangeStyleInfo ------------------------------------------------ | 85 // StyledLabel::RangeStyleInfo ------------------------------------------------ |
| 70 | 86 |
| 71 StyledLabel::RangeStyleInfo::RangeStyleInfo() | 87 StyledLabel::RangeStyleInfo::RangeStyleInfo() |
| 72 : font_style(gfx::Font::NORMAL), | 88 : font_style(gfx::Font::NORMAL), |
| 73 weight(gfx::Font::Weight::NORMAL), | 89 weight(gfx::Font::Weight::NORMAL), |
| 74 color(SK_ColorTRANSPARENT), | 90 color(SK_ColorTRANSPARENT), |
| 75 disable_line_wrapping(false), | 91 disable_line_wrapping(false), |
| 76 is_link(false) {} | 92 is_link(false) {} |
| 77 | 93 |
| 78 StyledLabel::RangeStyleInfo::~RangeStyleInfo() {} | 94 StyledLabel::RangeStyleInfo::~RangeStyleInfo() {} |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 | 187 |
| 172 SetSize(CalculateAndDoLayout(max_width, true)); | 188 SetSize(CalculateAndDoLayout(max_width, true)); |
| 173 } | 189 } |
| 174 | 190 |
| 175 const char* StyledLabel::GetClassName() const { | 191 const char* StyledLabel::GetClassName() const { |
| 176 return kViewClassName; | 192 return kViewClassName; |
| 177 } | 193 } |
| 178 | 194 |
| 179 gfx::Insets StyledLabel::GetInsets() const { | 195 gfx::Insets StyledLabel::GetInsets() const { |
| 180 gfx::Insets insets = View::GetInsets(); | 196 gfx::Insets insets = View::GetInsets(); |
| 197 if (Link::GetDefaultFocusStyle() != Link::FocusStyle::RING) |
| 198 return insets; |
| 181 | 199 |
| 182 // We need a focus border iff we contain a link that will have a focus border. | 200 // We need a focus border iff we contain a link that will have a focus border. |
| 183 // That in turn will be true only if the link is non-empty. | 201 // That in turn will be true only if the link is non-empty. |
| 184 for (StyleRanges::const_iterator i(style_ranges_.begin()); | 202 for (StyleRanges::const_iterator i(style_ranges_.begin()); |
| 185 i != style_ranges_.end(); ++i) { | 203 i != style_ranges_.end(); ++i) { |
| 186 if (i->style_info.is_link && !i->range.is_empty()) { | 204 if (i->style_info.is_link && !i->range.is_empty()) { |
| 187 const gfx::Insets focus_border_padding( | 205 insets += gfx::Insets(Link::kFocusBorderPadding); |
| 188 Label::kFocusBorderPadding, Label::kFocusBorderPadding, | |
| 189 Label::kFocusBorderPadding, Label::kFocusBorderPadding); | |
| 190 insets += focus_border_padding; | |
| 191 break; | 206 break; |
| 192 } | 207 } |
| 193 } | 208 } |
| 194 | 209 |
| 195 return insets; | 210 return insets; |
| 196 } | 211 } |
| 197 | 212 |
| 198 gfx::Size StyledLabel::GetPreferredSize() const { | 213 gfx::Size StyledLabel::GetPreferredSize() const { |
| 199 return calculated_size_; | 214 return calculated_size_; |
| 200 } | 215 } |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 // This chunk is normal text. | 358 // This chunk is normal text. |
| 344 if (position + chunk.size() > range.start()) | 359 if (position + chunk.size() > range.start()) |
| 345 chunk = chunk.substr(0, range.start() - position); | 360 chunk = chunk.substr(0, range.start() - position); |
| 346 label = CreateLabelRange(chunk, font_list_, default_style_info_, this); | 361 label = CreateLabelRange(chunk, font_list_, default_style_info_, this); |
| 347 } | 362 } |
| 348 | 363 |
| 349 if (displayed_on_background_color_set_) | 364 if (displayed_on_background_color_set_) |
| 350 label->SetBackgroundColor(displayed_on_background_color_); | 365 label->SetBackgroundColor(displayed_on_background_color_); |
| 351 label->SetAutoColorReadabilityEnabled(auto_color_readability_enabled_); | 366 label->SetAutoColorReadabilityEnabled(auto_color_readability_enabled_); |
| 352 | 367 |
| 353 // Calculate the size of the optional focus border, and overlap by that | |
| 354 // amount. Otherwise, "<a>link</a>," will render as "link ,". | |
| 355 gfx::Insets focus_border_insets(label->GetInsets()); | |
| 356 focus_border_insets -= label->View::GetInsets(); | |
| 357 const gfx::Size view_size = label->GetPreferredSize(); | 368 const gfx::Size view_size = label->GetPreferredSize(); |
| 358 const gfx::Insets insets = GetInsets(); | 369 const gfx::Insets insets = GetInsets(); |
| 359 label->SetBoundsRect(gfx::Rect( | 370 gfx::Point view_origin(insets.left() + x, |
| 360 gfx::Point( | 371 insets.top() + line * line_height); |
| 361 insets.left() + x - focus_border_insets.left(), | 372 if (Link::GetDefaultFocusStyle() == Link::FocusStyle::RING) { |
| 362 insets.top() + line * line_height - focus_border_insets.top()), | 373 // Calculate the size of the optional focus border, and overlap by that |
| 363 view_size)); | 374 // amount. Otherwise, "<a>link</a>," will render as "link ,". |
| 364 x += view_size.width() - focus_border_insets.width(); | 375 const gfx::Insets focus_border_insets = FocusBorderInsets(*label); |
| 376 view_origin.Offset(-focus_border_insets.left(), |
| 377 -focus_border_insets.top()); |
| 378 label->SetBoundsRect(gfx::Rect(view_origin, view_size)); |
| 379 x += view_size.width() - focus_border_insets.width(); |
| 380 used_width = std::max(used_width, x); |
| 381 total_height = |
| 382 std::max(total_height, label->bounds().bottom() + insets.bottom() - |
| 383 focus_border_insets.bottom()); |
| 384 } else { |
| 385 label->SetBoundsRect(gfx::Rect(view_origin, view_size)); |
| 386 x += view_size.width(); |
| 387 total_height = |
| 388 std::max(total_height, label->bounds().bottom() + insets.bottom()); |
| 389 } |
| 365 used_width = std::max(used_width, x); | 390 used_width = std::max(used_width, x); |
| 366 total_height = | 391 |
| 367 std::max(total_height, label->bounds().bottom() + insets.bottom() - | |
| 368 focus_border_insets.bottom()); | |
| 369 if (!dry_run) | 392 if (!dry_run) |
| 370 AddChildView(label.release()); | 393 AddChildView(label.release()); |
| 371 | 394 |
| 372 // If |gfx::ElideRectangleText| returned more than one substring, that | 395 // If |gfx::ElideRectangleText| returned more than one substring, that |
| 373 // means the whole text did not fit into remaining line width, with text | 396 // means the whole text did not fit into remaining line width, with text |
| 374 // after |susbtring[0]| spilling into next line. If whole |substring[0]| | 397 // after |susbtring[0]| spilling into next line. If whole |substring[0]| |
| 375 // was added to the current line (this may not be the case if part of the | 398 // was added to the current line (this may not be the case if part of the |
| 376 // substring has different style), proceed to the next line. | 399 // substring has different style), proceed to the next line. |
| 377 if (substrings.size() > 1 && chunk.size() == substrings[0].size()) { | 400 if (substrings.size() > 1 && chunk.size() == substrings[0].size()) { |
| 378 x = 0; | 401 x = 0; |
| 379 ++line; | 402 ++line; |
| 380 } | 403 } |
| 381 | 404 |
| 382 remaining_string = remaining_string.substr(chunk.size()); | 405 remaining_string = remaining_string.substr(chunk.size()); |
| 383 } | 406 } |
| 384 | 407 |
| 385 DCHECK_LE(used_width, width); | 408 DCHECK_LE(used_width, width); |
| 386 calculated_size_ = gfx::Size(used_width + GetInsets().width(), total_height); | 409 calculated_size_ = gfx::Size(used_width + GetInsets().width(), total_height); |
| 387 return calculated_size_; | 410 return calculated_size_; |
| 388 } | 411 } |
| 389 | 412 |
| 390 } // namespace views | 413 } // namespace views |
| OLD | NEW |