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

Side by Side Diff: ash/tooltips/tooltip_controller.cc

Issue 9796004: aura: Really long tooltips should be wrapped not truncated. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: trying to fix windows build again! Created 8 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
« no previous file with comments | « ash/tooltips/tooltip_controller.h ('k') | ash/tooltips/tooltip_controller_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ash/tooltips/tooltip_controller.h" 5 #include "ash/tooltips/tooltip_controller.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "ash/ash_switches.h" 9 #include "ash/ash_switches.h"
10 #include "ash/shell.h" 10 #include "ash/shell.h"
(...skipping 15 matching lines...) Expand all
26 #include "ui/views/border.h" 26 #include "ui/views/border.h"
27 #include "ui/views/controls/label.h" 27 #include "ui/views/controls/label.h"
28 #include "ui/views/widget/widget.h" 28 #include "ui/views/widget/widget.h"
29 29
30 namespace { 30 namespace {
31 31
32 const SkColor kTooltipBackground = 0xFFFFFFCC; 32 const SkColor kTooltipBackground = 0xFFFFFFCC;
33 const SkColor kTooltipBorder = 0xFF646450; 33 const SkColor kTooltipBorder = 0xFF646450;
34 const int kTooltipBorderWidth = 1; 34 const int kTooltipBorderWidth = 1;
35 const int kTooltipHorizontalPadding = 3; 35 const int kTooltipHorizontalPadding = 3;
36
37 // Max visual tooltip width. If a tooltip is greater than this width, it will
38 // be wrapped.
39 const int kTooltipMaxWidthPixels = 400;
40
41 // Maximum number of lines we allow in the tooltip.
42 const size_t kMaxLines = 10;
43
36 // TODO(derat): This padding is needed on Chrome OS devices but seems excessive 44 // TODO(derat): This padding is needed on Chrome OS devices but seems excessive
37 // when running the same binary on a Linux workstation; presumably there's a 45 // when running the same binary on a Linux workstation; presumably there's a
38 // difference in font metrics. Rationalize this. 46 // difference in font metrics. Rationalize this.
39 const int kTooltipVerticalPadding = 2; 47 const int kTooltipVerticalPadding = 2;
40 const int kTooltipTimeoutMs = 500; 48 const int kTooltipTimeoutMs = 500;
41 49
42 // FIXME: get cursor offset from actual cursor size. 50 // FIXME: get cursor offset from actual cursor size.
43 const int kCursorOffsetX = 10; 51 const int kCursorOffsetX = 10;
44 const int kCursorOffsetY = 15; 52 const int kCursorOffsetY = 15;
45 53
46 // Maximum number of characters we allow in a tooltip. 54 // Maximum number of characters we allow in a tooltip.
47 const size_t kMaxTooltipLength = 1024; 55 const size_t kMaxTooltipLength = 1024;
48 56
49 // Maximum number of lines we allow in the tooltip.
50 const size_t kMaxLines = 6;
51
52 gfx::Font GetDefaultFont() { 57 gfx::Font GetDefaultFont() {
53 // TODO(varunjain): implementation duplicated in tooltip_manager_aura. Figure 58 // TODO(varunjain): implementation duplicated in tooltip_manager_aura. Figure
54 // out a way to merge. 59 // out a way to merge.
55 return ui::ResourceBundle::GetSharedInstance().GetFont( 60 return ui::ResourceBundle::GetSharedInstance().GetFont(
56 ui::ResourceBundle::BaseFont); 61 ui::ResourceBundle::BaseFont);
57 } 62 }
58 63
59 int GetMaxWidth(int x, int y) { 64 int GetMaxWidth(int x, int y) {
60 // TODO(varunjain): implementation duplicated in tooltip_manager_aura. Figure 65 // TODO(varunjain): implementation duplicated in tooltip_manager_aura. Figure
61 // out a way to merge. 66 // out a way to merge.
62 gfx::Rect monitor_bounds = 67 gfx::Rect monitor_bounds =
63 gfx::Screen::GetMonitorAreaNearestPoint(gfx::Point(x, y)); 68 gfx::Screen::GetMonitorAreaNearestPoint(gfx::Point(x, y));
64 return (monitor_bounds.width() + 1) / 2; 69 return (monitor_bounds.width() + 1) / 2;
65 } 70 }
66 71
67 // Trims the tooltip to fit, setting |text| to the clipped result,
68 // |max_width| to the width (in pixels) of the clipped text and |line_count|
69 // to the number of lines of text in the tooltip. |x| and |y| give the
70 // location of the tooltip in screen coordinates.
71 void TrimTooltipToFit(string16* text,
72 int* max_width,
73 int* line_count,
74 int x,
75 int y) {
76 *max_width = 0;
77 *line_count = 0;
78
79 // Clamp the tooltip length to kMaxTooltipLength so that we don't
80 // accidentally DOS the user with a mega tooltip.
81 if (text->length() > kMaxTooltipLength)
82 *text = text->substr(0, kMaxTooltipLength);
83
84 // Determine the available width for the tooltip.
85 int available_width = GetMaxWidth(x, y);
86
87 // Split the string into at most kMaxLines lines.
88 std::vector<string16> lines;
89 base::SplitString(*text, '\n', &lines);
90 if (lines.size() > kMaxLines)
91 lines.resize(kMaxLines);
92 *line_count = static_cast<int>(lines.size());
93
94 // Format each line to fit.
95 gfx::Font font = GetDefaultFont();
96 string16 result;
97 for (std::vector<string16>::iterator i = lines.begin(); i != lines.end();
98 ++i) {
99 string16 elided_text =
100 ui::ElideText(*i, font, available_width, ui::ELIDE_AT_END);
101 *max_width = std::max(*max_width, font.GetStringWidth(elided_text));
102 if (!result.empty())
103 result.push_back('\n');
104 result.append(elided_text);
105 }
106 *text = result;
107 }
108
109 // Creates a widget of type TYPE_TOOLTIP 72 // Creates a widget of type TYPE_TOOLTIP
110 views::Widget* CreateTooltip() { 73 views::Widget* CreateTooltip() {
111 views::Widget* widget = new views::Widget; 74 views::Widget* widget = new views::Widget;
112 views::Widget::InitParams params; 75 views::Widget::InitParams params;
113 // For aura, since we set the type to TOOLTIP_TYPE, the widget will get 76 // For aura, since we set the type to TOOLTIP_TYPE, the widget will get
114 // auto-parented to the MenuAndTooltipsContainer. 77 // auto-parented to the MenuAndTooltipsContainer.
115 params.type = views::Widget::InitParams::TYPE_TOOLTIP; 78 params.type = views::Widget::InitParams::TYPE_TOOLTIP;
116 params.keep_on_top = true; 79 params.keep_on_top = true;
117 params.accept_events = false; 80 params.accept_events = false;
118 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 81 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 return ui::GESTURE_STATUS_UNKNOWN; 276 return ui::GESTURE_STATUS_UNKNOWN;
314 } 277 }
315 278
316 void TooltipController::OnWindowDestroyed(aura::Window* window) { 279 void TooltipController::OnWindowDestroyed(aura::Window* window) {
317 if (tooltip_window_ == window) { 280 if (tooltip_window_ == window) {
318 tooltip_window_->RemoveObserver(this); 281 tooltip_window_->RemoveObserver(this);
319 tooltip_window_ = NULL; 282 tooltip_window_ = NULL;
320 } 283 }
321 } 284 }
322 285
286 ////////////////////////////////////////////////////////////////////////////////
287 // TooltipController private:
288
289 // static
290 void TooltipController::TrimTooltipToFit(string16* text,
291 int* max_width,
292 int* line_count,
293 int x,
294 int y) {
295 *max_width = 0;
296 *line_count = 0;
297
298 // Clamp the tooltip length to kMaxTooltipLength so that we don't
299 // accidentally DOS the user with a mega tooltip.
300 if (text->length() > kMaxTooltipLength)
301 *text = text->substr(0, kMaxTooltipLength);
302
303 // Determine the available width for the tooltip.
304 int available_width = std::min(kTooltipMaxWidthPixels, GetMaxWidth(x, y));
305
306 std::vector<string16> lines;
307 base::SplitString(*text, '\n', &lines);
308 std::vector<string16> result_lines;
309
310 // Format each line to fit.
311 gfx::Font font = GetDefaultFont();
312 for (std::vector<string16>::iterator l = lines.begin(); l != lines.end();
313 ++l) {
314 // We break the line at word boundaries, then stuff as many words as we can
315 // in the available width to the current line, and move the remaining words
316 // to a new line.
317 std::vector<string16> words;
318 base::SplitStringDontTrim(*l, ' ', &words);
319 int current_width = 0;
320 string16 line;
321 for (std::vector<string16>::iterator w = words.begin(); w != words.end();
322 ++w) {
323 string16 word = *w;
324 if (w + 1 != words.end())
325 word.push_back(' ');
326 int word_width = font.GetStringWidth(word);
327 if (current_width + word_width > available_width) {
328 // Current width will exceed the available width. Must start a new line.
329 if (!line.empty())
330 result_lines.push_back(line);
331 current_width = 0;
332 line.clear();
333 }
334 current_width += word_width;
335 line.append(word);
336 }
337 result_lines.push_back(line);
338 }
339
340 // Clamp number of lines to |kMaxLines|.
341 if (result_lines.size() > kMaxLines) {
342 result_lines.resize(kMaxLines);
343 // Add ellipses character to last line.
344 result_lines[kMaxLines - 1] = ui::TruncateString(
345 result_lines.back(), result_lines.back().length() - 1);
346 }
347 *line_count = result_lines.size();
348
349 // Flatten the result.
350 string16 result;
351 for (std::vector<string16>::iterator l = result_lines.begin();
352 l != result_lines.end(); ++l) {
353 if (!result.empty())
354 result.push_back('\n');
355 int line_width = font.GetStringWidth(*l);
356 // Since we only break at word boundaries, it could happen that due to some
357 // very long word, line_width is greater than the available_width. In such
358 // case, we simply truncate at available_width and add ellipses at the end.
359 if (line_width > available_width) {
360 *max_width = available_width;
361 result.append(ui::ElideText(*l, font, available_width, ui::ELIDE_AT_END));
362 } else {
363 *max_width = std::max(*max_width, line_width);
364 result.append(*l);
365 }
366 }
367 *text = result;
368 }
369
323 void TooltipController::TooltipTimerFired() { 370 void TooltipController::TooltipTimerFired() {
324 UpdateIfRequired(); 371 UpdateIfRequired();
325 } 372 }
326 373
327 void TooltipController::UpdateIfRequired() { 374 void TooltipController::UpdateIfRequired() {
328 if (!tooltips_enabled_ || mouse_pressed_ || IsDragDropInProgress()) { 375 if (!tooltips_enabled_ || mouse_pressed_ || IsDragDropInProgress()) {
329 tooltip_->Hide(); 376 tooltip_->Hide();
330 return; 377 return;
331 } 378 }
332 379
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 bool TooltipController::IsDragDropInProgress() { 418 bool TooltipController::IsDragDropInProgress() {
372 aura::client::DragDropClient* client = aura::client::GetDragDropClient( 419 aura::client::DragDropClient* client = aura::client::GetDragDropClient(
373 Shell::GetRootWindow()); 420 Shell::GetRootWindow());
374 if (client) 421 if (client)
375 return client->IsDragDropInProgress(); 422 return client->IsDragDropInProgress();
376 return false; 423 return false;
377 } 424 }
378 425
379 } // namespace internal 426 } // namespace internal
380 } // namespace ash 427 } // namespace ash
OLDNEW
« no previous file with comments | « ash/tooltips/tooltip_controller.h ('k') | ash/tooltips/tooltip_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698