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// Draws the view for the balloons. 6 7#ifndef CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_NOTIFICATION_PANEL_H_ 8#define CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_NOTIFICATION_PANEL_H_ 9#pragma once 10 11#include "base/memory/scoped_ptr.h" 12#include "base/task.h" 13#include "chrome/browser/chromeos/frame/panel_controller.h" 14#include "chrome/browser/chromeos/notifications/balloon_collection_impl.h" 15#include "content/common/notification_registrar.h" 16#include "ui/gfx/rect.h" 17 18class Balloon; 19class Notification; 20 21namespace views { 22class ScrollView; 23} // namespace views 24 25namespace chromeos { 26 27class BalloonContainer; 28class BalloonViewImpl; 29class NotificationPanelTester; 30 31// NotificationPanel is a panel that displays notifications. It has 32// several states and displays the different portion of notifications 33// depending on in which state the panel is. The following shows 34// how the panel's state changes in response to various events. 35// 36// TODO(oshima): add remove event and fix state transition graph below. 37// Event List: 38// close: a user pressed close button on the title bar, 39// or the system closed the panel. 40// new : a new notification is added. 41// stale: one of new notifications became stale. 42// expand: a user pressed minimized panel to expand. 43// minimize: a user pressed the panel's title bar to minimize. 44// user: the user's mouse moved over the panel, indicates 45// that user is trying to interact with the panel. 46// For state, see State enum's description below. 47// 48// 49// [CLOSE]<-(event=close)-+ +--(event=stale, cond=has new|sticky) 50// | | | (event=new) 51// | | V | 52// +--(event=new)-->[STICKY_AND_NEW]----- +--------(event=user) 53// | ^ | | 54// | | (event=stale, V 55// | | cond=has new, no sticy) +[ KEEP_SIZE ]<-+ 56// | (event=new) (event=minimize) | | | 57// | | | | | | 58// | | | (event=minimize)(event=close)| 59// | | +---------------+ | | 60// | | V V | 61// | [ MINIMIZED ]---(event=close)--> [CLOSE] | 62// | | ^ | 63// | | | | 64// | (event=expand) (event=minmize) (event=user) 65// | V | | 66// +--(event=open)---->[ FULL ]-------------+-------------------+ 67// | ^ | 68// (event=close) +-------(event=stale)(event=new) 69// | 70// [CLOSE] <------+ 71// 72class NotificationPanel : public PanelController::Delegate, 73 public BalloonCollectionImpl::NotificationUI, 74 public NotificationObserver { 75 public: 76 enum State { 77 FULL, // Show all notifications 78 KEEP_SIZE, // Don't change the size. 79 STICKY_AND_NEW, // Show only new and sticky notifications. 80 MINIMIZED, // The panel is minimized. 81 CLOSED, // The panel is closed. 82 }; 83 84 NotificationPanel(); 85 virtual ~NotificationPanel(); 86 87 // Shows/Hides the Panel. 88 void Show(); 89 void Hide(); 90 91 // BalloonCollectionImpl::NotificationUI overrides.. 92 virtual void Add(Balloon* balloon); 93 virtual bool Update(Balloon* balloon); 94 virtual void Remove(Balloon* balloon); 95 virtual void Show(Balloon* balloon); 96 virtual void ResizeNotification(Balloon* balloon, 97 const gfx::Size& size); 98 virtual void SetActiveView(BalloonViewImpl* view); 99 100 // PanelController::Delegate overrides. 101 virtual string16 GetPanelTitle(); 102 virtual SkBitmap GetPanelIcon(); 103 virtual bool CanClosePanel(); 104 virtual void ClosePanel(); 105 virtual void ActivatePanel(); 106 107 // NotificationObserver overrides: 108 virtual void Observe(NotificationType type, 109 const NotificationSource& source, 110 const NotificationDetails& details); 111 112 // Called when a mouse left the panel window. 113 void OnMouseLeave(); 114 void OnMouseMotion(const gfx::Point& point); 115 116 NotificationPanelTester* GetTester(); 117 118 private: 119 friend class NotificationPanelTester; 120 121 void Init(); 122 123 // Unregister the panel's state change notification. 124 void UnregisterNotification(); 125 126 // Update the Panel Size according to its state. 127 void UpdatePanel(bool update_panel_size); 128 129 // Scroll the panel so that the |balloon| is visible. 130 void ScrollBalloonToVisible(Balloon* balloon); 131 132 // Update the container's bounds so that it can show all notifications. 133 void UpdateContainerBounds(); 134 135 // Update the notification's control view state. 136 void UpdateControl(); 137 138 // Returns the panel's preferred bounds in the screen's coordinates. 139 // The position will be controlled by window manager so 140 // the origin is always (0, 0). 141 gfx::Rect GetPreferredBounds(); 142 143 // Returns the bounds that covers sticky and new notifications. 144 gfx::Rect GetStickyNewBounds(); 145 146 void StartStaleTimer(Balloon* balloon); 147 148 // A callback function that is called when the notification 149 // (that the view is associated with) becomes stale after a timeout. 150 void OnStale(BalloonViewImpl* view); 151 152 // Set the state. It can also print the 153 void SetState(State, const char* method_name); 154 155 // Mark the given notification as stale. 156 void MarkStale(const Notification& notification); 157 158 // Contains all notifications. This is owned by the panel so that we can 159 // re-attach to the widget when closing and opening the panel. 160 scoped_ptr<BalloonContainer> balloon_container_; 161 162 // The notification panel's widget. 163 views::Widget* panel_widget_; 164 165 // The notification panel's widget. 166 views::Widget* container_host_; 167 168 // Panel controller for the notification panel. 169 // This is owned by the panel to compute the panel size before 170 // actually opening the panel. 171 scoped_ptr<PanelController> panel_controller_; 172 173 // A scrollable parent of the BalloonContainer. 174 scoped_ptr<views::ScrollView> scroll_view_; 175 176 // Panel's state. 177 State state_; 178 179 ScopedRunnableMethodFactory<NotificationPanel> task_factory_; 180 181 // The minimum size of a notification. 182 gfx::Rect min_bounds_; 183 184 // Stale timeout. 185 int stale_timeout_; 186 187 // A registrar to subscribe PANEL_STATE_CHANGED event. 188 NotificationRegistrar registrar_; 189 190 // The notification a mouse pointer is currently on. NULL if the mouse 191 // is out of the panel. 192 BalloonViewImpl* active_; 193 194 // A balloon that should be visible when it gets some size. 195 Balloon* scroll_to_; 196 197 // An object that provides interfacce for tests. 198 scoped_ptr<NotificationPanelTester> tester_; 199 200 DISALLOW_COPY_AND_ASSIGN(NotificationPanel); 201}; 202 203class NotificationPanelTester { 204 public: 205 explicit NotificationPanelTester(NotificationPanel* panel) 206 : panel_(panel) { 207 } 208 209 NotificationPanel::State state() { 210 return panel_->state_; 211 } 212 213 // Returns number of of sticky and new notifications. 214 int GetNotificationCount() const; 215 216 // Returns number of new notifications. 217 int GetNewNotificationCount() const; 218 219 // Returns number of of sticky notifications. 220 int GetStickyNotificationCount() const; 221 222 // Sets the timeout for a notification to become stale. 223 void SetStaleTimeout(int timeout); 224 225 // Mark the given notification as stale. 226 void MarkStale(const Notification& notification); 227 228 // Returns the notification panel's PanelController. 229 PanelController* GetPanelController() const; 230 231 // Returns the BalloonView object of the notification. 232 BalloonViewImpl* GetBalloonView(BalloonCollectionImpl* collection, 233 const Notification& notification); 234 235 // True if the view is in visible in the ScrollView. 236 bool IsVisible(const BalloonViewImpl* view) const; 237 238 // True if the view is currently active. 239 bool IsActive(const BalloonViewImpl* view) const; 240 241 private: 242 NotificationPanel* panel_; 243 DISALLOW_COPY_AND_ASSIGN(NotificationPanelTester); 244}; 245 246} // namespace chromeos 247 248#endif // CHROME_BROWSER_CHROMEOS_NOTIFICATIONS_NOTIFICATION_PANEL_H_ 249