Index: ash/tooltips/tooltip_controller.cc |
diff --git a/ash/tooltips/tooltip_controller.cc b/ash/tooltips/tooltip_controller.cc |
index 52049e73f2e05e6a8d96d1d3dab0acbf6d8470b7..6e533c4bd325e9b0ad1379f07f2be7737fc5c24a 100644 |
--- a/ash/tooltips/tooltip_controller.cc |
+++ b/ash/tooltips/tooltip_controller.cc |
@@ -33,6 +33,14 @@ const SkColor kTooltipBackground = 0xFFFFFFCC; |
const SkColor kTooltipBorder = 0xFF646450; |
const int kTooltipBorderWidth = 1; |
const int kTooltipHorizontalPadding = 3; |
+ |
+// Max visual tooltip width. If a tooltip is greater than this width, it will |
+// be wrapped. |
+const int kTooltipMaxWidthPixels = 400; |
sky
2012/03/21 04:17:23
On the windows side we initially had tooltips exte
varunjain
2012/03/21 04:48:38
I restrict them here to the smaller of available s
|
+ |
+// Maximum number of lines we allow in the tooltip. |
+const size_t kMaxLines = 10; |
+ |
// TODO(derat): This padding is needed on Chrome OS devices but seems excessive |
// when running the same binary on a Linux workstation; presumably there's a |
// difference in font metrics. Rationalize this. |
@@ -46,9 +54,6 @@ const int kCursorOffsetY = 15; |
// Maximum number of characters we allow in a tooltip. |
const size_t kMaxTooltipLength = 1024; |
-// Maximum number of lines we allow in the tooltip. |
-const size_t kMaxLines = 6; |
- |
gfx::Font GetDefaultFont() { |
// TODO(varunjain): implementation duplicated in tooltip_manager_aura. Figure |
// out a way to merge. |
@@ -82,26 +87,67 @@ void TrimTooltipToFit(string16* text, |
*text = text->substr(0, kMaxTooltipLength); |
// Determine the available width for the tooltip. |
- int available_width = GetMaxWidth(x, y); |
+ int available_width = std::min(kTooltipMaxWidthPixels, GetMaxWidth(x, y)); |
- // Split the string into at most kMaxLines lines. |
std::vector<string16> lines; |
base::SplitString(*text, '\n', &lines); |
- if (lines.size() > kMaxLines) |
- lines.resize(kMaxLines); |
- *line_count = static_cast<int>(lines.size()); |
+ std::vector<string16> result_lines; |
// Format each line to fit. |
gfx::Font font = GetDefaultFont(); |
+ for (std::vector<string16>::iterator l = lines.begin(); l != lines.end(); |
+ ++l) { |
+ // We break the line at word boundaries, then stuff as many words as we can |
+ // in the available width to the current line, and move the remaining words |
+ // to a new line. |
+ std::vector<string16> words; |
+ base::SplitStringDontTrim(*l, ' ', &words); |
Daniel Erat
2012/03/21 00:55:40
is it okay to rebuild the string like this, or are
varunjain
2012/03/21 04:48:38
whitespace is preserver when I use SplitStringDont
|
+ int current_width = 0; |
+ string16 line; |
+ for (std::vector<string16>::iterator w = words.begin(); w != words.end(); |
+ ++w) { |
+ string16 word = *w; |
+ if (w + 1 != words.end()) |
+ word.push_back(' '); |
+ int word_width = font.GetStringWidth(word); |
+ if (current_width + word_width > available_width) { |
+ // Current width will exceed the available width. Must start a new line. |
+ result_lines.push_back(line); |
+ current_width = 0; |
+ line.clear(); |
+ } |
+ current_width += word_width; |
+ line.append(word); |
+ } |
+ result_lines.push_back(line); |
+ } |
+ |
+ // Clamp number of lines to |kMaxLines|. |
+ if (result_lines.size() > kMaxLines) { |
+ result_lines.resize(kMaxLines); |
+ // Add ellipses character to last line. |
+ result_lines[kMaxLines - 1] = ui::TruncateString( |
+ result_lines.back(), result_lines.back().length() - 1); |
+ } |
+ *line_count = result_lines.size(); |
+ |
+ // Flatten the result. |
string16 result; |
- for (std::vector<string16>::iterator i = lines.begin(); i != lines.end(); |
- ++i) { |
- string16 elided_text = |
- ui::ElideText(*i, font, available_width, ui::ELIDE_AT_END); |
- *max_width = std::max(*max_width, font.GetStringWidth(elided_text)); |
+ for (std::vector<string16>::iterator l = result_lines.begin(); |
+ l != result_lines.end(); ++l) { |
if (!result.empty()) |
result.push_back('\n'); |
- result.append(elided_text); |
+ int line_width = font.GetStringWidth(*l); |
+ // Since we only break at word boundaries, it could happen that due to some |
+ // very long word, line_width is greater than the available_width. In such |
+ // case, we simply truncate at available_width and add ellipses at the end. |
+ if (line_width > available_width) { |
+ *max_width = available_width; |
+ result.append(ui::ElideText(*l, font, available_width, ui::ELIDE_AT_END)); |
+ } else { |
+ *max_width = std::max(*max_width, line_width); |
+ result.append(*l); |
+ } |
} |
*text = result; |
} |