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