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