1// Copyright (c) 2011 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#ifndef CHROME_BROWSER_UI_VIEWS_BUBBLE_BUBBLE_H_
6#define CHROME_BROWSER_UI_VIEWS_BUBBLE_BUBBLE_H_
7#pragma once
8
9#include "chrome/browser/ui/views/bubble/bubble_border.h"
10#include "ui/base/animation/animation_delegate.h"
11#include "views/accelerator.h"
12#include "views/view.h"
13
14#if defined(OS_WIN)
15#include "views/widget/widget_win.h"
16#elif defined(OS_LINUX)
17#include "views/widget/widget_gtk.h"
18#endif
19
20// Bubble is used to display an arbitrary view above all other windows.
21// Think of Bubble as a tooltip that allows you to embed an arbitrary view
22// in the tooltip. Additionally the Bubble renders an arrow pointing at
23// the region the info bubble is providing the information about.
24//
25// To use an Bubble, invoke Show() and it'll take care of the rest.  The Bubble
26// insets the contents for you, so the contents typically shouldn't have any
27// additional margins.
28
29class BorderContents;
30#if defined(OS_WIN)
31class BorderWidgetWin;
32#endif
33class Bubble;
34
35namespace gfx {
36class Path;
37}
38
39namespace ui {
40class SlideAnimation;
41}
42
43namespace views {
44class Widget;
45}
46
47class BubbleDelegate {
48 public:
49  // Called when the Bubble is closing and is about to be deleted.
50  // |closed_by_escape| is true if the close is the result of the user pressing
51  // escape.
52  virtual void BubbleClosing(Bubble* bubble, bool closed_by_escape) = 0;
53
54  // Whether the Bubble should be closed when the Esc key is pressed.
55  virtual bool CloseOnEscape() = 0;
56
57  // Whether the Bubble should fade in when opening. When trying to determine
58  // whether to use FadeIn, consider whether the bubble is shown as a direct
59  // result of a user action or not. For example, if the bubble is being shown
60  // as a direct result of a mouse-click, we should not use FadeIn. However, if
61  // the bubble appears as a notification that something happened in the
62  // background, we use FadeIn.
63  virtual bool FadeInOnShow() = 0;
64
65  // The name of the window to which this delegate belongs.
66  virtual std::wstring accessible_name();
67};
68
69// TODO(sky): this code is ifdef-tastic. It might be cleaner to refactor the
70// WidgetFoo subclass into a separate class that calls into Bubble.
71// That way Bubble has no (or very few) ifdefs.
72class Bubble
73#if defined(OS_WIN)
74    : public views::WidgetWin,
75#elif defined(OS_LINUX)
76    : public views::WidgetGtk,
77#endif
78      public views::AcceleratorTarget,
79      public ui::AnimationDelegate {
80 public:
81  // Shows the Bubble.
82  // |parent| is set as the parent window.
83  // |contents| are the contents shown in the bubble.
84  // |position_relative_to| is a rect in screen coordinates at which the Bubble
85  // will point.
86  // Show() takes ownership of |contents| and deletes the created Bubble when
87  // another window is activated. You can explicitly close the bubble by
88  // invoking Close().
89  // |arrow_location| specifies preferred bubble alignment.
90  // You may provide an optional |delegate| to:
91  //     - Be notified when the Bubble is closed.
92  //     - Prevent the Bubble from being closed when the Escape key is
93  //       pressed (the default behavior).
94  static Bubble* Show(views::Widget* parent,
95                      const gfx::Rect& position_relative_to,
96                      BubbleBorder::ArrowLocation arrow_location,
97                      views::View* contents,
98                      BubbleDelegate* delegate);
99
100#if defined(OS_CHROMEOS)
101  // Shows the Bubble without grabbing the focus. Others are the same as
102  // above.  TYPE_POPUP widget is used to achieve the focusless effect.
103  // If |show_while_screen_is_locked| is true, a property is set telling the
104  // window manager to continue showing the bubble even while the screen is
105  // locked.
106  static Bubble* ShowFocusless(views::Widget* parent,
107                               const gfx::Rect& position_relative_to,
108                               BubbleBorder::ArrowLocation arrow_location,
109                               views::View* contents,
110                               BubbleDelegate* delegate,
111                               bool show_while_screen_is_locked);
112#endif
113
114  // Resizes and potentially moves the Bubble to best accommodate the
115  // contents preferred size.
116  void SizeToContents();
117
118  // Whether the Bubble should fade away when it closes. Generally speaking,
119  // we use FadeOut when the user selects something within the bubble that
120  // causes the bubble to dismiss. We don't use it when the bubble gets
121  // deactivated as a result of clicking outside the bubble.
122  void set_fade_away_on_close(bool fade_away_on_close) {
123    fade_away_on_close_ = fade_away_on_close;
124  }
125
126  // Overridden from WidgetWin:
127  virtual void Close();
128
129  // Overridden from ui::AnimationDelegate:
130  virtual void AnimationEnded(const ui::Animation* animation);
131  virtual void AnimationProgressed(const ui::Animation* animation);
132
133  static const SkColor kBackgroundColor;
134
135 protected:
136  Bubble();
137#if defined(OS_CHROMEOS)
138  Bubble(views::WidgetGtk::Type type, bool show_while_screen_is_locked);
139#endif
140  virtual ~Bubble();
141
142  // Creates the Bubble.
143  virtual void InitBubble(views::Widget* parent,
144                          const gfx::Rect& position_relative_to,
145                          BubbleBorder::ArrowLocation arrow_location,
146                          views::View* contents,
147                          BubbleDelegate* delegate);
148
149  // Instantiates and returns the BorderContents this Bubble should use.
150  // Subclasses can return their own BorderContents implementation.
151  virtual BorderContents* CreateBorderContents();
152
153#if defined(OS_WIN)
154  // Overridden from WidgetWin:
155  virtual void OnActivate(UINT action, BOOL minimized, HWND window);
156#elif defined(OS_LINUX)
157  // Overridden from WidgetGtk:
158  virtual void IsActiveChanged();
159#endif
160
161#if defined(OS_WIN)
162  // The window used to render the padding, border and arrow.
163  BorderWidgetWin* border_;
164#elif defined(OS_LINUX)
165  // The view displaying the border.
166  BorderContents* border_contents_;
167#endif
168
169 private:
170  enum ShowStatus {
171    kOpen,
172    kClosing,
173    kClosed
174  };
175
176  // Closes the window notifying the delegate. |closed_by_escape| is true if
177  // the close is the result of pressing escape.
178  void DoClose(bool closed_by_escape);
179
180  // Animates to a visible state.
181  void FadeIn();
182  // Animates to a hidden state.
183  void FadeOut();
184
185  // Animates to a visible/hidden state (visible if |fade_in| is true).
186  void Fade(bool fade_in);
187
188  // Overridden from AcceleratorTarget:
189  virtual bool AcceleratorPressed(const views::Accelerator& accelerator);
190
191  // The delegate, if any.
192  BubbleDelegate* delegate_;
193
194  // The animation used to fade the bubble out.
195  scoped_ptr<ui::SlideAnimation> animation_;
196
197  // The current visibility status of the bubble.
198  ShowStatus show_status_;
199
200  // Whether to fade away when the bubble closes.
201  bool fade_away_on_close_;
202
203#if defined(OS_CHROMEOS)
204  // Should we set a property telling the window manager to show this window
205  // onscreen even when the screen is locked?
206  bool show_while_screen_is_locked_;
207#endif
208
209  gfx::Rect position_relative_to_;
210  BubbleBorder::ArrowLocation arrow_location_;
211
212  views::View* contents_;
213
214  DISALLOW_COPY_AND_ASSIGN(Bubble);
215};
216
217#endif  // CHROME_BROWSER_UI_VIEWS_BUBBLE_BUBBLE_H_
218