| Index: chrome/browser/chromeos/notifications/notification_panel.cc
|
| diff --git a/chrome/browser/chromeos/notifications/notification_panel.cc b/chrome/browser/chromeos/notifications/notification_panel.cc
|
| deleted file mode 100644
|
| index 49d6a01722dd196fbf1f6847cca543e371f688cb..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/chromeos/notifications/notification_panel.cc
|
| +++ /dev/null
|
| @@ -1,897 +0,0 @@
|
| -// 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.
|
| -
|
| -#include "chrome/browser/chromeos/notifications/notification_panel.h"
|
| -
|
| -#include <algorithm>
|
| -
|
| -#include "base/bind.h"
|
| -#include "chrome/browser/chromeos/notifications/balloon_collection_impl.h"
|
| -#include "chrome/browser/chromeos/notifications/balloon_view.h"
|
| -#include "chrome/common/chrome_notification_types.h"
|
| -#include "content/public/browser/notification_details.h"
|
| -#include "content/public/browser/notification_source.h"
|
| -#include "grit/generated_resources.h"
|
| -#include "third_party/cros_system_api/window_manager/chromeos_wm_ipc_enums.h"
|
| -#include "ui/base/l10n/l10n_util.h"
|
| -#include "ui/base/resource/resource_bundle.h"
|
| -#include "ui/gfx/canvas.h"
|
| -#include "ui/views/background.h"
|
| -#include "ui/views/controls/native/native_view_host.h"
|
| -#include "ui/views/controls/scroll_view.h"
|
| -#include "ui/views/widget/native_widget_gtk.h"
|
| -
|
| -#define SET_STATE(state) SetState(state, __PRETTY_FUNCTION__)
|
| -
|
| -using views::Widget;
|
| -
|
| -namespace {
|
| -// Minimum and maximum size of balloon content.
|
| -const int kBalloonMinWidth = 300;
|
| -const int kBalloonMaxWidth = 300;
|
| -const int kBalloonMinHeight = 24;
|
| -const int kBalloonMaxHeight = 120;
|
| -
|
| -// Maximum height of the notification panel.
|
| -// TODO(oshima): Get this from system's metrics.
|
| -const int kMaxPanelHeight = 400;
|
| -
|
| -// The duration for a new notification to become stale.
|
| -const int kStaleTimeoutInSeconds = 10;
|
| -
|
| -// Panel Background color
|
| -const SkColor kPanelBackground = 0xFFEEEEEE;
|
| -
|
| -using chromeos::BalloonViewImpl;
|
| -using chromeos::NotificationPanel;
|
| -
|
| -#if !defined(NDEBUG)
|
| -// A utility function to convert State enum to string.
|
| -const char* ToStr(const NotificationPanel::State state) {
|
| - switch (state) {
|
| - case NotificationPanel::FULL:
|
| - return "full";
|
| - case NotificationPanel::KEEP_SIZE:
|
| - return "keep_size";
|
| - case NotificationPanel::STICKY_AND_NEW:
|
| - return "sticky_new";
|
| - case NotificationPanel::MINIMIZED:
|
| - return "minimized";
|
| - case NotificationPanel::CLOSED:
|
| - return "closed";
|
| - default:
|
| - return "unknown";
|
| - }
|
| -}
|
| -#endif
|
| -
|
| -chromeos::BalloonViewImpl* GetBalloonViewOf(const Balloon* balloon) {
|
| - return static_cast<chromeos::BalloonViewImpl*>(balloon->view());
|
| -}
|
| -
|
| -// A Widget that covers entire ScrollView's viewport. Without this, all
|
| -// renderer's native gtk widgets are moved one by one via
|
| -// View::VisibleBoundsInRootChanged() notification, which makes scrolling not
|
| -// smooth.
|
| -class ViewportWidget : public views::Widget {
|
| - public:
|
| - explicit ViewportWidget(chromeos::NotificationPanel* panel)
|
| - : panel_(panel),
|
| - pointer_inside_panel_(false) {
|
| - }
|
| -
|
| - void UpdateControl() {
|
| - if (pointer_inside_panel_)
|
| - panel_->OnMouseMotion(last_point_);
|
| - }
|
| -
|
| - // views::Widget overrides:
|
| - virtual bool OnMouseEvent(const views::MouseEvent& event) OVERRIDE {
|
| - bool result = Widget::OnMouseEvent(event);
|
| - switch (event.type()) {
|
| - case ui::ET_MOUSE_MOVED:
|
| - OnMouseMoved(event);
|
| - break;
|
| - case ui::ET_MOUSE_EXITED:
|
| - OnMouseExited(event);
|
| - break;
|
| - default:
|
| - break;
|
| - }
|
| - return result;
|
| - }
|
| -
|
| - private:
|
| - void OnMouseMoved(const views::MouseEvent& event) {
|
| - // Convert the point to the panel's coordinate system.
|
| - Widget* top_level_widget = GetTopLevelWidget();
|
| - // TODO: remove cast when this extends Widget.
|
| - DCHECK(top_level_widget != static_cast<Widget*>(this));
|
| - gfx::Rect panel_rect(event.location(), gfx::Size());
|
| - Widget::ConvertRect(this, top_level_widget, &panel_rect);
|
| - last_point_ = panel_rect.origin();
|
| - pointer_inside_panel_ = true;
|
| - panel_->OnMouseMotion(last_point_);
|
| - }
|
| -
|
| - void OnMouseExited(const views::MouseEvent& event) {
|
| - // Filter gtk's fake mouse leave events that are issued when
|
| - // window activation changes.
|
| - if (event.location().x() == 0 && event.location().y() == 0)
|
| - return;
|
| -
|
| - // Leave notify can happen if the mouse moves into the child gdk window.
|
| - // Make sure the mouse is outside of the panel.
|
| - gfx::Rect bounds = GetWindowScreenBounds();
|
| - if (!bounds.Contains(event.location().x() + bounds.x(),
|
| - event.location().y() + bounds.y())) {
|
| - panel_->OnMouseLeave();
|
| - pointer_inside_panel_ = false;
|
| - }
|
| - }
|
| -
|
| - private:
|
| - chromeos::NotificationPanel* panel_;
|
| - gfx::Point last_point_;
|
| - bool pointer_inside_panel_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ViewportWidget);
|
| -};
|
| -
|
| -class BalloonSubContainer : public views::View {
|
| - public:
|
| - explicit BalloonSubContainer(int margin)
|
| - : margin_(margin) {
|
| - }
|
| -
|
| - virtual ~BalloonSubContainer() {}
|
| -
|
| - // views::View overrides.
|
| - virtual gfx::Size GetPreferredSize() {
|
| - return preferred_size_;
|
| - }
|
| -
|
| - virtual void Layout() {
|
| - // Layout bottom up
|
| - int height = 0;
|
| - for (int i = child_count() - 1; i >= 0; --i) {
|
| - views::View* child = child_at(i);
|
| - child->SetBounds(0, height, child->width(), child->height());
|
| - height += child->height() + margin_;
|
| - }
|
| - SchedulePaint();
|
| - }
|
| -
|
| - // Updates the bound so that it can show all balloons.
|
| - void UpdateBounds() {
|
| - int height = 0;
|
| - int max_width = 0;
|
| - for (int i = child_count() - 1; i >= 0; --i) {
|
| - views::View* child = child_at(i);
|
| - height += child->height() + margin_;
|
| - max_width = std::max(max_width, child->width());
|
| - }
|
| - if (height > 0)
|
| - height -= margin_;
|
| - preferred_size_.set_width(max_width);
|
| - preferred_size_.set_height(height);
|
| - SizeToPreferredSize();
|
| - }
|
| -
|
| - // Returns the bounds that covers new notifications.
|
| - gfx::Rect GetNewBounds() {
|
| - gfx::Rect rect;
|
| - for (int i = child_count() - 1; i >= 0; --i) {
|
| - BalloonViewImpl* view = static_cast<BalloonViewImpl*>(child_at(i));
|
| - if (!view->stale()) {
|
| - if (rect.IsEmpty()) {
|
| - rect = view->bounds();
|
| - } else {
|
| - rect = rect.Union(view->bounds());
|
| - }
|
| - }
|
| - }
|
| - return gfx::Rect(x(), y(), rect.width(), rect.height());
|
| - }
|
| -
|
| - // Returns # of new notifications.
|
| - int GetNewCount() {
|
| - int count = 0;
|
| - for (int i = child_count() - 1; i >= 0; --i) {
|
| - BalloonViewImpl* view = static_cast<BalloonViewImpl*>(child_at(i));
|
| - if (!view->stale())
|
| - count++;
|
| - }
|
| - return count;
|
| - }
|
| -
|
| - // Make all notifications stale.
|
| - void MakeAllStale() {
|
| - for (int i = child_count() - 1; i >= 0; --i) {
|
| - BalloonViewImpl* view = static_cast<BalloonViewImpl*>(child_at(i));
|
| - view->set_stale();
|
| - }
|
| - }
|
| -
|
| - void DismissAll() {
|
| - for (int i = child_count() - 1; i >= 0; --i) {
|
| - BalloonViewImpl* view = static_cast<BalloonViewImpl*>(child_at(i));
|
| - view->Close(true);
|
| - }
|
| - }
|
| -
|
| - BalloonViewImpl* FindBalloonView(const Notification& notification) {
|
| - for (int i = child_count() - 1; i >= 0; --i) {
|
| - BalloonViewImpl* view = static_cast<BalloonViewImpl*>(child_at(i));
|
| - if (view->IsFor(notification)) {
|
| - return view;
|
| - }
|
| - }
|
| - return NULL;
|
| - }
|
| -
|
| - BalloonViewImpl* FindBalloonView(const gfx::Point point) {
|
| - gfx::Point copy(point);
|
| - ConvertPointFromWidget(this, ©);
|
| - for (int i = child_count() - 1; i >= 0; --i) {
|
| - views::View* view = child_at(i);
|
| - if (view->bounds().Contains(copy))
|
| - return static_cast<BalloonViewImpl*>(view);
|
| - }
|
| - return NULL;
|
| - }
|
| -
|
| - // Returns true if the |view| is in the container.
|
| - // |view| can be a deleted pointer - we do not dereference it.
|
| - bool HasChildView(View* view) const {
|
| - for (int i = 0; i < child_count(); ++i) {
|
| - if (child_at(i) == view)
|
| - return true;
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - private:
|
| - gfx::Size preferred_size_;
|
| - int margin_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(BalloonSubContainer);
|
| -};
|
| -
|
| -} // namespace
|
| -
|
| -namespace chromeos {
|
| -
|
| -class BalloonContainer : public views::View {
|
| - public:
|
| - explicit BalloonContainer(int margin)
|
| - : margin_(margin),
|
| - sticky_container_(new BalloonSubContainer(margin)),
|
| - non_sticky_container_(new BalloonSubContainer(margin)) {
|
| - AddChildView(sticky_container_);
|
| - AddChildView(non_sticky_container_);
|
| - }
|
| - virtual ~BalloonContainer() {}
|
| -
|
| - // views::View overrides.
|
| - virtual void Layout() {
|
| - int margin =
|
| - (sticky_container_->child_count() != 0 &&
|
| - non_sticky_container_->child_count() != 0) ?
|
| - margin_ : 0;
|
| - sticky_container_->SetBounds(
|
| - 0, 0, width(), sticky_container_->height());
|
| - non_sticky_container_->SetBounds(
|
| - 0, sticky_container_->bounds().bottom() + margin,
|
| - width(), non_sticky_container_->height());
|
| - }
|
| -
|
| - virtual gfx::Size GetPreferredSize() {
|
| - return preferred_size_;
|
| - }
|
| -
|
| - // Returns the size that covers sticky and new notifications.
|
| - gfx::Size GetStickyNewSize() {
|
| - gfx::Rect sticky = sticky_container_->bounds();
|
| - gfx::Rect new_non_sticky = non_sticky_container_->GetNewBounds();
|
| - if (sticky.IsEmpty())
|
| - return new_non_sticky.size();
|
| - if (new_non_sticky.IsEmpty())
|
| - return sticky.size();
|
| - return sticky.Union(new_non_sticky).size();
|
| - }
|
| -
|
| - // Adds a ballon to the panel.
|
| - void Add(Balloon* balloon) {
|
| - BalloonViewImpl* view = GetBalloonViewOf(balloon);
|
| - GetContainerFor(balloon)->AddChildView(view);
|
| - }
|
| -
|
| - // Updates the position of the |balloon|.
|
| - bool Update(Balloon* balloon) {
|
| - BalloonViewImpl* view = GetBalloonViewOf(balloon);
|
| - View* container = NULL;
|
| - if (view->parent() == sticky_container_) {
|
| - container = sticky_container_;
|
| - } else if (view->parent() == non_sticky_container_) {
|
| - container = non_sticky_container_;
|
| - }
|
| - if (container) {
|
| - container->RemoveChildView(view);
|
| - container->AddChildView(view);
|
| - return true;
|
| - } else {
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - // Removes a ballon from the panel.
|
| - BalloonViewImpl* Remove(Balloon* balloon) {
|
| - BalloonViewImpl* view = GetBalloonViewOf(balloon);
|
| - GetContainerFor(balloon)->RemoveChildView(view);
|
| - return view;
|
| - }
|
| -
|
| - // Returns the number of notifications added to the panel.
|
| - int GetNotificationCount() {
|
| - return sticky_container_->child_count() +
|
| - non_sticky_container_->child_count();
|
| - }
|
| -
|
| - // Returns the # of new notifications.
|
| - int GetNewNotificationCount() {
|
| - return sticky_container_->GetNewCount() +
|
| - non_sticky_container_->GetNewCount();
|
| - }
|
| -
|
| - // Returns the # of sticky and new notifications.
|
| - int GetStickyNewNotificationCount() {
|
| - return sticky_container_->child_count() +
|
| - non_sticky_container_->GetNewCount();
|
| - }
|
| -
|
| - // Returns the # of sticky notifications.
|
| - int GetStickyNotificationCount() {
|
| - return sticky_container_->child_count();
|
| - }
|
| -
|
| - // Returns true if the |view| is contained in the panel.
|
| - // |view| can be a deleted pointer - we do not dereference it.
|
| - bool HasBalloonView(View* view) {
|
| - return sticky_container_->HasChildView(view) ||
|
| - non_sticky_container_->HasChildView(view);
|
| - }
|
| -
|
| - // Updates the bounds so that all notifications are visible.
|
| - void UpdateBounds() {
|
| - sticky_container_->UpdateBounds();
|
| - non_sticky_container_->UpdateBounds();
|
| - preferred_size_ = sticky_container_->GetPreferredSize();
|
| -
|
| - gfx::Size non_sticky_size = non_sticky_container_->GetPreferredSize();
|
| - int margin =
|
| - (!preferred_size_.IsEmpty() && !non_sticky_size.IsEmpty()) ?
|
| - margin_ : 0;
|
| - preferred_size_.Enlarge(0, non_sticky_size.height() + margin);
|
| - preferred_size_.set_width(std::max(
|
| - preferred_size_.width(), non_sticky_size.width()));
|
| - SizeToPreferredSize();
|
| - }
|
| -
|
| - void MakeAllStale() {
|
| - sticky_container_->MakeAllStale();
|
| - non_sticky_container_->MakeAllStale();
|
| - }
|
| -
|
| - void DismissAllNonSticky() {
|
| - non_sticky_container_->DismissAll();
|
| - }
|
| -
|
| - BalloonViewImpl* FindBalloonView(const Notification& notification) {
|
| - BalloonViewImpl* view = sticky_container_->FindBalloonView(notification);
|
| - return view ? view : non_sticky_container_->FindBalloonView(notification);
|
| - }
|
| -
|
| - BalloonViewImpl* FindBalloonView(const gfx::Point& point) {
|
| - BalloonViewImpl* view = sticky_container_->FindBalloonView(point);
|
| - return view ? view : non_sticky_container_->FindBalloonView(point);
|
| - }
|
| -
|
| - private:
|
| - BalloonSubContainer* GetContainerFor(Balloon* balloon) const {
|
| - BalloonViewImpl* view = GetBalloonViewOf(balloon);
|
| - return view->sticky() ?
|
| - sticky_container_ : non_sticky_container_;
|
| - }
|
| -
|
| - int margin_;
|
| - // Sticky/non-sticky ballon containers. They're child views and
|
| - // deleted when this container is deleted.
|
| - BalloonSubContainer* sticky_container_;
|
| - BalloonSubContainer* non_sticky_container_;
|
| - gfx::Size preferred_size_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(BalloonContainer);
|
| -};
|
| -
|
| -NotificationPanel::NotificationPanel()
|
| - : balloon_container_(NULL),
|
| - panel_widget_(NULL),
|
| - container_host_(NULL),
|
| - state_(CLOSED),
|
| - min_bounds_(0, 0, kBalloonMinWidth, kBalloonMinHeight),
|
| - stale_timeout_(1000 * kStaleTimeoutInSeconds),
|
| - active_(NULL),
|
| - scroll_to_(NULL) {
|
| - Init();
|
| -}
|
| -
|
| -NotificationPanel::~NotificationPanel() {
|
| - Hide();
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// NotificationPanel public.
|
| -
|
| -void NotificationPanel::Show() {
|
| - if (!panel_widget_) {
|
| - panel_widget_ = new views::Widget;
|
| - // TODO(oshima): Using window because Popup widget behaves weird
|
| - // when resizing. This needs to be investigated.
|
| - Widget::InitParams params(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
|
| - // Enable double buffering because the panel has both pure views
|
| - // control and native controls (scroll bar).
|
| - params.double_buffer = true;
|
| -
|
| - gfx::Rect bounds = GetPreferredBounds();
|
| - bounds = bounds.Union(min_bounds_);
|
| - params.bounds = bounds;
|
| - panel_widget_->Init(params);
|
| - // Set minimum bounds so that it can grow freely.
|
| - gtk_widget_set_size_request(GTK_WIDGET(panel_widget_->GetNativeView()),
|
| - min_bounds_.width(), min_bounds_.height());
|
| -
|
| - views::NativeViewHost* native = new views::NativeViewHost();
|
| - scroll_view_->SetContents(native);
|
| -
|
| - panel_widget_->SetContentsView(scroll_view_.get());
|
| -
|
| -#if defined(USE_AURA)
|
| - native->AttachToView(balloon_container_.get());
|
| -#else
|
| - // Add the view port after scroll_view is attached to the panel widget.
|
| - ViewportWidget* viewport_widget = new ViewportWidget(this);
|
| - container_host_ = viewport_widget;
|
| - container_host_->Init(
|
| - views::Widget::InitParams(views::Widget::InitParams::TYPE_CONTROL));
|
| - container_host_->SetContentsView(balloon_container_.get());
|
| - // The window_contents_ is onwed by the Widget. Increase ref count
|
| - // so that window_contents does not get deleted when detached.
|
| - g_object_ref(viewport_widget->GetNativeView());
|
| - native->Attach(viewport_widget->GetNativeView());
|
| -#endif
|
| - UnregisterNotification();
|
| - panel_controller_.reset(
|
| - new PanelController(this, GTK_WINDOW(panel_widget_->GetNativeView())));
|
| - panel_controller_->Init(false /* don't focus when opened */,
|
| - gfx::Rect(0, 0, kBalloonMinWidth, 1), 0,
|
| - WM_IPC_PANEL_USER_RESIZE_VERTICALLY);
|
| - registrar_.Add(this, chrome::NOTIFICATION_PANEL_STATE_CHANGED,
|
| - content::Source<PanelController>(panel_controller_.get()));
|
| - }
|
| - panel_widget_->Show();
|
| -}
|
| -
|
| -void NotificationPanel::Hide() {
|
| - balloon_container_->DismissAllNonSticky();
|
| - if (panel_widget_) {
|
| - if (container_host_)
|
| - container_host_->GetRootView()->RemoveChildView(balloon_container_.get());
|
| -
|
| - views::NativeViewHost* native =
|
| - static_cast<views::NativeViewHost*>(scroll_view_->GetContents());
|
| - native->Detach();
|
| - scroll_view_->SetContents(NULL);
|
| - if (container_host_) {
|
| - container_host_->Hide();
|
| - container_host_->CloseNow();
|
| - container_host_ = NULL;
|
| - }
|
| -
|
| - UnregisterNotification();
|
| - panel_controller_->Close();
|
| - MessageLoop::current()->DeleteSoon(FROM_HERE, panel_controller_.release());
|
| - // We need to remove & detach the scroll view from hierarchy to
|
| - // avoid GTK deleting child.
|
| - // TODO(oshima): handle this details in NativeWidgetGtk.
|
| - panel_widget_->GetRootView()->RemoveChildView(scroll_view_.get());
|
| - panel_widget_->Close();
|
| - panel_widget_ = NULL;
|
| - }
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// BalloonCollectionImpl::NotificationUI overrides.
|
| -
|
| -void NotificationPanel::Add(Balloon* balloon) {
|
| - balloon_container_->Add(balloon);
|
| - if (state_ == CLOSED || state_ == MINIMIZED)
|
| - SET_STATE(STICKY_AND_NEW);
|
| - Show();
|
| - // Don't resize the panel yet. The panel will be resized when WebKit tells
|
| - // the size in ResizeNotification.
|
| - UpdatePanel(false);
|
| - UpdateControl();
|
| - StartStaleTimer(balloon);
|
| - scroll_to_ = balloon;
|
| -}
|
| -
|
| -bool NotificationPanel::Update(Balloon* balloon) {
|
| - return balloon_container_->Update(balloon);
|
| -}
|
| -
|
| -void NotificationPanel::Remove(Balloon* balloon) {
|
| - BalloonViewImpl* view = balloon_container_->Remove(balloon);
|
| - if (view == active_)
|
| - active_ = NULL;
|
| - if (scroll_to_ == balloon)
|
| - scroll_to_ = NULL;
|
| -
|
| - // TODO(oshima): May be we shouldn't close
|
| - // if the mouse pointer is still on the panel.
|
| - if (balloon_container_->GetNotificationCount() == 0)
|
| - SET_STATE(CLOSED);
|
| - // no change to the state
|
| - if (state_ == KEEP_SIZE) {
|
| - // Just update the content.
|
| - UpdateContainerBounds();
|
| - } else {
|
| - if (state_ != CLOSED &&
|
| - balloon_container_->GetStickyNewNotificationCount() == 0)
|
| - SET_STATE(MINIMIZED);
|
| - UpdatePanel(true);
|
| - }
|
| - UpdateControl();
|
| -}
|
| -
|
| -void NotificationPanel::Show(Balloon* balloon) {
|
| - if (state_ == CLOSED || state_ == MINIMIZED)
|
| - SET_STATE(STICKY_AND_NEW);
|
| - Show();
|
| - UpdatePanel(true);
|
| - StartStaleTimer(balloon);
|
| - ScrollBalloonToVisible(balloon);
|
| -}
|
| -
|
| -void NotificationPanel::ResizeNotification(
|
| - Balloon* balloon, const gfx::Size& size) {
|
| - // restrict to the min & max sizes
|
| - gfx::Size real_size(
|
| - std::max(kBalloonMinWidth,
|
| - std::min(kBalloonMaxWidth, size.width())),
|
| - std::max(kBalloonMinHeight,
|
| - std::min(kBalloonMaxHeight, size.height())));
|
| -
|
| - // Don't allow balloons to shrink. This avoids flickering
|
| - // which sometimes rapidly reports alternating sizes. Special
|
| - // case for setting the minimum value.
|
| - gfx::Size old_size = balloon->content_size();
|
| - if (real_size.width() > old_size.width() ||
|
| - real_size.height() > old_size.height() ||
|
| - real_size == min_bounds_.size()) {
|
| - balloon->set_content_size(real_size);
|
| - GetBalloonViewOf(balloon)->Layout();
|
| - UpdatePanel(true);
|
| - if (scroll_to_ == balloon) {
|
| - ScrollBalloonToVisible(scroll_to_);
|
| - scroll_to_ = NULL;
|
| - }
|
| - }
|
| -}
|
| -
|
| -void NotificationPanel::SetActiveView(BalloonViewImpl* view) {
|
| - // Don't change the active view if it's same notification,
|
| - // or the notification is being closed.
|
| - if (active_ == view || (view && view->closed()))
|
| - return;
|
| - if (active_)
|
| - active_->Deactivated();
|
| - active_ = view;
|
| - if (active_)
|
| - active_->Activated();
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// PanelController overrides.
|
| -
|
| -string16 NotificationPanel::GetPanelTitle() {
|
| - return string16(l10n_util::GetStringUTF16(IDS_NOTIFICATION_PANEL_TITLE));
|
| -}
|
| -
|
| -SkBitmap NotificationPanel::GetPanelIcon() {
|
| - return SkBitmap();
|
| -}
|
| -
|
| -bool NotificationPanel::CanClosePanel() {
|
| - return true;
|
| -}
|
| -
|
| -void NotificationPanel::ClosePanel() {
|
| - SET_STATE(CLOSED);
|
| - UpdatePanel(false);
|
| -}
|
| -
|
| -void NotificationPanel::ActivatePanel() {
|
| - if (active_)
|
| - active_->Activated();
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// content::NotificationObserver overrides.
|
| -
|
| -void NotificationPanel::Observe(int type,
|
| - const content::NotificationSource& source,
|
| - const content::NotificationDetails& details) {
|
| - DCHECK(type == chrome::NOTIFICATION_PANEL_STATE_CHANGED);
|
| - PanelController::State* state =
|
| - reinterpret_cast<PanelController::State*>(details.map_key());
|
| - switch (*state) {
|
| - case PanelController::EXPANDED:
|
| - // Geting expanded in STICKY_AND_NEW or in KEEP_SIZE state means
|
| - // that a new notification is added, so just leave the
|
| - // state. Otherwise, expand to full.
|
| - if (state_ != STICKY_AND_NEW && state_ != KEEP_SIZE)
|
| - SET_STATE(FULL);
|
| - // When the panel is to be expanded, we either show all, or
|
| - // show only sticky/new, depending on the state.
|
| - UpdatePanel(false);
|
| - break;
|
| - case PanelController::MINIMIZED:
|
| - SET_STATE(MINIMIZED);
|
| - // Make all notifications stale when a user minimize the panel.
|
| - balloon_container_->MakeAllStale();
|
| - break;
|
| - case PanelController::INITIAL:
|
| - NOTREACHED() << "Transition to Initial state should not happen";
|
| - }
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// PanelController public.
|
| -
|
| -void NotificationPanel::OnMouseLeave() {
|
| - SetActiveView(NULL);
|
| - if (balloon_container_->GetNotificationCount() == 0)
|
| - SET_STATE(CLOSED);
|
| - UpdatePanel(true);
|
| -}
|
| -
|
| -void NotificationPanel::OnMouseMotion(const gfx::Point& point) {
|
| - SetActiveView(balloon_container_->FindBalloonView(point));
|
| - // We need to set the focus to scroll view to get mouse wheel
|
| - // working. Setting focus when mouse moves on the panel
|
| - // because focus may be taken by other view.
|
| - scroll_view_->RequestFocus();
|
| - // This method used to set KEEP_SIZE state. However,
|
| - // some html notifications may want to change their size,
|
| - // and setting KEEP_SIZE caused them to behave differently
|
| - // depending on whether user moved mouse over notification
|
| - // or not.
|
| -}
|
| -
|
| -NotificationPanelTester* NotificationPanel::GetTester() {
|
| - if (!tester_.get())
|
| - tester_.reset(new NotificationPanelTester(this));
|
| - return tester_.get();
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// NotificationPanel private.
|
| -
|
| -void NotificationPanel::Init() {
|
| - DCHECK(!panel_widget_);
|
| - balloon_container_.reset(new BalloonContainer(1));
|
| - balloon_container_->set_parent_owned(false);
|
| - balloon_container_->set_background(
|
| - views::Background::CreateSolidBackground(kPanelBackground));
|
| -
|
| - scroll_view_.reset(new views::ScrollView());
|
| - scroll_view_->set_focusable(true);
|
| - scroll_view_->set_parent_owned(false);
|
| - scroll_view_->set_background(
|
| - views::Background::CreateSolidBackground(SK_ColorWHITE));
|
| -}
|
| -
|
| -void NotificationPanel::UnregisterNotification() {
|
| - if (panel_controller_.get()) {
|
| - registrar_.Remove(
|
| - this, chrome::NOTIFICATION_PANEL_STATE_CHANGED,
|
| - content::Source<PanelController>(panel_controller_.get()));
|
| - }
|
| -}
|
| -
|
| -void NotificationPanel::ScrollBalloonToVisible(Balloon* balloon) {
|
| - BalloonViewImpl* view = GetBalloonViewOf(balloon);
|
| - if (!view->closed()) {
|
| - // We can't use View::ScrollRectToVisible because the viewport is not
|
| - // ancestor of the BalloonViewImpl.
|
| - // Use Widget's coordinate which is same as viewport's coordinates.
|
| - gfx::Point p(0, 0);
|
| - views::View::ConvertPointToWidget(view, &p);
|
| - gfx::Rect visible_rect(p.x(), p.y(), view->width(), view->height());
|
| - scroll_view_->ScrollContentsRegionToBeVisible(visible_rect);
|
| - }
|
| -}
|
| -
|
| -void NotificationPanel::UpdatePanel(bool update_container_size) {
|
| - if (update_container_size)
|
| - UpdateContainerBounds();
|
| - switch (state_) {
|
| - case KEEP_SIZE: {
|
| - gfx::Rect min_bounds = GetPreferredBounds();
|
| - gfx::Rect panel_bounds = panel_widget_->GetWindowScreenBounds();
|
| - if (min_bounds.height() < panel_bounds.height())
|
| - panel_widget_->SetBounds(min_bounds);
|
| - else if (min_bounds.height() > panel_bounds.height()) {
|
| - // need scroll bar
|
| - int width = balloon_container_->width() +
|
| - scroll_view_->GetScrollBarWidth();
|
| - panel_bounds.set_width(width);
|
| - panel_widget_->SetBounds(panel_bounds);
|
| - }
|
| -
|
| - // no change.
|
| - break;
|
| - }
|
| - case CLOSED:
|
| - Hide();
|
| - break;
|
| - case MINIMIZED:
|
| - balloon_container_->MakeAllStale();
|
| - if (panel_controller_.get())
|
| - panel_controller_->SetState(PanelController::MINIMIZED);
|
| - break;
|
| - case FULL:
|
| - if (panel_widget_) {
|
| - panel_widget_->SetBounds(GetPreferredBounds());
|
| - panel_controller_->SetState(PanelController::EXPANDED);
|
| - }
|
| - break;
|
| - case STICKY_AND_NEW:
|
| - if (panel_widget_) {
|
| - panel_widget_->SetBounds(GetStickyNewBounds());
|
| - panel_controller_->SetState(PanelController::EXPANDED);
|
| - }
|
| - break;
|
| - }
|
| -}
|
| -
|
| -void NotificationPanel::UpdateContainerBounds() {
|
| - balloon_container_->UpdateBounds();
|
| - views::NativeViewHost* native =
|
| - static_cast<views::NativeViewHost*>(scroll_view_->GetContents());
|
| - // Update from WebKit may arrive after the panel is closed/hidden
|
| - // and viewport widget is detached.
|
| - if (native) {
|
| - native->SetBoundsRect(balloon_container_->bounds());
|
| - scroll_view_->Layout();
|
| - }
|
| -}
|
| -
|
| -void NotificationPanel::UpdateControl() {
|
| - if (container_host_)
|
| - static_cast<ViewportWidget*>(container_host_)->UpdateControl();
|
| -}
|
| -
|
| -gfx::Rect NotificationPanel::GetPreferredBounds() {
|
| - gfx::Size pref_size = balloon_container_->GetPreferredSize();
|
| - int new_height = std::min(pref_size.height(), kMaxPanelHeight);
|
| - int new_width = pref_size.width();
|
| - // Adjust the width to avoid showing a horizontal scroll bar.
|
| - if (new_height != pref_size.height()) {
|
| - new_width += scroll_view_->GetScrollBarWidth();
|
| - }
|
| - return gfx::Rect(0, 0, new_width, new_height).Union(min_bounds_);
|
| -}
|
| -
|
| -gfx::Rect NotificationPanel::GetStickyNewBounds() {
|
| - gfx::Size pref_size = balloon_container_->GetPreferredSize();
|
| - gfx::Size sticky_size = balloon_container_->GetStickyNewSize();
|
| - int new_height = std::min(sticky_size.height(), kMaxPanelHeight);
|
| - int new_width = pref_size.width();
|
| - // Adjust the width to avoid showing a horizontal scroll bar.
|
| - if (new_height != pref_size.height())
|
| - new_width += scroll_view_->GetScrollBarWidth();
|
| - return gfx::Rect(0, 0, new_width, new_height).Union(min_bounds_);
|
| -}
|
| -
|
| -void NotificationPanel::StartStaleTimer(Balloon* balloon) {
|
| - BalloonViewImpl* view = GetBalloonViewOf(balloon);
|
| - MessageLoop::current()->PostDelayedTask(
|
| - FROM_HERE,
|
| - base::Bind(&NotificationPanel::OnStale, AsWeakPtr(), view),
|
| - stale_timeout_);
|
| -}
|
| -
|
| -void NotificationPanel::OnStale(BalloonViewImpl* view) {
|
| - // Note: |view| may point to deleted memory.
|
| - if (balloon_container_->HasBalloonView(view) && !view->stale()) {
|
| - view->set_stale();
|
| - // don't update panel on stale
|
| - if (state_ == KEEP_SIZE)
|
| - return;
|
| - if (balloon_container_->GetStickyNewNotificationCount() > 0) {
|
| - SET_STATE(STICKY_AND_NEW);
|
| - } else {
|
| - SET_STATE(MINIMIZED);
|
| - }
|
| - UpdatePanel(false);
|
| - }
|
| -}
|
| -
|
| -void NotificationPanel::SetState(State new_state, const char* name) {
|
| -#if !defined(NDEBUG)
|
| - DVLOG(1) << "state transition " << ToStr(state_) << " >> " << ToStr(new_state)
|
| - << " in " << name;
|
| -#endif
|
| - state_ = new_state;
|
| -}
|
| -
|
| -void NotificationPanel::MarkStale(const Notification& notification) {
|
| - BalloonViewImpl* view = balloon_container_->FindBalloonView(notification);
|
| - DCHECK(view);
|
| - OnStale(view);
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// NotificationPanelTester public.
|
| -
|
| -int NotificationPanelTester::GetNotificationCount() const {
|
| - return panel_->balloon_container_->GetNotificationCount();
|
| -}
|
| -
|
| -int NotificationPanelTester::GetStickyNotificationCount() const {
|
| - return panel_->balloon_container_->GetStickyNotificationCount();
|
| -}
|
| -
|
| -int NotificationPanelTester::GetNewNotificationCount() const {
|
| - return panel_->balloon_container_->GetNewNotificationCount();
|
| -}
|
| -
|
| -void NotificationPanelTester::SetStaleTimeout(int timeout) {
|
| - panel_->stale_timeout_ = timeout;
|
| -}
|
| -
|
| -void NotificationPanelTester::MarkStale(const Notification& notification) {
|
| - panel_->MarkStale(notification);
|
| -}
|
| -
|
| -PanelController* NotificationPanelTester::GetPanelController() const {
|
| - return panel_->panel_controller_.get();
|
| -}
|
| -
|
| -BalloonViewImpl* NotificationPanelTester::GetBalloonView(
|
| - BalloonCollectionImpl* collection,
|
| - const Notification& notification) {
|
| - Balloon* balloon = collection->FindBalloon(notification);
|
| - DCHECK(balloon);
|
| - return GetBalloonViewOf(balloon);
|
| -}
|
| -
|
| -bool NotificationPanelTester::IsVisible(const BalloonViewImpl* view) const {
|
| - gfx::Rect rect = panel_->scroll_view_->GetVisibleRect();
|
| - gfx::Point origin(0, 0);
|
| - views::View::ConvertPointToView(view, panel_->balloon_container_.get(),
|
| - &origin);
|
| - return rect.Contains(gfx::Rect(origin, view->size()));
|
| -}
|
| -
|
| -
|
| -bool NotificationPanelTester::IsActive(const BalloonViewImpl* view) const {
|
| - return panel_->active_ == view;
|
| -}
|
| -
|
| -} // namespace chromeos
|
|
|