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 "ash/shelf/overflow_bubble.h"
6
7#include "ash/root_window_controller.h"
8#include "ash/shelf/overflow_bubble_view.h"
9#include "ash/shelf/shelf_layout_manager.h"
10#include "ash/shelf/shelf_view.h"
11#include "ash/shelf/shelf_widget.h"
12#include "ash/shell.h"
13#include "ash/system/tray/system_tray.h"
14#include "ui/aura/client/screen_position_client.h"
15#include "ui/aura/window_event_dispatcher.h"
16#include "ui/events/event.h"
17#include "ui/gfx/screen.h"
18#include "ui/views/widget/widget.h"
19
20namespace ash {
21
22OverflowBubble::OverflowBubble()
23    : bubble_(NULL),
24      anchor_(NULL),
25      shelf_view_(NULL) {
26}
27
28OverflowBubble::~OverflowBubble() {
29  Hide();
30}
31
32void OverflowBubble::Show(views::View* anchor, ShelfView* shelf_view) {
33  Hide();
34
35  bubble_ = new OverflowBubbleView();
36  bubble_->InitOverflowBubble(anchor, shelf_view);
37  shelf_view_ = shelf_view;
38  anchor_ = anchor;
39
40  Shell::GetInstance()->AddPreTargetHandler(this);
41
42  RootWindowController::ForWindow(anchor->GetWidget()->GetNativeView())->
43      GetSystemTray()->InitializeBubbleAnimations(bubble_->GetWidget());
44  bubble_->GetWidget()->AddObserver(this);
45  bubble_->GetWidget()->Show();
46}
47
48void OverflowBubble::Hide() {
49  if (!IsShowing())
50    return;
51
52  Shell::GetInstance()->RemovePreTargetHandler(this);
53  bubble_->GetWidget()->RemoveObserver(this);
54  bubble_->GetWidget()->Close();
55  bubble_ = NULL;
56  anchor_ = NULL;
57  shelf_view_ = NULL;
58}
59
60void OverflowBubble::HideBubbleAndRefreshButton() {
61  if (!IsShowing())
62    return;
63
64  views::View* anchor = anchor_;
65  Hide();
66  // Update overflow button (|anchor|) status when overflow bubble is hidden
67  // by outside event of overflow button.
68  anchor->SchedulePaint();
69}
70
71void OverflowBubble::ProcessPressedEvent(ui::LocatedEvent* event) {
72  aura::Window* target = static_cast<aura::Window*>(event->target());
73  gfx::Point event_location_in_screen = event->location();
74  aura::client::GetScreenPositionClient(target->GetRootWindow())->
75      ConvertPointToScreen(target, &event_location_in_screen);
76  if (!shelf_view_->IsShowingMenu() &&
77      !bubble_->GetBoundsInScreen().Contains(event_location_in_screen) &&
78      !anchor_->GetBoundsInScreen().Contains(event_location_in_screen)) {
79    HideBubbleAndRefreshButton();
80  }
81}
82
83void OverflowBubble::OnMouseEvent(ui::MouseEvent* event) {
84  if (event->type() == ui::ET_MOUSE_PRESSED)
85    ProcessPressedEvent(event);
86}
87
88void OverflowBubble::OnTouchEvent(ui::TouchEvent* event) {
89  if (event->type() == ui::ET_TOUCH_PRESSED)
90    ProcessPressedEvent(event);
91}
92
93void OverflowBubble::OnWidgetDestroying(views::Widget* widget) {
94  DCHECK(widget == bubble_->GetWidget());
95  bubble_ = NULL;
96  anchor_ = NULL;
97  shelf_view_ = NULL;
98  ShelfLayoutManager::ForShelf(
99      widget->GetNativeView())->shelf_widget()->shelf()->SchedulePaint();
100}
101
102}  // namespace ash
103