// Copyright (c) 2011 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_
#pragma once
#include "base/memory/scoped_ptr.h"
#include "base/task.h"
#include "chrome/browser/chromeos/frame/panel_controller.h"
#include "chrome/browser/chromeos/notifications/balloon_collection_impl.h"
#include "content/common/notification_registrar.h"
#include "ui/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::Delegate overrides.
virtual string16 GetPanelTitle();
virtual SkBitmap GetPanelIcon();
virtual bool CanClosePanel();
virtual void ClosePanel();
virtual void ActivatePanel();
// 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_