C++程序  |  249行  |  8.25 KB

// 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_