• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 namespace autofill {
17 
18 namespace {
19 
GetPreferredInsets(views::View * view)20 gfx::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.
32 class TooltipBubble : public InfoBubble {
33  public:
TooltipBubble(views::View * anchor,const base::string16 & message)34   TooltipBubble(views::View* anchor, const base::string16& message)
35       : InfoBubble(anchor, message) {}
~TooltipBubble()36   virtual ~TooltipBubble() {}
37 
38  protected:
39   // InfoBubble:
GetAnchorRect()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 
TooltipIcon(const base::string16 & tooltip)52 TooltipIcon::TooltipIcon(const base::string16& tooltip)
53     : tooltip_(tooltip),
54       mouse_inside_(false),
55       bubble_(NULL),
56       observer_(this) {
57   ChangeImageTo(IDR_AUTOFILL_TOOLTIP_ICON);
58   SetFocusable(true);
59 }
60 
~TooltipIcon()61 TooltipIcon::~TooltipIcon() {
62   HideBubble();
63 }
64 
65 // static
66 const char TooltipIcon::kViewClassName[] = "autofill/TooltipIcon";
67 
GetClassName() const68 const char* TooltipIcon::GetClassName() const {
69   return TooltipIcon::kViewClassName;
70 }
71 
OnMouseEntered(const ui::MouseEvent & event)72 void 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 
OnMouseExited(const ui::MouseEvent & event)78 void TooltipIcon::OnMouseExited(const ui::MouseEvent& event) {
79   show_timer_.Stop();
80 }
81 
OnGestureEvent(ui::GestureEvent * event)82 void TooltipIcon::OnGestureEvent(ui::GestureEvent* event) {
83   if (event->type() == ui::ET_GESTURE_TAP) {
84     ShowBubble();
85     event->SetHandled();
86   }
87 }
88 
OnBoundsChanged(const gfx::Rect & prev_bounds)89 void TooltipIcon::OnBoundsChanged(const gfx::Rect& prev_bounds) {
90   SetFocusPainter(views::Painter::CreateDashedFocusPainterWithInsets(
91                       GetPreferredInsets(this)));
92 }
93 
OnFocus()94 void TooltipIcon::OnFocus() {
95   ShowBubble();
96 }
97 
OnBlur()98 void TooltipIcon::OnBlur() {
99   if (!mouse_inside_)
100     HideBubble();
101 }
102 
MouseMovedOutOfHost()103 void TooltipIcon::MouseMovedOutOfHost() {
104   if (IsMouseHovered()) {
105     mouse_watcher_->Start();
106     return;
107   }
108 
109   mouse_inside_ = false;
110   if (!HasFocus())
111     HideBubble();
112 }
113 
ChangeImageTo(int idr)114 void TooltipIcon::ChangeImageTo(int idr) {
115   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
116   SetImage(rb.GetImageNamed(idr).ToImageSkia());
117 }
118 
ShowBubble()119 void TooltipIcon::ShowBubble() {
120   if (bubble_)
121     return;
122 
123   ChangeImageTo(IDR_AUTOFILL_TOOLTIP_ICON_H);
124 
125   bubble_ = new TooltipBubble(this, tooltip_);
126   // When shown due to a gesture event, close on deactivate (i.e. don't use
127   // "focusless").
128   bubble_->set_use_focusless(mouse_inside_ || HasFocus());
129 
130   bubble_->Show();
131   observer_.Add(bubble_->GetWidget());
132 
133   if (mouse_inside_) {
134     views::View* frame = bubble_->GetWidget()->non_client_view()->frame_view();
135     scoped_ptr<views::MouseWatcherHost> host(
136         new views::MouseWatcherViewHost(frame, gfx::Insets()));
137     mouse_watcher_.reset(new views::MouseWatcher(host.release(), this));
138     mouse_watcher_->Start();
139   }
140 }
141 
HideBubble()142 void TooltipIcon::HideBubble() {
143   if (bubble_)
144     bubble_->Hide();
145 }
146 
OnWidgetDestroyed(views::Widget * widget)147 void TooltipIcon::OnWidgetDestroyed(views::Widget* widget) {
148   observer_.Remove(widget);
149 
150   ChangeImageTo(IDR_AUTOFILL_TOOLTIP_ICON);
151   mouse_watcher_.reset();
152   bubble_ = NULL;
153 }
154 
155 }  // namespace autofill
156