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/gfx/text_elider.h" | 10 #include "ui/gfx/text_elider.h" |
11 #include "ui/native_theme/native_theme.h" | 11 #include "ui/native_theme/native_theme.h" |
12 #include "ui/views/controls/label.h" | 12 #include "ui/views/controls/label.h" |
13 #include "ui/views/controls/link.h" | 13 #include "ui/views/controls/link.h" |
14 #include "ui/views/controls/styled_label_listener.h" | 14 #include "ui/views/controls/styled_label_listener.h" |
15 | 15 |
16 namespace views { | 16 namespace views { |
17 | 17 |
18 namespace { | 18 namespace { |
19 | 19 |
20 // Calculates the height of a line of text. Currently returns the height of | 20 // Calculates the height of a line of text. Currently returns the height of |
21 // a label. | 21 // a label. |
22 int CalculateLineHeight() { | 22 int CalculateLineHeight() { |
23 Label label; | 23 Label label; |
24 return label.GetPreferredSize().height(); | 24 return label.GetPreferredSize().height(); |
25 } | 25 } |
26 | 26 |
27 scoped_ptr<Label> CreateLabelRange( | 27 scoped_ptr<Label> CreateLabelRange( |
28 const string16& text, | 28 const base::string16& text, |
29 const StyledLabel::RangeStyleInfo& style_info, | 29 const StyledLabel::RangeStyleInfo& style_info, |
30 views::LinkListener* link_listener) { | 30 views::LinkListener* link_listener) { |
31 scoped_ptr<Label> result; | 31 scoped_ptr<Label> result; |
32 | 32 |
33 if (style_info.is_link) { | 33 if (style_info.is_link) { |
34 Link* link = new Link(text); | 34 Link* link = new Link(text); |
35 link->set_listener(link_listener); | 35 link->set_listener(link_listener); |
36 link->SetUnderline((style_info.font_style & gfx::Font::UNDERLINE) != 0); | 36 link->SetUnderline((style_info.font_style & gfx::Font::UNDERLINE) != 0); |
37 result.reset(link); | 37 result.reset(link); |
38 } else { | 38 } else { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 result.color = Link::GetDefaultEnabledColor(); | 73 result.color = Link::GetDefaultEnabledColor(); |
74 return result; | 74 return result; |
75 } | 75 } |
76 | 76 |
77 bool StyledLabel::StyleRange::operator<( | 77 bool StyledLabel::StyleRange::operator<( |
78 const StyledLabel::StyleRange& other) const { | 78 const StyledLabel::StyleRange& other) const { |
79 // Intentionally reversed so the priority queue is sorted by smallest first. | 79 // Intentionally reversed so the priority queue is sorted by smallest first. |
80 return range.start() > other.range.start(); | 80 return range.start() > other.range.start(); |
81 } | 81 } |
82 | 82 |
83 StyledLabel::StyledLabel(const string16& text, StyledLabelListener* listener) | 83 StyledLabel::StyledLabel(const base::string16& text, |
| 84 StyledLabelListener* listener) |
84 : listener_(listener), | 85 : listener_(listener), |
85 displayed_on_background_color_set_(false), | 86 displayed_on_background_color_set_(false), |
86 auto_color_readability_enabled_(true) { | 87 auto_color_readability_enabled_(true) { |
87 TrimWhitespace(text, TRIM_TRAILING, &text_); | 88 TrimWhitespace(text, TRIM_TRAILING, &text_); |
88 } | 89 } |
89 | 90 |
90 StyledLabel::~StyledLabel() {} | 91 StyledLabel::~StyledLabel() {} |
91 | 92 |
92 void StyledLabel::SetText(const string16& text) { | 93 void StyledLabel::SetText(const base::string16& text) { |
93 text_ = text; | 94 text_ = text; |
94 style_ranges_ = std::priority_queue<StyleRange>(); | 95 style_ranges_ = std::priority_queue<StyleRange>(); |
95 RemoveAllChildViews(true); | 96 RemoveAllChildViews(true); |
96 PreferredSizeChanged(); | 97 PreferredSizeChanged(); |
97 } | 98 } |
98 | 99 |
99 void StyledLabel::AddStyleRange(const gfx::Range& range, | 100 void StyledLabel::AddStyleRange(const gfx::Range& range, |
100 const RangeStyleInfo& style_info) { | 101 const RangeStyleInfo& style_info) { |
101 DCHECK(!range.is_reversed()); | 102 DCHECK(!range.is_reversed()); |
102 DCHECK(!range.is_empty()); | 103 DCHECK(!range.is_empty()); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 if (width <= 0 || text_.empty()) | 156 if (width <= 0 || text_.empty()) |
156 return 0; | 157 return 0; |
157 | 158 |
158 const int line_height = CalculateLineHeight(); | 159 const int line_height = CalculateLineHeight(); |
159 // The index of the line we're on. | 160 // The index of the line we're on. |
160 int line = 0; | 161 int line = 0; |
161 // The x position (in pixels) of the line we're on, relative to content | 162 // The x position (in pixels) of the line we're on, relative to content |
162 // bounds. | 163 // bounds. |
163 int x = 0; | 164 int x = 0; |
164 | 165 |
165 string16 remaining_string = text_; | 166 base::string16 remaining_string = text_; |
166 std::priority_queue<StyleRange> style_ranges = style_ranges_; | 167 std::priority_queue<StyleRange> style_ranges = style_ranges_; |
167 | 168 |
168 // Iterate over the text, creating a bunch of labels and links and laying them | 169 // Iterate over the text, creating a bunch of labels and links and laying them |
169 // out in the appropriate positions. | 170 // out in the appropriate positions. |
170 while (!remaining_string.empty()) { | 171 while (!remaining_string.empty()) { |
171 // Don't put whitespace at beginning of a line with an exception for the | 172 // Don't put whitespace at beginning of a line with an exception for the |
172 // first line (so the text's leading whitespace is respected). | 173 // first line (so the text's leading whitespace is respected). |
173 if (x == 0 && line > 0) | 174 if (x == 0 && line > 0) |
174 TrimWhitespace(remaining_string, TRIM_LEADING, &remaining_string); | 175 TrimWhitespace(remaining_string, TRIM_LEADING, &remaining_string); |
175 | 176 |
176 gfx::Range range(gfx::Range::InvalidRange()); | 177 gfx::Range range(gfx::Range::InvalidRange()); |
177 if (!style_ranges.empty()) | 178 if (!style_ranges.empty()) |
178 range = style_ranges.top().range; | 179 range = style_ranges.top().range; |
179 | 180 |
180 const size_t position = text_.size() - remaining_string.size(); | 181 const size_t position = text_.size() - remaining_string.size(); |
181 | 182 |
182 const gfx::Rect chunk_bounds(x, 0, width - x, 2 * line_height); | 183 const gfx::Rect chunk_bounds(x, 0, width - x, 2 * line_height); |
183 std::vector<string16> substrings; | 184 std::vector<base::string16> substrings; |
184 gfx::FontList text_font_list; | 185 gfx::FontList text_font_list; |
185 // If the start of the remaining text is inside a styled range, the font | 186 // If the start of the remaining text is inside a styled range, the font |
186 // style may differ from the base font. The font specified by the range | 187 // style may differ from the base font. The font specified by the range |
187 // should be used when eliding text. | 188 // should be used when eliding text. |
188 if (position >= range.start()) { | 189 if (position >= range.start()) { |
189 text_font_list = text_font_list.DeriveFontListWithSizeDeltaAndStyle( | 190 text_font_list = text_font_list.DeriveFontListWithSizeDeltaAndStyle( |
190 0, style_ranges.top().style_info.font_style); | 191 0, style_ranges.top().style_info.font_style); |
191 } | 192 } |
192 gfx::ElideRectangleText(remaining_string, | 193 gfx::ElideRectangleText(remaining_string, |
193 text_font_list, | 194 text_font_list, |
194 chunk_bounds.width(), | 195 chunk_bounds.width(), |
195 chunk_bounds.height(), | 196 chunk_bounds.height(), |
196 gfx::IGNORE_LONG_WORDS, | 197 gfx::IGNORE_LONG_WORDS, |
197 &substrings); | 198 &substrings); |
198 | 199 |
199 DCHECK(!substrings.empty()); | 200 DCHECK(!substrings.empty()); |
200 string16 chunk = substrings[0]; | 201 base::string16 chunk = substrings[0]; |
201 if (chunk.empty()) { | 202 if (chunk.empty()) { |
202 // Nothing fits on this line. Start a new line. | 203 // Nothing fits on this line. Start a new line. |
203 // If x is 0, first line may have leading whitespace that doesn't fit in a | 204 // If x is 0, first line may have leading whitespace that doesn't fit in a |
204 // single line, so try trimming those. Otherwise there is no room for | 205 // single line, so try trimming those. Otherwise there is no room for |
205 // anything; abort. | 206 // anything; abort. |
206 if (x == 0) { | 207 if (x == 0) { |
207 if (line == 0) { | 208 if (line == 0) { |
208 TrimWhitespace(remaining_string, TRIM_LEADING, &remaining_string); | 209 TrimWhitespace(remaining_string, TRIM_LEADING, &remaining_string); |
209 continue; | 210 continue; |
210 } | 211 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 } | 264 } |
264 x += view_size.width() - 2 * overlap; | 265 x += view_size.width() - 2 * overlap; |
265 | 266 |
266 remaining_string = remaining_string.substr(chunk.size()); | 267 remaining_string = remaining_string.substr(chunk.size()); |
267 } | 268 } |
268 | 269 |
269 return (line + 1) * line_height + GetInsets().height(); | 270 return (line + 1) * line_height + GetInsets().height(); |
270 } | 271 } |
271 | 272 |
272 } // namespace views | 273 } // namespace views |
OLD | NEW |