tooltip_icon.cc revision 23730a6e56a168d1879203e4b3819bb36e3d8f1f
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(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() 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