Chromium Code Reviews| 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,14 +75,20 @@ |
| 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), |
| + is_drawn_(false), |
| displayed_on_background_color_set_(false), |
| auto_color_readability_enabled_(true) { |
| TrimWhitespace(text, TRIM_TRAILING, &text_); |
| @@ -91,7 +98,7 @@ |
| void StyledLabel::SetText(const string16& text) { |
| text_ = text; |
| - style_ranges_ = std::priority_queue<StyleRange>(); |
| + style_ranges_.clear(); |
| RemoveAllChildViews(true); |
| PreferredSizeChanged(); |
| } |
| @@ -102,7 +109,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 +129,34 @@ |
| 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 and we are drawn. |
| + is_drawn_ = IsDrawn(); |
|
sky
2013/12/10 17:18:00
Similar to my comment in Label I think you should
|
| + if (is_drawn_) { |
| + 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() { |
| @@ -140,12 +164,23 @@ |
| View::PreferredSizeChanged(); |
| } |
| +void StyledLabel::ViewHierarchyChanged( |
| + const ViewHierarchyChangedDetails& details) { |
| + if (IsDrawn() != is_drawn_) |
| + PreferredSizeChanged(); |
| +} |
| + |
| +void StyledLabel::VisibilityChanged(View* starting_from, bool is_visible) { |
| + if (IsDrawn() != is_drawn_) |
| + PreferredSizeChanged(); |
| +} |
| + |
| void StyledLabel::LinkClicked(Link* source, int event_flags) { |
| if (listener_) |
| 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 +188,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 +198,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 +209,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 +222,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 +253,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 +272,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 +284,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 |