Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(424)

Unified Diff: ui/message_center/views/bounded_label.cc

Issue 12742005: Added text line limits to collapsed and expanded notifications. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/message_center/views/bounded_label.cc
diff --git a/ui/message_center/views/bounded_label.cc b/ui/message_center/views/bounded_label.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f9c71b312a67d7f7e7a64cc4923a5209d117de6a
--- /dev/null
+++ b/ui/message_center/views/bounded_label.cc
@@ -0,0 +1,157 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/message_center/views/bounded_label.h"
+
+#include <limits>
+
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "ui/base/text/text_elider.h"
+#include "ui/gfx/canvas.h"
+
+namespace message_center {
+
+BoundedLabel::BoundedLabel(string16 text, size_t max_lines)
+ : views::Label(text, gfx::Font()) {
+ Init(max_lines);
+}
+
+BoundedLabel::BoundedLabel(string16 text, gfx::Font font, size_t max_lines)
+ : views::Label(text, font) {
+ Init(max_lines);
+}
+
+BoundedLabel::~BoundedLabel() {
+}
+
+void BoundedLabel::SetMaxLines(size_t lines) {
+ is_preferred_lines_valid_ = false;
+ is_text_size_valid_ = false;
+ max_lines_ = lines;
+}
+
+size_t BoundedLabel::GetMaxLines() {
+ return max_lines_;
+}
+
+size_t BoundedLabel::GetPreferredLines() {
+ if (!is_preferred_lines_valid_) {
+ int wrap_width = width() - GetInsets().width();
+ int unlimited_lines = std::numeric_limits<size_t>::max();
+ preferred_lines_ = SplitLines(wrap_width, unlimited_lines).size();
+ is_preferred_lines_valid_ = true;
+ }
+ return preferred_lines_;
+}
+
+int BoundedLabel::GetHeightForWidth(int width) {
+ gfx::Insets insets = GetInsets();
+ return GetTextHeightForWidth(width - insets.width()) + insets.height();
+}
+
+gfx::Size BoundedLabel::GetTextSize() const {
+ if (!is_text_size_valid_) {
+ text_size_.set_width(width() - GetInsets().width());
+ text_size_.set_height(GetTextHeightForWidth(text_size_.width()));
+ is_text_size_valid_ = true;
+ }
+ return text_size_;
+}
+
+void BoundedLabel::OnBoundsChanged(const gfx::Rect& previous_bounds) {
+ is_preferred_lines_valid_ = false;
+ is_text_size_valid_ = false;
+}
+
+void BoundedLabel::PaintText(gfx::Canvas* canvas,
+ const string16& paint_text,
+ const gfx::Rect& text_bounds,
+ int flags) {
+ gfx::Insets insets = GetInsets();
+ gfx::Rect bounds(gfx::Point(insets.left(), insets.top()), GetTextSize());
+ string16 text = JoinString(SplitLines(bounds.width(), max_lines_), '\n');
+ views::Label::PaintText(canvas, text, bounds, GetTextFlags());
+}
+
+void BoundedLabel::Init(size_t max_lines) {
+ SetMultiLine(true);
+ SetAllowCharacterBreak(true);
+ SetElideBehavior(views::Label::ELIDE_AT_END);
+ max_lines_ = max_lines;
+ is_preferred_lines_valid_ = false;
+ is_text_size_valid_ = false;
+}
+
+int BoundedLabel::GetTextFlags() const {
+ int flags = gfx::Canvas::MULTI_LINE | gfx::Canvas::CHARACTER_BREAK;
+
+ // We can't use subpixel rendering if the background is non-opaque.
+ if (SkColorGetA(background_color()) != 0xFF)
+ flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING;
+
+ if (directionality_mode() == AUTO_DETECT_DIRECTIONALITY) {
+ base::i18n::TextDirection direction =
+ base::i18n::GetFirstStrongCharacterDirection(text());
+ if (direction == base::i18n::RIGHT_TO_LEFT)
+ flags |= gfx::Canvas::FORCE_RTL_DIRECTIONALITY;
+ else
+ flags |= gfx::Canvas::FORCE_LTR_DIRECTIONALITY;
+ }
+
+ switch (horizontal_alignment()) {
+ case gfx::ALIGN_LEFT:
+ flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
+ break;
+ case gfx::ALIGN_CENTER:
+ flags |= gfx::Canvas::TEXT_ALIGN_CENTER;
+ break;
+ case gfx::ALIGN_RIGHT:
+ flags |= gfx::Canvas::TEXT_ALIGN_RIGHT;
+ break;
+ }
+
+ return flags;
+}
+
+int BoundedLabel::GetTextHeightForWidth(int width) const {
+ int height = font().GetHeight();
+ width = std::max(width, 0);
+ string16 text = JoinString(SplitLines(width, max_lines_), '\n');
+ gfx::Canvas::SizeStringInt(text, font(), &width, &height, GetTextFlags());
+ return height;
+}
+
+std::vector<string16> BoundedLabel::SplitLines(int width,
+ size_t max_lines) const {
+ // Adjust max_lines so (max_lines + 1) * line_height <= INT_MAX, then use the
+ // adjusted max_lines to get a max_height of (max_lines + 1) * line_height.
+ size_t max_height = std::numeric_limits<int>::max();
+ size_t line_height = std::max(font().GetHeight(), 2); // At least 2 pixels!
+ max_lines = std::min(max_lines, max_height / line_height - 1);
+ max_height = (max_lines + 1) * line_height;
+
+ // Split. Do not use ui::WRAP_LONG_WORDS instead of ui::IGNORE_LONG_WORDS
+ // below as this may cause ui::ElideRectangleText() to go into an infinite
+ // loop for small width values.
+ std::vector<string16> lines;
+ ui::ElideRectangleText(text(), font(), width, max_height,
+ ui::IGNORE_LONG_WORDS, &lines);
+
+ // Elide if necessary.
+ if (lines.size() > max_lines) {
+ // Add an ellipsis to the last line. If this ellipsis makes the last line
+ // too wide, that line will be further elided by the ui::ElideText below,
+ // so for example "ABC" could become "ABC..." here and "AB..." below.
+ string16 last = lines[max_lines - 1] + UTF8ToUTF16(ui::kEllipsis);
+ lines.resize(max_lines - 1);
+ lines.push_back((font().GetStringWidth(last) > width) ?
+ ui::ElideText(last, font(), width, ui::ELIDE_AT_END) :
+ last);
+ }
+
+ return lines;
+}
+
+} // namespace message_center

Powered by Google App Engine
This is Rietveld 408576698