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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/message_center/views/bounded_label.h"
6
7 #include <limits>
8
9 #include "base/string_util.h"
10 #include "base/utf_string_conversions.h"
11 #include "ui/base/text/text_elider.h"
12 #include "ui/gfx/canvas.h"
13
14 namespace message_center {
15
16 BoundedLabel::BoundedLabel(string16 text, size_t max_lines)
17 : views::Label(text, gfx::Font()) {
18 Init(max_lines);
19 }
20
21 BoundedLabel::BoundedLabel(string16 text, gfx::Font font, size_t max_lines)
22 : views::Label(text, font) {
23 Init(max_lines);
24 }
25
26 BoundedLabel::~BoundedLabel() {
27 }
28
29 void BoundedLabel::SetMaxLines(size_t lines) {
30 is_preferred_lines_valid_ = false;
31 is_text_size_valid_ = false;
32 max_lines_ = lines;
33 }
34
35 size_t BoundedLabel::GetMaxLines() {
36 return max_lines_;
37 }
38
39 size_t BoundedLabel::GetPreferredLines() {
40 if (!is_preferred_lines_valid_) {
41 int wrap_width = width() - GetInsets().width();
42 int unlimited_lines = std::numeric_limits<size_t>::max();
43 preferred_lines_ = SplitLines(wrap_width, unlimited_lines).size();
44 is_preferred_lines_valid_ = true;
45 }
46 return preferred_lines_;
47 }
48
49 int BoundedLabel::GetHeightForWidth(int width) const {
50 width = std::max(0, width - GetInsets().width());
51 int height = font().GetHeight();
52 string16 text = JoinString(SplitLines(width, max_lines_), '\n');
53 gfx::Canvas::SizeStringInt(text, font(), &width, &height, GetTextFlags());
54 return height + GetInsets().height();
55 }
56
57 gfx::Size BoundedLabel::GetTextSize() const {
58 if (!is_text_size_valid_) {
59 text_size_.set_width(width() - GetInsets().width());
60 text_size_.set_height(GetHeightForWidth(width()) - GetInsets().height());
61 is_text_size_valid_ = true;
62 }
63 return text_size_;
64 }
65
66 void BoundedLabel::OnBoundsChanged(const gfx::Rect& previous_bounds) {
67 is_preferred_lines_valid_ = false;
68 is_text_size_valid_ = false;
69 }
70
71 void BoundedLabel::PaintText(gfx::Canvas* canvas,
72 const string16& paint_text,
73 const gfx::Rect& text_bounds,
74 int flags) {
75 gfx::Insets insets = GetInsets();
76 gfx::Rect bounds(gfx::Point(insets.left(), insets.top()), GetTextSize());
77 string16 text = JoinString(SplitLines(bounds.width(), max_lines_), '\n');
78 views::Label::PaintText(canvas, text, bounds, GetTextFlags());
79 }
80
81 void BoundedLabel::Init(size_t max_lines) {
82 SetMultiLine(true);
83 SetAllowCharacterBreak(true);
84 SetElideBehavior(views::Label::ELIDE_AT_END);
85 max_lines_ = max_lines;
86 is_preferred_lines_valid_ = false;
87 is_text_size_valid_ = false;
88 }
89
90 int BoundedLabel::GetTextFlags() const {
91 int flags = gfx::Canvas::MULTI_LINE | gfx::Canvas::CHARACTER_BREAK;
92
93 // We can't use subpixel rendering if the background is non-opaque.
94 if (SkColorGetA(background_color()) != 0xFF)
95 flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING;
96
97 if (directionality_mode() == AUTO_DETECT_DIRECTIONALITY) {
98 base::i18n::TextDirection direction =
99 base::i18n::GetFirstStrongCharacterDirection(text());
100 if (direction == base::i18n::RIGHT_TO_LEFT)
101 flags |= gfx::Canvas::FORCE_RTL_DIRECTIONALITY;
102 else
103 flags |= gfx::Canvas::FORCE_LTR_DIRECTIONALITY;
104 }
105
106 switch (horizontal_alignment()) {
107 case gfx::ALIGN_LEFT:
108 flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
109 break;
110 case gfx::ALIGN_CENTER:
111 flags |= gfx::Canvas::TEXT_ALIGN_CENTER;
112 break;
113 case gfx::ALIGN_RIGHT:
114 flags |= gfx::Canvas::TEXT_ALIGN_RIGHT;
115 break;
116 }
117
118 return flags;
119 }
120
121 std::vector<string16> BoundedLabel::SplitLines(int width,
122 size_t max_lines) const {
123 // Adjust max_lines so (max_lines + 1) * line_height <= INT_MAX, then use the
124 // adjusted max_lines to get a max_height of (max_lines + 1) * line_height.
125 size_t max_height = std::numeric_limits<int>::max();
126 size_t line_height = std::max(font().GetHeight(), 2); // At least 2 pixels!
127 max_lines = std::min(max_lines, max_height / line_height - 1);
128 max_height = (max_lines + 1) * line_height;
129
130 // Split. Do not use ui::WRAP_LONG_WORDS instead of ui::IGNORE_LONG_WORDS
131 // below as this may cause ui::ElideRectangleText() to go into an infinite
132 // loop for small width values.
133 std::vector<string16> lines;
134 ui::ElideRectangleText(text(), font(), width, max_height,
135 ui::IGNORE_LONG_WORDS, &lines);
136
137 // Elide if necessary.
138 if (lines.size() > max_lines) {
139 // Add an ellipsis to the last line. If this ellipsis makes the last line
140 // too wide, that line will be further elided by the ui::ElideText below,
141 // so for example "ABC" could become "ABC..." here and "AB..." below.
142 string16 last = lines[max_lines - 1] + UTF8ToUTF16(ui::kEllipsis);
143 lines.resize(max_lines - 1);
144 lines.push_back((font().GetStringWidth(last) > width) ?
145 ui::ElideText(last, font(), width, ui::ELIDE_AT_END) :
146 last);
147 }
148
149 return lines;
150 }
151
152 } // namespace message_center
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698