tooltip_icon.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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.
4
5#include "chrome/browser/ui/views/autofill/tooltip_icon.h"
6
7#include "base/basictypes.h"
8#include "base/timer/timer.h"
9#include "chrome/browser/ui/views/autofill/info_bubble.h"
10#include "grit/theme_resources.h"
11#include "ui/base/resource/resource_bundle.h"
12#include "ui/views/bubble/bubble_frame_view.h"
13#include "ui/views/mouse_watcher_view_host.h"
14#include "ui/views/painter.h"
15
16namespace autofill {
17
18namespace {
19
20gfx::Insets GetPreferredInsets(views::View* view) {
21  gfx::Size pref_size = view->GetPreferredSize();
22  gfx::Rect local_bounds = view->GetLocalBounds();
23  gfx::Point origin = local_bounds.CenterPoint();
24  origin.Offset(-pref_size.width() / 2, -pref_size.height() / 2);
25  return gfx::Insets(origin.y(),
26                     origin.x(),
27                     local_bounds.bottom() - (origin.y() + pref_size.height()),
28                     local_bounds.right() - (origin.x() + pref_size.width()));
29}
30
31// An info bubble with some extra positioning magic for tooltip icons.
32class TooltipBubble : public InfoBubble {
33 public:
34  TooltipBubble(views::View* anchor, const base::string16& message)
35      : InfoBubble(anchor, message) {}
36  virtual ~TooltipBubble() {}
37
38 protected:
39  // InfoBubble:
40  virtual gfx::Rect GetAnchorRect() OVERRIDE {
41    gfx::Rect bounds = views::BubbleDelegateView::GetAnchorRect();
42    bounds.Inset(GetPreferredInsets(anchor()));
43    return bounds;
44  }
45
46 private:
47  DISALLOW_COPY_AND_ASSIGN(TooltipBubble);
48};
49
50}  // namespace
51
52TooltipIcon::TooltipIcon(const base::string16& tooltip)
53    : tooltip_(tooltip),
54      mouse_inside_(false),
55      bubble_(NULL) {
56  ChangeImageTo(IDR_AUTOFILL_TOOLTIP_ICON);
57  set_focusable(true);
58}
59
60TooltipIcon::~TooltipIcon() {
61  HideBubble();
62}
63
64// static
65const char TooltipIcon::kViewClassName[] = "autofill/TooltipIcon";
66
67const char* TooltipIcon::GetClassName() const {
68  return TooltipIcon::kViewClassName;
69}
70
71void TooltipIcon::OnMouseEntered(const ui::MouseEvent& event) {
72  mouse_inside_ = true;
73  show_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(150), this,
74                    &TooltipIcon::ShowBubble);
75}
76
77void TooltipIcon::OnMouseExited(const ui::MouseEvent& event) {
78  show_timer_.Stop();
79}
80
81void TooltipIcon::OnGestureEvent(ui::GestureEvent* event) {
82  if (event->type() == ui::ET_GESTURE_TAP) {
83    ShowBubble();
84    event->SetHandled();
85  }
86}
87
88void TooltipIcon::OnBoundsChanged(const gfx::Rect& prev_bounds) {
89  SetFocusPainter(views::Painter::CreateDashedFocusPainterWithInsets(
90                      GetPreferredInsets(this)));
91}
92
93void TooltipIcon::OnFocus() {
94  ShowBubble();
95}
96
97void TooltipIcon::OnBlur() {
98  HideBubble();
99}
100
101void TooltipIcon::MouseMovedOutOfHost() {
102  if (IsMouseHovered()) {
103    mouse_watcher_->Start();
104    return;
105  }
106
107  mouse_inside_ = false;
108  HideBubble();
109}
110
111void TooltipIcon::ChangeImageTo(int idr) {
112  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
113  SetImage(rb.GetImageNamed(idr).ToImageSkia());
114}
115
116void TooltipIcon::ShowBubble() {
117  if (bubble_)
118    return;
119
120  ChangeImageTo(IDR_AUTOFILL_TOOLTIP_ICON_H);
121
122  bubble_ = new TooltipBubble(this, tooltip_);
123  // When shown due to a gesture event, close on deactivate (i.e. don't use
124  // "focusless").
125  bubble_->set_use_focusless(mouse_inside_ || HasFocus());
126
127  bubble_->Show();
128
129  if (mouse_inside_) {
130    views::View* frame = bubble_->GetWidget()->non_client_view()->frame_view();
131    scoped_ptr<views::MouseWatcherHost> host(
132        new views::MouseWatcherViewHost(frame, gfx::Insets()));
133    mouse_watcher_.reset(new views::MouseWatcher(host.release(), this));
134    mouse_watcher_->Start();
135  }
136}
137
138void TooltipIcon::HideBubble() {
139  if (HasFocus() || mouse_inside_ || !bubble_)
140    return;
141
142  ChangeImageTo(IDR_AUTOFILL_TOOLTIP_ICON);
143
144  mouse_watcher_.reset();
145  bubble_->Hide();
146  bubble_ = NULL;
147}
148
149}  // namespace autofill
150