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

Side by Side Diff: ui/aura_shell/shell_tooltip_manager.cc

Issue 8769011: Reland change for aura tooltips that was revert due to build break: (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: moved exclude to gyp file Created 9 years 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 | « ui/aura_shell/shell_tooltip_manager.h ('k') | ui/views/test/test_tooltip_client.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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/aura_shell/shell_tooltip_manager.h"
6
7 #include <vector>
8
9 #include "base/location.h"
10 #include "base/string_split.h"
11 #include "base/time.h"
12 #include "ui/aura/client/aura_constants.h"
13 #include "ui/aura/event.h"
14 #include "ui/aura/window.h"
15 #include "ui/aura_shell/shell.h"
16 #include "ui/base/resource/resource_bundle.h"
17 #include "ui/base/text/text_elider.h"
18 #include "ui/gfx/font.h"
19 #include "ui/gfx/point.h"
20 #include "ui/gfx/rect.h"
21 #include "ui/gfx/screen.h"
22 #include "ui/views/background.h"
23 #include "ui/views/border.h"
24 #include "ui/views/controls/label.h"
25 #include "ui/views/widget/widget.h"
26
27 namespace {
28
29 SkColor kTooltipBackground = 0xFFFFFFCC;
30 SkColor kTooltipBorder = 0xFF000000;
31 int kTooltipBorderWidth = 1;
32 int kTooltipTimeoutMs = 500;
33
34 // FIXME: get cursor offset from actual cursor size.
35 int kCursorOffsetX = 10;
36 int kCursorOffsetY = 15;
37
38 // Maximum number of characters we allow in a tooltip.
39 const size_t kMaxTooltipLength = 1024;
40
41 // Maximum number of lines we allow in the tooltip.
42 const size_t kMaxLines = 6;
43
44 // Trims the tooltip to fit, setting |text| to the clipped result,
45 // |max_width| to the width (in pixels) of the clipped text and |line_count|
46 // to the number of lines of text in the tooltip. |x| and |y| give the
47 // location of the tooltip in screen coordinates.
48 void TrimTooltipToFit(string16* text,
49 int* max_width,
50 int* line_count,
51 int x,
52 int y) {
53 *max_width = 0;
54 *line_count = 0;
55
56 // Clamp the tooltip length to kMaxTooltipLength so that we don't
57 // accidentally DOS the user with a mega tooltip.
58 if (text->length() > kMaxTooltipLength)
59 *text = text->substr(0, kMaxTooltipLength);
60
61 // Determine the available width for the tooltip.
62 int available_width = aura::TooltipClient::GetMaxWidth(x, y);
63
64 // Split the string into at most kMaxLines lines.
65 std::vector<string16> lines;
66 base::SplitString(*text, '\n', &lines);
67 if (lines.size() > kMaxLines)
68 lines.resize(kMaxLines);
69 *line_count = static_cast<int>(lines.size());
70
71 // Format each line to fit.
72 gfx::Font font = aura::TooltipClient::GetDefaultFont();
73 string16 result;
74 for (std::vector<string16>::iterator i = lines.begin(); i != lines.end();
75 ++i) {
76 string16 elided_text = ui::ElideText(*i, font, available_width, false);
77 *max_width = std::max(*max_width, font.GetStringWidth(elided_text));
78 if (!result.empty())
79 result.push_back('\n');
80 result.append(elided_text);
81 }
82 *text = result;
83 }
84
85 // Creates a widget of type TYPE_TOOLTIP
86 views::Widget* CreateTooltip() {
87 views::Widget* widget = new views::Widget;
88 views::Widget::InitParams params;
89 // For aura, since we set the type to TOOLTIP_TYPE, the widget will get
90 // auto-parented to the MenuAndTooltipsContainer.
91 params.type = views::Widget::InitParams::TYPE_TOOLTIP;
92 params.keep_on_top = true;
93 params.accept_events = false;
94 params.transparent = true;
95 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
96 widget->Init(params);
97 return widget;
98 }
99
100 } // namespace
101
102 namespace aura_shell {
103
104 // Displays a widget with tooltip using a views::Label.
105 class ShellTooltipManager::Tooltip {
106 public:
107 Tooltip() {
108 label_.set_background(
109 views::Background::CreateSolidBackground(kTooltipBackground));
110 label_.set_border(
111 views::Border::CreateSolidBorder(kTooltipBorderWidth, kTooltipBorder));
112 label_.set_parent_owned(false);
113 widget_.reset(CreateTooltip());
114 widget_->SetContentsView(&label_);
115 widget_->Activate();
116 }
117
118 ~Tooltip() {
119 widget_->Close();
120 }
121
122 // Updates the text on the tooltip and resizes to fit.
123 void SetText(string16 tooltip_text, gfx::Point location) {
124 int max_width, line_count;
125 TrimTooltipToFit(&tooltip_text, &max_width, &line_count,
126 location.x(), location.y());
127 label_.SetText(tooltip_text);
128
129 SetTooltipBounds(location, max_width + 2 * kTooltipBorderWidth,
130 label_.GetPreferredSize().height());
131 }
132
133 // Shows the tooltip.
134 void Show() {
135 widget_->Show();
136 }
137
138 // Hides the tooltip.
139 void Hide() {
140 widget_->Hide();
141 }
142
143 bool IsVisible() {
144 return widget_->IsVisible();
145 }
146
147 private:
148 views::Label label_;
149 scoped_ptr<views::Widget> widget_;
150
151 // Adjusts the bounds given by the arguments to fit inside the desktop
152 // and applies the adjusted bounds to the label_.
153 void SetTooltipBounds(gfx::Point mouse_pos,
154 int tooltip_width,
155 int tooltip_height) {
156 gfx::Rect tooltip_rect(mouse_pos.x(), mouse_pos.y(), tooltip_width,
157 tooltip_height);
158
159 tooltip_rect.Offset(kCursorOffsetX, kCursorOffsetY);
160 gfx::Rect monitor_bounds =
161 gfx::Screen::GetMonitorAreaNearestPoint(tooltip_rect.origin());
162 widget_->SetBounds(tooltip_rect.AdjustToFit(monitor_bounds));
163 }
164
165 };
166
167 ////////////////////////////////////////////////////////////////////////////////
168 // ShellTooltipManager public:
169
170 ShellTooltipManager::ShellTooltipManager() : aura::EventFilter(NULL),
171 tooltip_window_(NULL),
172 tooltip_(new Tooltip) {
173 tooltip_timer_.Start(FROM_HERE,
174 base::TimeDelta::FromMilliseconds(kTooltipTimeoutMs),
175 this, &ShellTooltipManager::TooltipTimerFired);
176 }
177
178 ShellTooltipManager::~ShellTooltipManager() {
179 if (tooltip_window_)
180 tooltip_window_->RemoveObserver(this);
181 }
182
183 void ShellTooltipManager::UpdateTooltip(aura::Window* target) {
184 // If tooltip is visible, we may want to hide it. If it is not, we are ok.
185 if (tooltip_window_ == target && tooltip_->IsVisible())
186 UpdateIfRequired();
187 }
188
189 bool ShellTooltipManager::PreHandleKeyEvent(aura::Window* target,
190 aura::KeyEvent* event) {
191 return false;
192 }
193
194 bool ShellTooltipManager::PreHandleMouseEvent(aura::Window* target,
195 aura::MouseEvent* event) {
196 switch (event->type()) {
197 case ui::ET_MOUSE_MOVED:
198 if (tooltip_window_ != target) {
199 if (tooltip_window_)
200 tooltip_window_->RemoveObserver(this);
201 tooltip_window_ = target;
202 tooltip_window_->AddObserver(this);
203 }
204 curr_mouse_loc_ = event->location();
205 if (tooltip_timer_.IsRunning())
206 tooltip_timer_.Reset();
207
208 if (tooltip_->IsVisible())
209 UpdateIfRequired();
210 break;
211 case ui::ET_MOUSE_PRESSED:
212 case ui::ET_MOUSE_RELEASED:
213 case ui::ET_MOUSE_DRAGGED:
214 case ui::ET_MOUSEWHEEL:
215 // Hide the tooltip for click, release, drag, wheel events.
216 if (tooltip_->IsVisible())
217 tooltip_->Hide();
218 break;
219 default:
220 break;
221 }
222 return false;
223 }
224
225 ui::TouchStatus ShellTooltipManager::PreHandleTouchEvent(
226 aura::Window* target,
227 aura::TouchEvent* event) {
228 return ui::TOUCH_STATUS_UNKNOWN;
229 }
230
231 void ShellTooltipManager::OnWindowDestroyed(aura::Window* window) {
232 if (tooltip_window_ == window) {
233 tooltip_window_->RemoveObserver(this);
234 tooltip_window_ = NULL;
235 }
236 }
237
238 void ShellTooltipManager::TooltipTimerFired() {
239 UpdateIfRequired();
240 }
241
242 void ShellTooltipManager::UpdateIfRequired() {
243 string16 tooltip_text;
244 if (tooltip_window_) {
245 void* property = tooltip_window_->GetProperty(aura::kTooltipTextKey);
246 if (property)
247 tooltip_text = *static_cast<string16*>(property);
248 }
249
250 if (tooltip_text_ != tooltip_text) {
251 tooltip_text_ = tooltip_text;
252 if (tooltip_text_.empty()) {
253 tooltip_->Hide();
254 } else {
255 string16 tooltip_text(tooltip_text_);
256 gfx::Point widget_loc = curr_mouse_loc_;
257 widget_loc = widget_loc.Add(tooltip_window_->GetScreenBounds().origin());
258 tooltip_->SetText(tooltip_text, widget_loc);
259 tooltip_->Show();
260 }
261 }
262 }
263
264 } // namespace aura_shell
265
266 namespace aura {
267
268 // static
269 gfx::Font TooltipClient::GetDefaultFont() {
270 return ui::ResourceBundle::GetSharedInstance().GetFont(
271 ui::ResourceBundle::BaseFont);
272 }
273
274 // static
275 int TooltipClient::GetMaxWidth(int x, int y) {
276 gfx::Rect monitor_bounds =
277 gfx::Screen::GetMonitorAreaNearestPoint(gfx::Point(x, y));
278 return (monitor_bounds.width() + 1) / 2;
279 }
280
281 } // namespace aura
OLDNEW
« no previous file with comments | « ui/aura_shell/shell_tooltip_manager.h ('k') | ui/views/test/test_tooltip_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698