Index: ui/views/controls/styled_label.cc |
diff --git a/ui/views/controls/styled_label.cc b/ui/views/controls/styled_label.cc |
index f875c7f36c68e6d35158e670d08c27ac97ff2cde..7c6793acc223579473a084cf8fc1beec3f85e620 100644 |
--- a/ui/views/controls/styled_label.cc |
+++ b/ui/views/controls/styled_label.cc |
@@ -23,10 +23,46 @@ int CalculateLineHeight() { |
return label.GetPreferredSize().height(); |
} |
+scoped_ptr<View> CreateLabelRange(const string16& text, |
+ const StyledLabel::RangeStyleInfo& style_info, |
+ views::LinkListener* link_listener) { |
+ scoped_ptr<Label> result; |
+ |
+ if (style_info.linkify) { |
+ Link* link = new Link(text); |
+ link->set_listener(link_listener); |
+ link->SetUnderline(style_info.font_style & gfx::Font::UNDERLINE); |
+ result.reset(link); |
+ } else { |
+ Label* label = new Label(text); |
+ // Give the label a focus border so that its preferred size matches |
+ // links' preferred sizes |
+ label->SetHasFocusBorder(true); |
+ |
+ result.reset(label); |
+ } |
+ |
+ if (!style_info.tooltip.empty()) |
+ result->SetTooltipText(style_info.tooltip); |
+ if (style_info.font_style != gfx::Font::NORMAL) |
+ result->SetFont(result->font().DeriveFont(0, style_info.font_style)); |
Evan Stade
2013/03/18 23:20:50
setting a different font means that the bounds cal
tbarzic
2013/03/19 01:07:34
good point.. is it safe to assume that the font he
Evan Stade
2013/03/19 04:49:29
height and width would both need to stay the same
tonibarzic
2013/03/19 16:27:53
Yes, I understand that width is important for wrap
|
+ |
+ return scoped_ptr<View>(result.release()); |
+} |
+ |
} // namespace |
-bool StyledLabel::LinkRange::operator<( |
- const StyledLabel::LinkRange& other) const { |
+ |
+StyledLabel::RangeStyleInfo::RangeStyleInfo() |
+ : font_style(gfx::Font::NORMAL), |
+ disable_line_wrapping(false), |
+ linkify(false) { |
+} |
+ |
+StyledLabel::RangeStyleInfo::~RangeStyleInfo() {} |
+ |
+bool StyledLabel::StyleRange::operator<( |
+ const StyledLabel::StyleRange& other) const { |
// Intentionally reversed so the priority queue is sorted by smallest first. |
return range.start() > other.range.start(); |
} |
@@ -41,7 +77,25 @@ void StyledLabel::AddLink(const ui::Range& range) { |
DCHECK(!range.is_reversed()); |
DCHECK(!range.is_empty()); |
DCHECK(ui::Range(0, text_.size()).Contains(range)); |
- link_ranges_.push(LinkRange(range)); |
+ |
+ RangeStyleInfo style_info; |
+ style_info.disable_line_wrapping = true; |
+ style_info.linkify = true; |
+ style_info.font_style = gfx::Font::UNDERLINE; |
+ style_ranges_.push(StyleRange(range, style_info)); |
+ |
+ calculated_size_ = gfx::Size(); |
+ InvalidateLayout(); |
+} |
+ |
+void StyledLabel::AddStyleRange(const ui::Range& range, |
+ const RangeStyleInfo& style_info) { |
+ DCHECK(!range.is_reversed()); |
+ DCHECK(!range.is_empty()); |
+ DCHECK(ui::Range(0, text_.size()).Contains(range)); |
+ |
+ style_ranges_.push(StyleRange(range, style_info)); |
+ |
calculated_size_ = gfx::Size(); |
InvalidateLayout(); |
} |
@@ -86,7 +140,7 @@ int StyledLabel::CalculateAndDoLayout(int width, bool dry_run) { |
int x = 0; |
string16 remaining_string = text_; |
- std::priority_queue<LinkRange> link_ranges = link_ranges_; |
+ std::priority_queue<StyleRange> style_ranges = style_ranges_; |
// Iterate over the text, creating a bunch of labels and links and laying them |
// out in the appropriate positions. |
@@ -96,8 +150,8 @@ int StyledLabel::CalculateAndDoLayout(int width, bool dry_run) { |
TrimWhitespace(remaining_string, TRIM_LEADING, &remaining_string); |
ui::Range range(ui::Range::InvalidRange()); |
- if (!link_ranges.empty()) |
- range = link_ranges.top().range; |
+ if (!style_ranges.empty()) |
+ range = style_ranges.top().range; |
const gfx::Rect chunk_bounds(x, 0, width - x, 2 * line_height); |
std::vector<string16> substrings; |
@@ -108,6 +162,10 @@ int StyledLabel::CalculateAndDoLayout(int width, bool dry_run) { |
ui::IGNORE_LONG_WORDS, |
&substrings); |
+ // This happens when only whitespace is left. |
Evan Stade
2013/03/18 23:20:50
it doesn't seem like this should be what happens i
tbarzic
2013/03/19 01:07:34
yeah we could do that, the downside is trimming th
Evan Stade
2013/03/25 22:30:11
but you still don't handle that correctly, because
tbarzic
2013/03/26 21:32:33
ok then, added trimming in the constructor.
note t
|
+ if (substrings.empty()) |
+ break; |
+ |
string16 chunk = substrings[0]; |
if (chunk.empty()) { |
// Nothing fit on this line. Start a new line. If x is 0, there's no room |
@@ -123,31 +181,31 @@ int StyledLabel::CalculateAndDoLayout(int width, bool dry_run) { |
scoped_ptr<View> view; |
const size_t position = text_.size() - remaining_string.size(); |
if (position >= range.start()) { |
- // This chunk is a link. |
- if (chunk.size() < range.length() && x != 0) { |
- // Don't wrap links. Try to fit them entirely on one line. |
+ const RangeStyleInfo& style_info = style_ranges.top().style_info; |
+ |
+ if (style_info.disable_line_wrapping && chunk.size() < range.length() && |
+ position == range.start() && x != 0) { |
+ // If the chunk should not be wrapped, try to fit it entirely on the |
+ // next line. |
x = 0; |
line++; |
continue; |
} |
- chunk = chunk.substr(0, range.length()); |
- Link* link = new Link(chunk); |
- link->set_listener(this); |
- if (!dry_run) |
- link_targets_[link] = range; |
- view.reset(link); |
- link_ranges.pop(); |
+ chunk = chunk.substr(0, std::min(chunk.size(), range.end() - position)); |
+ |
+ view = CreateLabelRange(chunk, style_info, this); |
+ |
+ if (style_info.linkify && !dry_run) |
+ link_targets_[view.get()] = range; |
+ |
+ if (position + chunk.size() >= range.end()) |
+ style_ranges.pop(); |
} else { |
// This chunk is normal text. |
if (position + chunk.size() > range.start()) |
chunk = chunk.substr(0, range.start() - position); |
- |
- Label* label = new Label(chunk); |
- // Give the label a focus border so that its preferred size matches |
- // links' preferred sizes. |
- label->SetHasFocusBorder(true); |
- view.reset(label); |
+ view = CreateLabelRange(chunk, RangeStyleInfo(), this); |
} |
// Lay out the views to overlap by 1 pixel to compensate for their border |