Index: ui/views/controls/styled_label.cc |
=================================================================== |
--- ui/views/controls/styled_label.cc (revision 239550) |
+++ ui/views/controls/styled_label.cc (working copy) |
@@ -15,6 +15,9 @@ |
namespace views { |
+ |
+// Helpers -------------------------------------------------------------------- |
+ |
namespace { |
// Calculates the height of a line of text. Currently returns the height of |
@@ -36,12 +39,7 @@ |
link->SetUnderline((style_info.font_style & gfx::Font::UNDERLINE) != 0); |
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); |
+ result.reset(new Label(text)); |
} |
result->SetEnabledColor(style_info.color); |
@@ -56,6 +54,9 @@ |
} // namespace |
+ |
+// StyledLabel::RangeStyleInfo ------------------------------------------------ |
+ |
StyledLabel::RangeStyleInfo::RangeStyleInfo() |
: font_style(gfx::Font::NORMAL), |
color(ui::NativeTheme::instance()->GetSystemColor( |
@@ -74,12 +75,17 @@ |
return result; |
} |
+ |
+// StyledLabel::StyleRange ---------------------------------------------------- |
+ |
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(); |
+ return range.start() < other.range.start(); |
} |
+ |
+// StyledLabel ---------------------------------------------------------------- |
+ |
StyledLabel::StyledLabel(const string16& text, StyledLabelListener* listener) |
: listener_(listener), |
displayed_on_background_color_set_(false), |
@@ -91,7 +97,7 @@ |
void StyledLabel::SetText(const string16& text) { |
text_ = text; |
- style_ranges_ = std::priority_queue<StyleRange>(); |
+ style_ranges_.clear(); |
RemoveAllChildViews(true); |
PreferredSizeChanged(); |
} |
@@ -102,7 +108,10 @@ |
DCHECK(!range.is_empty()); |
DCHECK(gfx::Range(0, text_.size()).Contains(range)); |
- style_ranges_.push(StyleRange(range, style_info)); |
+ // Insert the new range in sorted order. |
+ StyleRanges new_range; |
+ new_range.push_front(StyleRange(range, style_info)); |
+ style_ranges_.merge(new_range); |
PreferredSizeChanged(); |
} |
@@ -119,20 +128,31 @@ |
gfx::Insets StyledLabel::GetInsets() const { |
gfx::Insets insets = View::GetInsets(); |
- const gfx::Insets focus_border_padding(1, 1, 1, 1); |
- insets += focus_border_padding; |
+ |
+ // We need a focus border iff we contain a link that will have a focus border. |
+ // That in turn will be true only if the link is non-empty. |
+ for (StyleRanges::const_iterator i(style_ranges_.begin()); |
+ i != style_ranges_.end(); ++i) { |
+ if (i->style_info.is_link && !i->range.is_empty()) { |
+ const gfx::Insets focus_border_padding( |
+ Label::kFocusBorderPadding, Label::kFocusBorderPadding, |
+ Label::kFocusBorderPadding, Label::kFocusBorderPadding); |
+ insets += focus_border_padding; |
+ break; |
+ } |
+ } |
+ |
return insets; |
} |
int StyledLabel::GetHeightForWidth(int w) { |
if (w != calculated_size_.width()) |
- calculated_size_ = gfx::Size(w, CalculateAndDoLayout(w, true)); |
- |
+ calculated_size_ = CalculateAndDoLayout(w, true); |
return calculated_size_.height(); |
} |
void StyledLabel::Layout() { |
- CalculateAndDoLayout(GetLocalBounds().width(), false); |
+ calculated_size_ = CalculateAndDoLayout(GetLocalBounds().width(), false); |
} |
void StyledLabel::PreferredSizeChanged() { |
@@ -145,7 +165,7 @@ |
listener_->StyledLabelLinkClicked(link_targets_[source], event_flags); |
} |
-int StyledLabel::CalculateAndDoLayout(int width, bool dry_run) { |
+gfx::Size StyledLabel::CalculateAndDoLayout(int width, bool dry_run) { |
if (!dry_run) { |
RemoveAllChildViews(true); |
link_targets_.clear(); |
@@ -153,7 +173,7 @@ |
width -= GetInsets().width(); |
if (width <= 0 || text_.empty()) |
- return 0; |
+ return gfx::Size(); |
const int line_height = CalculateLineHeight(); |
// The index of the line we're on. |
@@ -163,7 +183,7 @@ |
int x = 0; |
string16 remaining_string = text_; |
- std::priority_queue<StyleRange> style_ranges = style_ranges_; |
+ StyleRanges::const_iterator current_range = style_ranges_.begin(); |
// Iterate over the text, creating a bunch of labels and links and laying them |
// out in the appropriate positions. |
@@ -174,8 +194,8 @@ |
TrimWhitespace(remaining_string, TRIM_LEADING, &remaining_string); |
gfx::Range range(gfx::Range::InvalidRange()); |
- if (!style_ranges.empty()) |
- range = style_ranges.top().range; |
+ if (current_range != style_ranges_.end()) |
+ range = current_range->range; |
const size_t position = text_.size() - remaining_string.size(); |
@@ -187,7 +207,7 @@ |
// should be used when eliding text. |
if (position >= range.start()) { |
text_font_list = text_font_list.DeriveFontListWithSizeDeltaAndStyle( |
- 0, style_ranges.top().style_info.font_style); |
+ 0, current_range->style_info.font_style); |
} |
gfx::ElideRectangleText(remaining_string, |
text_font_list, |
@@ -218,7 +238,7 @@ |
scoped_ptr<Label> label; |
if (position >= range.start()) { |
- const RangeStyleInfo& style_info = style_ranges.top().style_info; |
+ const RangeStyleInfo& style_info = current_range->style_info; |
if (style_info.disable_line_wrapping && chunk.size() < range.length() && |
position == range.start() && x != 0) { |
@@ -237,7 +257,7 @@ |
link_targets_[label.get()] = range; |
if (position + chunk.size() >= range.end()) |
- style_ranges.pop(); |
+ ++current_range; |
} else { |
// This chunk is normal text. |
if (position + chunk.size() > range.start()) |
@@ -249,24 +269,26 @@ |
label->SetBackgroundColor(displayed_on_background_color_); |
label->SetAutoColorReadabilityEnabled(auto_color_readability_enabled_); |
- // Lay out the views to overlap by 1 pixel to compensate for their border |
- // spacing. Otherwise, "<a>link</a>," will render as "link ,". |
- const int overlap = 1; |
+ // Calculate the size of the optional focus border, and overlap by that |
+ // amount. Otherwise, "<a>link</a>," will render as "link ,". |
+ gfx::Insets focus_border_insets(label->GetInsets()); |
+ focus_border_insets += -label->View::GetInsets(); |
const gfx::Size view_size = label->GetPreferredSize(); |
- DCHECK_EQ(line_height, view_size.height() - 2 * overlap); |
+ DCHECK_EQ(line_height, view_size.height() - focus_border_insets.height()); |
if (!dry_run) { |
label->SetBoundsRect(gfx::Rect( |
- gfx::Point(GetInsets().left() + x - overlap, |
- GetInsets().top() + line * line_height - overlap), |
+ gfx::Point(GetInsets().left() + x - focus_border_insets.left(), |
+ GetInsets().top() + line * line_height - |
+ focus_border_insets.top()), |
view_size)); |
AddChildView(label.release()); |
} |
- x += view_size.width() - 2 * overlap; |
+ x += view_size.width() - focus_border_insets.width(); |
remaining_string = remaining_string.substr(chunk.size()); |
} |
- return (line + 1) * line_height + GetInsets().height(); |
+ return gfx::Size(width, (line + 1) * line_height + GetInsets().height()); |
} |
} // namespace views |