Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ui / views / corewm / tooltip_aura.cc
blobfffcafbea7c2ae04f03792d6dd66c2fdfa70ecf4
1 // Copyright 2013 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.
5 #include "ui/views/corewm/tooltip_aura.h"
7 #include "base/strings/string_split.h"
8 #include "base/strings/string_util.h"
9 #include "ui/aura/window.h"
10 #include "ui/aura/window_tree_host.h"
11 #include "ui/gfx/canvas.h"
12 #include "ui/gfx/render_text.h"
13 #include "ui/gfx/screen.h"
14 #include "ui/gfx/text_elider.h"
15 #include "ui/gfx/text_utils.h"
16 #include "ui/native_theme/native_theme.h"
17 #include "ui/views/background.h"
18 #include "ui/views/border.h"
19 #include "ui/views/view.h"
20 #include "ui/views/widget/widget.h"
22 namespace {
24 // Max visual tooltip width. If a tooltip is greater than this width, it will
25 // be wrapped.
26 const int kTooltipMaxWidthPixels = 400;
28 // FIXME: get cursor offset from actual cursor size.
29 const int kCursorOffsetX = 10;
30 const int kCursorOffsetY = 15;
32 // Creates a widget of type TYPE_TOOLTIP
33 views::Widget* CreateTooltipWidget(aura::Window* tooltip_window) {
34 views::Widget* widget = new views::Widget;
35 views::Widget::InitParams params;
36 // For aura, since we set the type to TYPE_TOOLTIP, the widget will get
37 // auto-parented to the right container.
38 params.type = views::Widget::InitParams::TYPE_TOOLTIP;
39 params.context = tooltip_window;
40 DCHECK(params.context);
41 params.keep_on_top = true;
42 params.accept_events = false;
43 widget->Init(params);
44 return widget;
47 } // namespace
49 namespace views {
50 namespace corewm {
52 // TODO(oshima): Consider to use views::Label.
53 class TooltipAura::TooltipView : public views::View {
54 public:
55 TooltipView()
56 : render_text_(gfx::RenderText::CreateInstance()),
57 max_width_(0) {
58 const int kHorizontalPadding = 3;
59 const int kVerticalPadding = 2;
60 SetBorder(Border::CreateEmptyBorder(
61 kVerticalPadding, kHorizontalPadding,
62 kVerticalPadding, kHorizontalPadding));
64 set_owned_by_client();
65 render_text_->SetWordWrapBehavior(gfx::WRAP_LONG_WORDS);
66 render_text_->SetMultiline(true);
68 ResetDisplayRect();
71 ~TooltipView() override {}
73 // views:View:
74 void OnPaint(gfx::Canvas* canvas) override {
75 OnPaintBackground(canvas);
76 gfx::Size text_size = size();
77 gfx::Insets insets = border()->GetInsets();
78 text_size.Enlarge(-insets.width(), -insets.height());
79 render_text_->SetDisplayRect(gfx::Rect(text_size));
80 canvas->Save();
81 canvas->Translate(gfx::Vector2d(insets.left(), insets.top()));
82 render_text_->Draw(canvas);
83 canvas->Restore();
84 OnPaintBorder(canvas);
87 gfx::Size GetPreferredSize() const override {
88 gfx::Size view_size = render_text_->GetStringSize();
89 gfx::Insets insets = border()->GetInsets();
90 view_size.Enlarge(insets.width(), insets.height());
91 return view_size;
94 const char* GetClassName() const override {
95 return "TooltipView";
98 void SetText(const base::string16& text) {
99 render_text_->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD);
100 render_text_->SetText(text);
101 SchedulePaint();
104 void SetForegroundColor(SkColor color) {
105 render_text_->SetColor(color);
108 void SetMaxWidth(int width) {
109 max_width_ = width;
110 ResetDisplayRect();
113 private:
114 void ResetDisplayRect() {
115 gfx::Insets insets = border()->GetInsets();
116 int max_text_width = max_width_ - insets.width();
117 render_text_->SetDisplayRect(gfx::Rect(0, 0, max_text_width, 100000));
120 scoped_ptr<gfx::RenderText> render_text_;
121 int max_width_;
123 DISALLOW_COPY_AND_ASSIGN(TooltipView);
126 TooltipAura::TooltipAura()
127 : tooltip_view_(new TooltipView),
128 widget_(NULL),
129 tooltip_window_(NULL) {
132 TooltipAura::~TooltipAura() {
133 DestroyWidget();
136 void TooltipAura::SetTooltipBounds(const gfx::Point& mouse_pos,
137 const gfx::Size& tooltip_size) {
138 gfx::Rect tooltip_rect(mouse_pos, tooltip_size);
139 tooltip_rect.Offset(kCursorOffsetX, kCursorOffsetY);
140 gfx::Screen* screen = gfx::Screen::GetScreenFor(tooltip_window_);
141 gfx::Rect display_bounds(screen->GetDisplayNearestPoint(mouse_pos).bounds());
143 // If tooltip is out of bounds on the x axis, we simply shift it
144 // horizontally by the offset.
145 if (tooltip_rect.right() > display_bounds.right()) {
146 int h_offset = tooltip_rect.right() - display_bounds.right();
147 tooltip_rect.Offset(-h_offset, 0);
150 // If tooltip is out of bounds on the y axis, we flip it to appear above the
151 // mouse cursor instead of below.
152 if (tooltip_rect.bottom() > display_bounds.bottom())
153 tooltip_rect.set_y(mouse_pos.y() - tooltip_size.height());
155 tooltip_rect.AdjustToFit(display_bounds);
156 widget_->SetBounds(tooltip_rect);
159 void TooltipAura::DestroyWidget() {
160 if (widget_) {
161 widget_->RemoveObserver(this);
162 widget_->Close();
163 widget_ = NULL;
167 int TooltipAura::GetMaxWidth(const gfx::Point& location,
168 aura::Window* context) const {
169 gfx::Screen* screen = gfx::Screen::GetScreenFor(context);
170 gfx::Rect display_bounds(screen->GetDisplayNearestPoint(location).bounds());
171 return std::min(kTooltipMaxWidthPixels, (display_bounds.width() + 1) / 2);
174 void TooltipAura::SetText(aura::Window* window,
175 const base::string16& tooltip_text,
176 const gfx::Point& location) {
177 tooltip_window_ = window;
178 tooltip_view_->SetMaxWidth(GetMaxWidth(location, window));
179 tooltip_view_->SetText(tooltip_text);
181 if (!widget_) {
182 widget_ = CreateTooltipWidget(tooltip_window_);
183 widget_->SetContentsView(tooltip_view_.get());
184 widget_->AddObserver(this);
187 SetTooltipBounds(location, tooltip_view_->GetPreferredSize());
189 ui::NativeTheme* native_theme = widget_->GetNativeTheme();
190 tooltip_view_->set_background(
191 views::Background::CreateSolidBackground(
192 native_theme->GetSystemColor(
193 ui::NativeTheme::kColorId_TooltipBackground)));
194 tooltip_view_->SetForegroundColor(native_theme->GetSystemColor(
195 ui::NativeTheme::kColorId_TooltipText));
198 void TooltipAura::Show() {
199 if (widget_) {
200 widget_->Show();
201 widget_->StackAtTop();
205 void TooltipAura::Hide() {
206 tooltip_window_ = NULL;
207 if (widget_)
208 widget_->Hide();
211 bool TooltipAura::IsVisible() {
212 return widget_ && widget_->IsVisible();
215 void TooltipAura::OnWidgetDestroying(views::Widget* widget) {
216 DCHECK_EQ(widget_, widget);
217 widget_ = NULL;
218 tooltip_window_ = NULL;
221 } // namespace corewm
222 } // namespace views