14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ash/shelf/shelf_tooltip_manager.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shelf/shelf_layout_manager.h"
88bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "ash/shelf/shelf_view.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell_window_ids.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/window_animations.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/message_loop/message_loop.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h"
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h"
18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event.h"
19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event_constants.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/insets.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/bubble/bubble_delegate.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/bubble/bubble_frame_view.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/label.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/fill_layout.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kTooltipTopBottomMargin = 3;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kTooltipLeftRightMargin = 10;
31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const int kTooltipAppearanceDelay = 1000;  // msec
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kTooltipMinHeight = 29 - 2 * kTooltipTopBottomMargin;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SkColor kTooltipTextColor = SkColorSetRGB(0x22, 0x22, 0x22);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The maximum width of the tooltip bubble.  Borrowed the value from
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ash/tooltip/tooltip_controller.cc
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kTooltipMaxWidth = 250;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The offset for the tooltip bubble - making sure that the bubble is flush
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// with the shelf. The offset includes the arrow size in pixels as well as
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// the activation bar and other spacing elements.
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kArrowOffsetLeftRight = 11;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kArrowOffsetTopBottom = 7;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The implementation of tooltip of the launcher.
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class ShelfTooltipManager::ShelfTooltipBubble
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public views::BubbleDelegateView {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ShelfTooltipBubble(views::View* anchor,
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        views::BubbleBorder::Arrow arrow,
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                        ShelfTooltipManager* host);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void SetText(const base::string16& text);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Close();
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // views::WidgetDelegate overrides:
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void WindowClosing() OVERRIDE;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // views::View overrides:
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual gfx::Size GetPreferredSize() const OVERRIDE;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ShelfTooltipManager* host_;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Label* label_;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ShelfTooltipBubble);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ShelfTooltipManager::ShelfTooltipBubble::ShelfTooltipBubble(
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::View* anchor,
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    views::BubbleBorder::Arrow arrow,
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ShelfTooltipManager* host)
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : views::BubbleDelegateView(anchor, arrow), host_(host) {
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Insets insets = gfx::Insets(kArrowOffsetTopBottom,
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   kArrowOffsetLeftRight,
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   kArrowOffsetTopBottom,
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   kArrowOffsetLeftRight);
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Shelf items can have an asymmetrical border for spacing reasons.
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Adjust anchor location for this.
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (anchor->border())
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    insets += anchor->border()->GetInsets();
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  set_anchor_view_insets(insets);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_close_on_esc(false);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_close_on_deactivate(false);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_use_focusless(true);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_accept_events(false);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_margins(gfx::Insets(kTooltipTopBottomMargin, kTooltipLeftRightMargin,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          kTooltipTopBottomMargin, kTooltipLeftRightMargin));
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_shadow(views::BubbleBorder::SMALL_SHADOW);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetLayoutManager(new views::FillLayout());
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The anchor may not have the widget in tests.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (anchor->GetWidget() && anchor->GetWidget()->GetNativeView()) {
961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    aura::Window* root_window =
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        anchor->GetWidget()->GetNativeView()->GetRootWindow();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_parent_window(ash::Shell::GetInstance()->GetContainer(
99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        root_window, ash::kShellWindowId_SettingBubbleContainer));
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  label_ = new views::Label;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  label_->SetEnabledColor(kTooltipTextColor);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddChildView(label_);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::BubbleDelegateView::CreateBubble(this);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::ShelfTooltipBubble::SetText(
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::string16& text) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  label_->SetText(text);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SizeToContents();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::ShelfTooltipBubble::Close() {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetWidget()) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_ = NULL;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetWidget()->Close();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::ShelfTooltipBubble::WindowClosing() {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::BubbleDelegateView::WindowClosing();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host_)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_->OnBubbleClosed(this);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size ShelfTooltipManager::ShelfTooltipBubble::GetPreferredSize() const {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size pref_size = views::BubbleDelegateView::GetPreferredSize();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pref_size.height() < kTooltipMinHeight)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pref_size.set_height(kTooltipMinHeight);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pref_size.width() > kTooltipMaxWidth)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pref_size.set_width(kTooltipMaxWidth);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pref_size;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ShelfTooltipManager::ShelfTooltipManager(
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ShelfLayoutManager* shelf_layout_manager,
1388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ShelfView* shelf_view)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : view_(NULL),
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      widget_(NULL),
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      anchor_(NULL),
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shelf_layout_manager_(shelf_layout_manager),
1438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      shelf_view_(shelf_view),
144558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      weak_factory_(this) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shelf_layout_manager)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shelf_layout_manager->AddObserver(this);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (Shell::HasInstance())
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Shell::GetInstance()->AddPreTargetHandler(this);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ShelfTooltipManager::~ShelfTooltipManager() {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CancelHidingAnimation();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Close();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shelf_layout_manager_)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shelf_layout_manager_->RemoveObserver(this);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (Shell::HasInstance())
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Shell::GetInstance()->RemovePreTargetHandler(this);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::ShowDelayed(views::View* anchor,
1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                      const base::string16& text) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (view_) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (timer_.get() && timer_->IsRunning()) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CancelHidingAnimation();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Close();
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shelf_layout_manager_ && !shelf_layout_manager_->IsVisible())
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateBubble(anchor, text);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetTimer();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::ShowImmediately(views::View* anchor,
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                          const base::string16& text) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (view_) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (timer_.get() && timer_->IsRunning())
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StopTimer();
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CancelHidingAnimation();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Close();
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shelf_layout_manager_ && !shelf_layout_manager_->IsVisible())
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateBubble(anchor, text);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShowInternal();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::Close() {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopTimer();
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (view_) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->Close();
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_ = NULL;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    widget_ = NULL;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::OnBubbleClosed(views::BubbleDelegateView* view) {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (view == view_) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_ = NULL;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    widget_ = NULL;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::UpdateArrow() {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (view_) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CancelHidingAnimation();
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Close();
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ShowImmediately(anchor_, text_);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::ResetTimer() {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (timer_.get() && timer_->IsRunning()) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    timer_->Reset();
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't start the timer if the shelf isn't visible.
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shelf_layout_manager_ && !shelf_layout_manager_->IsVisible())
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CreateTimer(kTooltipAppearanceDelay);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::StopTimer() {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer_.reset();
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool ShelfTooltipManager::IsVisible() {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (timer_.get() && timer_->IsRunning())
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return widget_ && widget_->IsVisible();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::CreateZeroDelayTimerForTest() {
2437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CreateTimer(0);
2447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::OnMouseEvent(ui::MouseEvent* event) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(event);
2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(event->target());
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!widget_ || !widget_->IsVisible())
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(view_);
2538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(shelf_view_);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Pressing the mouse button anywhere should close the tooltip.
25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (event->type() == ui::ET_MOUSE_PRESSED) {
25758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    CloseSoon();
25858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
25958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
26058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::Window* target = static_cast<aura::Window*>(event->target());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (widget_->GetNativeWindow()->GetRootWindow() != target->GetRootWindow()) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseSoon();
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  gfx::Point location_in_shelf_view = event->location();
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::Window::ConvertPointToTarget(
2698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      target, shelf_view_->GetWidget()->GetNativeWindow(),
2708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      &location_in_shelf_view);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (shelf_view_->ShouldHideTooltip(location_in_shelf_view)) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Because this mouse event may arrive to |view_|, here we just schedule
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the closing event rather than directly calling Close().
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseSoon();
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::OnTouchEvent(ui::TouchEvent* event) {
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::Window* target = static_cast<aura::Window*>(event->target());
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (widget_ && widget_->IsVisible() && widget_->GetNativeWindow() != target)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Close();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::OnGestureEvent(ui::GestureEvent* event) {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (widget_ && widget_->IsVisible()) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Because this mouse event may arrive to |view_|, here we just schedule
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the closing event rather than directly calling Close().
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseSoon();
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::OnCancelMode(ui::CancelModeEvent* event) {
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Close();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::WillDeleteShelf() {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shelf_layout_manager_ = NULL;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::WillChangeVisibilityState(
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ShelfVisibilityState new_state) {
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (new_state == SHELF_HIDDEN) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StopTimer();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Close();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::OnAutoHideStateChanged(ShelfAutoHideState new_state) {
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (new_state == SHELF_AUTO_HIDE_HIDDEN) {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StopTimer();
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // AutoHide state change happens during an event filter, so immediate close
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // may cause a crash in the HandleMouseEvent() after the filter.  So we just
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // schedule the Close here.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseSoon();
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::CancelHidingAnimation() {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!widget_ || !widget_->GetNativeView())
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::NativeView native_view = widget_->GetNativeView();
324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  wm::SetWindowVisibilityAnimationTransition(
325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      native_view, wm::ANIMATE_NONE);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::CloseSoon() {
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoopForUI::current()->PostTask(
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Bind(&ShelfTooltipManager::Close, weak_factory_.GetWeakPtr()));
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::ShowInternal() {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (view_)
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    view_->GetWidget()->Show();
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer_.reset();
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::CreateBubble(views::View* anchor,
3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                       const base::string16& text) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!view_);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  anchor_ = anchor;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  text_ = text;
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  views::BubbleBorder::Arrow arrow =
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      shelf_layout_manager_->SelectValueForShelfAlignment(
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          views::BubbleBorder::BOTTOM_CENTER,
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          views::BubbleBorder::LEFT_CENTER,
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          views::BubbleBorder::RIGHT_CENTER,
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          views::BubbleBorder::TOP_CENTER);
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  view_ = new ShelfTooltipBubble(anchor, arrow, this);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  widget_ = view_->GetWidget();
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view_->SetText(text_);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::NativeView native_view = widget_->GetNativeView();
359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  wm::SetWindowVisibilityAnimationType(
360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      native_view, wm::WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL);
361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  wm::SetWindowVisibilityAnimationTransition(
362a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      native_view, wm::ANIMATE_HIDE);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShelfTooltipManager::CreateTimer(int delay_in_ms) {
3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::OneShotTimer<ShelfTooltipManager>* new_timer =
3674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      new base::OneShotTimer<ShelfTooltipManager>();
3684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  new_timer->Start(FROM_HERE,
3694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                   base::TimeDelta::FromMilliseconds(delay_in_ms),
3704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                   this,
3714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                   &ShelfTooltipManager::ShowInternal);
3727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  timer_.reset(new_timer);
3737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
376