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 <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
10 #include "ui/base/text/text_elider.h" | 10 #include "ui/base/text/text_elider.h" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 if (!style_info.tooltip.empty()) | 49 if (!style_info.tooltip.empty()) |
50 result->SetTooltipText(style_info.tooltip); | 50 result->SetTooltipText(style_info.tooltip); |
51 if (style_info.font_style != gfx::Font::NORMAL) | 51 if (style_info.font_style != gfx::Font::NORMAL) |
52 result->SetFont(result->font().DeriveFont(0, style_info.font_style)); | 52 result->SetFont(result->font().DeriveFont(0, style_info.font_style)); |
53 | 53 |
54 return scoped_ptr<Label>(result.release()); | 54 return scoped_ptr<Label>(result.release()); |
55 } | 55 } |
56 | 56 |
57 } // namespace | 57 } // namespace |
58 | 58 |
59 | |
60 StyledLabel::RangeStyleInfo::RangeStyleInfo() | 59 StyledLabel::RangeStyleInfo::RangeStyleInfo() |
61 : font_style(gfx::Font::NORMAL), | 60 : font_style(gfx::Font::NORMAL), |
62 color(ui::NativeTheme::instance()->GetSystemColor( | 61 color(ui::NativeTheme::instance()->GetSystemColor( |
63 ui::NativeTheme::kColorId_LabelEnabledColor)), | 62 ui::NativeTheme::kColorId_LabelEnabledColor)), |
64 disable_line_wrapping(false), | 63 disable_line_wrapping(false), |
65 is_link(false) { | 64 is_link(false) {} |
66 } | |
67 | 65 |
68 StyledLabel::RangeStyleInfo::~RangeStyleInfo() {} | 66 StyledLabel::RangeStyleInfo::~RangeStyleInfo() {} |
69 | 67 |
70 // static | 68 // static |
71 StyledLabel::RangeStyleInfo StyledLabel::RangeStyleInfo::CreateForLink() { | 69 StyledLabel::RangeStyleInfo StyledLabel::RangeStyleInfo::CreateForLink() { |
72 RangeStyleInfo result; | 70 RangeStyleInfo result; |
73 result.disable_line_wrapping = true; | 71 result.disable_line_wrapping = true; |
74 result.is_link = true; | 72 result.is_link = true; |
75 result.font_style = gfx::Font::UNDERLINE; | |
76 result.color = Link::GetDefaultEnabledColor(); | 73 result.color = Link::GetDefaultEnabledColor(); |
77 return result; | 74 return result; |
78 } | 75 } |
79 | 76 |
80 bool StyledLabel::StyleRange::operator<( | 77 bool StyledLabel::StyleRange::operator<( |
81 const StyledLabel::StyleRange& other) const { | 78 const StyledLabel::StyleRange& other) const { |
82 // Intentionally reversed so the priority queue is sorted by smallest first. | 79 // Intentionally reversed so the priority queue is sorted by smallest first. |
83 return range.start() > other.range.start(); | 80 return range.start() > other.range.start(); |
84 } | 81 } |
85 | 82 |
86 StyledLabel::StyledLabel(const string16& text, StyledLabelListener* listener) | 83 StyledLabel::StyledLabel(const string16& text, StyledLabelListener* listener) |
87 : listener_(listener), | 84 : listener_(listener), |
88 displayed_on_background_color_set_(false) { | 85 displayed_on_background_color_set_(false) { |
89 TrimWhitespace(text, TRIM_TRAILING, &text_); | 86 TrimWhitespace(text, TRIM_TRAILING, &text_); |
90 } | 87 } |
91 | 88 |
92 StyledLabel::~StyledLabel() {} | 89 StyledLabel::~StyledLabel() {} |
93 | 90 |
94 void StyledLabel::SetText(const string16& text) { | 91 void StyledLabel::SetText(const string16& text) { |
95 text_ = text; | 92 text_ = text; |
96 calculated_size_ = gfx::Size(); | |
97 style_ranges_ = std::priority_queue<StyleRange>(); | 93 style_ranges_ = std::priority_queue<StyleRange>(); |
98 RemoveAllChildViews(true); | 94 RemoveAllChildViews(true); |
99 PreferredSizeChanged(); | 95 PreferredSizeChanged(); |
100 } | 96 } |
101 | 97 |
102 void StyledLabel::AddStyleRange(const ui::Range& range, | 98 void StyledLabel::AddStyleRange(const ui::Range& range, |
103 const RangeStyleInfo& style_info) { | 99 const RangeStyleInfo& style_info) { |
104 DCHECK(!range.is_reversed()); | 100 DCHECK(!range.is_reversed()); |
105 DCHECK(!range.is_empty()); | 101 DCHECK(!range.is_empty()); |
106 DCHECK(ui::Range(0, text_.size()).Contains(range)); | 102 DCHECK(ui::Range(0, text_.size()).Contains(range)); |
107 | 103 |
108 style_ranges_.push(StyleRange(range, style_info)); | 104 style_ranges_.push(StyleRange(range, style_info)); |
109 | 105 |
110 calculated_size_ = gfx::Size(); | |
111 PreferredSizeChanged(); | 106 PreferredSizeChanged(); |
112 } | 107 } |
113 | 108 |
| 109 void StyledLabel::SetDefaultStyle(const RangeStyleInfo& style_info) { |
| 110 default_style_info_ = style_info; |
| 111 PreferredSizeChanged(); |
| 112 } |
| 113 |
114 void StyledLabel::SetDisplayedOnBackgroundColor(SkColor color) { | 114 void StyledLabel::SetDisplayedOnBackgroundColor(SkColor color) { |
115 displayed_on_background_color_ = color; | 115 displayed_on_background_color_ = color; |
116 displayed_on_background_color_set_ = true; | 116 displayed_on_background_color_set_ = true; |
117 } | 117 } |
118 | 118 |
119 gfx::Insets StyledLabel::GetInsets() const { | 119 gfx::Insets StyledLabel::GetInsets() const { |
120 gfx::Insets insets = View::GetInsets(); | 120 gfx::Insets insets = View::GetInsets(); |
121 const gfx::Insets focus_border_padding(1, 1, 1, 1); | 121 const gfx::Insets focus_border_padding(1, 1, 1, 1); |
122 insets += focus_border_padding; | 122 insets += focus_border_padding; |
123 return insets; | 123 return insets; |
124 } | 124 } |
125 | 125 |
126 int StyledLabel::GetHeightForWidth(int w) { | 126 int StyledLabel::GetHeightForWidth(int w) { |
127 if (w != calculated_size_.width()) | 127 if (w != calculated_size_.width()) |
128 calculated_size_ = gfx::Size(w, CalculateAndDoLayout(w, true)); | 128 calculated_size_ = gfx::Size(w, CalculateAndDoLayout(w, true)); |
129 | 129 |
130 return calculated_size_.height(); | 130 return calculated_size_.height(); |
131 } | 131 } |
132 | 132 |
133 void StyledLabel::Layout() { | 133 void StyledLabel::Layout() { |
134 CalculateAndDoLayout(GetLocalBounds().width(), false); | 134 CalculateAndDoLayout(GetLocalBounds().width(), false); |
135 } | 135 } |
136 | 136 |
| 137 void StyledLabel::PreferredSizeChanged() { |
| 138 calculated_size_ = gfx::Size(); |
| 139 View::PreferredSizeChanged(); |
| 140 } |
| 141 |
137 void StyledLabel::LinkClicked(Link* source, int event_flags) { | 142 void StyledLabel::LinkClicked(Link* source, int event_flags) { |
138 if (listener_) | 143 if (listener_) |
139 listener_->StyledLabelLinkClicked(link_targets_[source], event_flags); | 144 listener_->StyledLabelLinkClicked(link_targets_[source], event_flags); |
140 } | 145 } |
141 | 146 |
142 int StyledLabel::CalculateAndDoLayout(int width, bool dry_run) { | 147 int StyledLabel::CalculateAndDoLayout(int width, bool dry_run) { |
143 if (!dry_run) { | 148 if (!dry_run) { |
144 RemoveAllChildViews(true); | 149 RemoveAllChildViews(true); |
145 link_targets_.clear(); | 150 link_targets_.clear(); |
146 } | 151 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 | 234 |
230 if (style_info.is_link && !dry_run) | 235 if (style_info.is_link && !dry_run) |
231 link_targets_[label.get()] = range; | 236 link_targets_[label.get()] = range; |
232 | 237 |
233 if (position + chunk.size() >= range.end()) | 238 if (position + chunk.size() >= range.end()) |
234 style_ranges.pop(); | 239 style_ranges.pop(); |
235 } else { | 240 } else { |
236 // This chunk is normal text. | 241 // This chunk is normal text. |
237 if (position + chunk.size() > range.start()) | 242 if (position + chunk.size() > range.start()) |
238 chunk = chunk.substr(0, range.start() - position); | 243 chunk = chunk.substr(0, range.start() - position); |
239 label = CreateLabelRange(chunk, RangeStyleInfo(), this); | 244 label = CreateLabelRange(chunk, default_style_info_, this); |
240 } | 245 } |
241 | 246 |
242 if (displayed_on_background_color_set_) | 247 if (displayed_on_background_color_set_) |
243 label->SetBackgroundColor(displayed_on_background_color_); | 248 label->SetBackgroundColor(displayed_on_background_color_); |
244 | 249 |
245 // Lay out the views to overlap by 1 pixel to compensate for their border | 250 // Lay out the views to overlap by 1 pixel to compensate for their border |
246 // spacing. Otherwise, "<a>link</a>," will render as "link ,". | 251 // spacing. Otherwise, "<a>link</a>," will render as "link ,". |
247 const int overlap = 1; | 252 const int overlap = 1; |
248 const gfx::Size view_size = label->GetPreferredSize(); | 253 const gfx::Size view_size = label->GetPreferredSize(); |
249 DCHECK_EQ(line_height, view_size.height() - 2 * overlap); | 254 DCHECK_EQ(line_height, view_size.height() - 2 * overlap); |
250 if (!dry_run) { | 255 if (!dry_run) { |
251 label->SetBoundsRect(gfx::Rect( | 256 label->SetBoundsRect(gfx::Rect( |
252 gfx::Point(GetInsets().left() + x - overlap, | 257 gfx::Point(GetInsets().left() + x - overlap, |
253 GetInsets().top() + line * line_height - overlap), | 258 GetInsets().top() + line * line_height - overlap), |
254 view_size)); | 259 view_size)); |
255 AddChildView(label.release()); | 260 AddChildView(label.release()); |
256 } | 261 } |
257 x += view_size.width() - 2 * overlap; | 262 x += view_size.width() - 2 * overlap; |
258 | 263 |
259 remaining_string = remaining_string.substr(chunk.size()); | 264 remaining_string = remaining_string.substr(chunk.size()); |
260 } | 265 } |
261 | 266 |
262 return (line + 1) * line_height + GetInsets().height(); | 267 return (line + 1) * line_height + GetInsets().height(); |
263 } | 268 } |
264 | 269 |
265 } // namespace views | 270 } // namespace views |
OLD | NEW |