summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/notifications/notification_panel.h
blob: 7b795e45cbd6a6705f80df0c206aaf4ebd06fe2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Draws the view for the balloons.

#ifndef CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_NOTIFICATION_PANEL_H_
#define CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_NOTIFICATION_PANEL_H_

#include "base/task.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/chromeos/frame/panel_controller.h"
#include "chrome/browser/chromeos/notifications/balloon_collection_impl.h"
#include "chrome/common/notification_registrar.h"
#include "gfx/rect.h"

class Balloon;
class Notification;

namespace views {
class ScrollView;
}  // namespace views

namespace chromeos {

class BalloonContainer;
class BalloonViewImpl;
class NotificationPanelTester;

// NotificationPanel is a panel that displays notifications. It has
// several states and displays the different portion of notifications
// depending on in which state the panel is. The following shows
// how the panel's state changes in response to various events.
//
// TODO(oshima): add remove event and fix state transition graph below.
// Event List:
//   close: a user pressed close button on the title bar,
//          or the system closed the panel.
//   new : a new notification is added.
//   stale: one of new notifications became stale.
//   expand: a user pressed minimized panel to expand.
//   minimize: a user pressed the panel's title bar to minimize.
//   user: the user's mouse moved over the panel, indicates
//         that user is trying to interact with the panel.
// For state, see State enum's description below.
//
//
// [CLOSE]<-(event=close)-+     +--(event=stale, cond=has new|sticky)
//   |                    |     |         (event=new)
//   |                    |     V           |
//   +--(event=new)-->[STICKY_AND_NEW]----- +--------(event=user)
//   |                  ^           |                      |
//   |                  |  (event=stale,                   V
//   |                  |  cond=has new, no sticy)  +[ KEEP_SIZE ]<-+
//   |          (event=new)   (event=minimize)      |      |        |
//   |                  |           |               |      |        |
//   |                  |           |  (event=minimize)(event=close)|
//   |                  |           +---------------+      |        |
//   |                  |           V                      V        |
//   |                  [ MINIMIZED ]---(event=close)--> [CLOSE]    |
//   |                     |     ^                                  |
//   |                     |     |                                  |
//   |          (event=expand)  (event=minmize)                 (event=user)
//   |                     V     |                                  |
//   +--(event=open)---->[  FULL  ]-------------+-------------------+
//                         |     ^              |
//              (event=close)    +-------(event=stale)(event=new)
//                         |
//          [CLOSE] <------+
//
class NotificationPanel : public PanelController::Delegate,
                          public BalloonCollectionImpl::NotificationUI,
                          public NotificationObserver {
 public:
  enum State {
    FULL,  // Show all notifications
    KEEP_SIZE,  // Don't change the size.
    STICKY_AND_NEW,  // Show only new and sticky notifications.
    MINIMIZED,  // The panel is minimized.
    CLOSED,  // The panel is closed.
  };

  NotificationPanel();
  virtual ~NotificationPanel();

  // Shows/Hides the Panel.
  void Show();
  void Hide();

  // BalloonCollectionImpl::NotificationUI overrides..
  virtual void Add(Balloon* balloon);
  virtual bool Update(Balloon* balloon);
  virtual void Remove(Balloon* balloon);
  virtual void Show(Balloon* balloon);
  virtual void ResizeNotification(Balloon* balloon,
                                  const gfx::Size& size);
  virtual void SetActiveView(BalloonViewImpl* view);

  // PanelController overrides.
  virtual string16 GetPanelTitle();
  virtual SkBitmap GetPanelIcon();
  virtual void ClosePanel();

  // NotificationObserver overrides:
  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);

  // Called when a mouse left the panel window.
  void OnMouseLeave();
  void OnMouseMotion(const gfx::Point& point);

  NotificationPanelTester* GetTester();

 private:
  friend class NotificationPanelTester;

  void Init();

  // Unregister the panel's state change notification.
  void UnregisterNotification();

  // Update the Panel Size according to its state.
  void UpdatePanel(bool update_panel_size);

  // Scroll the panel so that the |balloon| is visible.
  void ScrollBalloonToVisible(Balloon* balloon);

  // Update the container's bounds so that it can show all notifications.
  void UpdateContainerBounds();

  // Update the notification's control view state.
  void UpdateControl();

  // Returns the panel's preferred bounds in the screen's coordinates.
  // The position will be controlled by window manager so
  // the origin is always (0, 0).
  gfx::Rect GetPreferredBounds();

  // Returns the bounds that covers sticky and new notifications.
  gfx::Rect GetStickyNewBounds();

  void StartStaleTimer(Balloon* balloon);

  // A callback function that is called when the notification
  // (that the view is associated with) becomes stale after a timeout.
  void OnStale(BalloonViewImpl* view);

  // Set the state. It can also print the
  void SetState(State, const char* method_name);

  // Mark the given notification as stale.
  void MarkStale(const Notification& notification);

  // Contains all notifications. This is owned by the panel so that we can
  // re-attach to the widget when closing and opening the panel.
  scoped_ptr<BalloonContainer> balloon_container_;

  // The notification panel's widget.
  views::Widget* panel_widget_;

  // The notification panel's widget.
  views::Widget* container_host_;

  // Panel controller for the notification panel.
  // This is owned by the panel to compute the panel size before
  // actually opening the panel.
  scoped_ptr<PanelController> panel_controller_;

  // A scrollable parent of the BalloonContainer.
  scoped_ptr<views::ScrollView> scroll_view_;

  // Panel's state.
  State state_;

  ScopedRunnableMethodFactory<NotificationPanel> task_factory_;

  // The minimum size of a notification.
  gfx::Rect min_bounds_;

  // Stale timeout.
  int stale_timeout_;

  // A registrar to subscribe PANEL_STATE_CHANGED event.
  NotificationRegistrar registrar_;

  // The notification a mouse pointer is currently on. NULL if the mouse
  // is out of the panel.
  BalloonViewImpl* active_;

  // A balloon that should be visible when it gets some size.
  Balloon* scroll_to_;

  // An object that provides interfacce for tests.
  scoped_ptr<NotificationPanelTester> tester_;

  DISALLOW_COPY_AND_ASSIGN(NotificationPanel);
};

class NotificationPanelTester {
 public:
  explicit NotificationPanelTester(NotificationPanel* panel)
      : panel_(panel) {
  }

  NotificationPanel::State state() {
    return panel_->state_;
  }

  // Returns number of of sticky and new notifications.
  int GetNotificationCount() const;

  // Returns number of new notifications.
  int GetNewNotificationCount() const;

  // Returns number of of sticky notifications.
  int GetStickyNotificationCount() const;

  // Sets the timeout for a notification to become stale.
  void SetStaleTimeout(int timeout);

  // Mark the given notification as stale.
  void MarkStale(const Notification& notification);

  // Returns the notification panel's PanelController.
  PanelController* GetPanelController() const;

  // Returns the BalloonView object of the notification.
  BalloonViewImpl* GetBalloonView(BalloonCollectionImpl* collection,
                                  const Notification& notification);

  // True if the view is in visible in the ScrollView.
  bool IsVisible(const BalloonViewImpl* view) const;

  // True if the view is currently active.
  bool IsActive(const BalloonViewImpl* view) const;

 private:
  NotificationPanel* panel_;
  DISALLOW_COPY_AND_ASSIGN(NotificationPanelTester);
};

}  // namespace chromeos

#endif  // CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_NOTIFICATION_PANEL_H_