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 18 class Balloon; 19 class Notification; 20 21 namespace views { 22 class ScrollView; 23 } // namespace views 24 25 namespace chromeos { 26 27 class BalloonContainer; 28 class BalloonViewImpl; 29 class 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 // 72 class 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 203 class 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