| 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
|
|
|