| Index: ui/message_center/message_center_tray.cc
 | 
| diff --git a/ui/message_center/message_center_tray.cc b/ui/message_center/message_center_tray.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..9db7e07ebc45b6011b9f8752eeb4669d0a5ed88f
 | 
| --- /dev/null
 | 
| +++ b/ui/message_center/message_center_tray.cc
 | 
| @@ -0,0 +1,270 @@
 | 
| +// Copyright (c) 2012 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.
 | 
| +
 | 
| +#include "ui/message_center/message_center_tray.h"
 | 
| +
 | 
| +#include "base/memory/singleton.h"
 | 
| +#include "base/utf_string_conversions.h"
 | 
| +#include "ui/message_center/message_center_bubble.h"
 | 
| +#include "ui/message_center/message_popup_bubble.h"
 | 
| +#include "ui/views/bubble/tray_bubble_view.h"
 | 
| +#include "ui/views/widget/widget.h"
 | 
| +
 | 
| +namespace {
 | 
| +
 | 
| +// Helper class that owns the MessageBubbleBase and listens to widget closing
 | 
| +// events.
 | 
| +class WebNotificationBubbleWrapper : public views::WidgetObserver {
 | 
| + public:
 | 
| +  WebNotificationBubbleWrapper(
 | 
| +      ui::MessageCenterTray* tray,
 | 
| +      message_center::MessageBubbleBase* bubble,
 | 
| +      views::TrayBubbleView::InitParams init_params,
 | 
| +      gfx::NativeWindow bubble_window_container,
 | 
| +      views::View* anchor_view);
 | 
| +  virtual ~WebNotificationBubbleWrapper();
 | 
| +  // Convenience accessors.
 | 
| +  message_center::MessageBubbleBase* message_bubble() const {
 | 
| +    return message_bubble_.get();
 | 
| +  }
 | 
| +  views::TrayBubbleView* bubble_view() const {
 | 
| +    return message_bubble_->bubble_view();
 | 
| +  }
 | 
| +  bool IsMessageBubbleVisible();
 | 
| +
 | 
| +  // views::WidgetObserver overrides:
 | 
| +  virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE;
 | 
| +
 | 
| + private:
 | 
| +  scoped_ptr<message_center::MessageBubbleBase> message_bubble_;
 | 
| +  views::TrayBubbleView* bubble_view_;  // unowned
 | 
| +  views::Widget* bubble_widget_;
 | 
| +  ui::MessageCenterTray* tray_;
 | 
| +  DISALLOW_COPY_AND_ASSIGN(WebNotificationBubbleWrapper);
 | 
| +};
 | 
| +
 | 
| +WebNotificationBubbleWrapper::WebNotificationBubbleWrapper(
 | 
| +    ui::MessageCenterTray* tray,
 | 
| +    message_center::MessageBubbleBase* bubble,
 | 
| +    views::TrayBubbleView::InitParams init_params,
 | 
| +    gfx::NativeWindow bubble_window_container,
 | 
| +    views::View* anchor_view) :
 | 
| +      tray_(tray) {
 | 
| +  message_bubble_.reset(bubble);
 | 
| +
 | 
| +  init_params.close_on_deactivate = false;
 | 
| +  init_params.anchor_type = views::TrayBubbleView::ANCHOR_TYPE_TRAY;
 | 
| +
 | 
| +  bubble_view_ = views::TrayBubbleView::Create(
 | 
| +      bubble_window_container,
 | 
| +      anchor_view,
 | 
| +      tray_,
 | 
| +      &init_params);
 | 
| +
 | 
| +  bubble_widget_ = views::BubbleDelegateView::CreateBubble(bubble_view_);
 | 
| +  bubble_widget_->AddObserver(this);
 | 
| +  bubble_widget_->StackAtTop();
 | 
| +  bubble_widget_->SetAlwaysOnTop(true);
 | 
| +  bubble_widget_->Activate();
 | 
| +
 | 
| +  bubble_view_->InitializeAndShowBubble();
 | 
| +
 | 
| +  bubble_view_->set_close_on_deactivate(true);
 | 
| +  bubble->InitializeContents(bubble_view_);
 | 
| +}
 | 
| +
 | 
| +WebNotificationBubbleWrapper::~WebNotificationBubbleWrapper() {
 | 
| +  if (bubble_widget_) {
 | 
| +    bubble_widget_->RemoveObserver(this);
 | 
| +    bubble_widget_->Close();
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void WebNotificationBubbleWrapper::OnWidgetClosing(
 | 
| +    views::Widget* widget) {
 | 
| +  if (widget == bubble_widget_) {
 | 
| +    bubble_widget_->RemoveObserver(this);
 | 
| +    bubble_widget_->Close();
 | 
| +    if (bubble_view_) {
 | 
| +      tray_->HideBubble(bubble_view_);
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +}  // namespace
 | 
| +
 | 
| +namespace ui {
 | 
| +
 | 
| +MessageCenterTray::MessageCenterTray(MessageCenterTrayHost* host)
 | 
| +    : host_(host) {
 | 
| +  message_center_ = new message_center::MessageCenter();
 | 
| +  message_center_->AddObserver(this);
 | 
| +}
 | 
| +
 | 
| +MessageCenterTray::~MessageCenterTray() {
 | 
| +  message_center_->RemoveObserver(this);
 | 
| +  popup_bubble_.reset();
 | 
| +}
 | 
| +
 | 
| +void MessageCenterTray::ShowMessageCenterBubble() {
 | 
| +  if (message_center_bubble_.get())
 | 
| +    return;
 | 
| +
 | 
| +  host_->OnShowMessageCenterBubble();
 | 
| +
 | 
| +  message_center_->SetMessageCenterVisible(true);
 | 
| +  OnChanged();
 | 
| +  HidePopupBubble();
 | 
| +
 | 
| +  message_center::MessageCenterBubble* bubble =
 | 
| +      new message_center::MessageCenterBubble(message_center_);
 | 
| +  // Delegate to the host to find the system-specific anchor alignment, and to
 | 
| +  // modify the InitParams as necessary.
 | 
| +  views::TrayBubbleView::AnchorAlignment alignment =
 | 
| +      host_->GetAnchorAlignment();
 | 
| +  views::TrayBubbleView::InitParams init_params =
 | 
| +      bubble->GetInitParams(alignment);
 | 
| +  host_->UpdateInitParams(&init_params);
 | 
| +  message_center_bubble_.reset(new WebNotificationBubbleWrapper(
 | 
| +    this,
 | 
| +    bubble,
 | 
| +    init_params,
 | 
| +    host_->GetBubbleWindowContainer(),
 | 
| +    host_->GetAnchorView()));
 | 
| +}
 | 
| +
 | 
| +bool MessageCenterTray::HideMessageCenterBubble() {
 | 
| +  if (!message_center_bubble_.get())
 | 
| +    return false;
 | 
| +
 | 
| +  host_->OnHideMessageCenterBubble();
 | 
| +
 | 
| +  message_center_bubble_.reset();
 | 
| +  message_center_->SetMessageCenterVisible(false);
 | 
| +  OnChanged();
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +void MessageCenterTray::ToggleMessageCenterBubble() {
 | 
| +  if (message_center_bubble_.get()) {
 | 
| +    HideMessageCenterBubble();
 | 
| +  } else {
 | 
| +    ShowMessageCenterBubble();
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void MessageCenterTray::ShowPopupBubble() {
 | 
| +  if (!host_->CanShowPopups())
 | 
| +    return;
 | 
| +  if (message_center_bubble_)
 | 
| +    return;
 | 
| +
 | 
| +  OnChanged();
 | 
| +
 | 
| +  // If there is already a popup bubble, just update it.
 | 
| +  if (popup_bubble_) {
 | 
| +    popup_bubble_->message_bubble()->ScheduleUpdate();
 | 
| +    return;
 | 
| +  }
 | 
| +  if (message_center_->HasPopupNotifications()) {
 | 
| +    message_center::MessagePopupBubble* bubble =
 | 
| +        new message_center::MessagePopupBubble(message_center_);
 | 
| +    views::TrayBubbleView::AnchorAlignment alignment =
 | 
| +        host_->GetAnchorAlignment();
 | 
| +    views::TrayBubbleView::InitParams init_params =
 | 
| +        bubble->GetInitParams(alignment);
 | 
| +    host_->UpdateInitParams(&init_params);
 | 
| +
 | 
| +    // Delegate to the host to find the system-specific anchor alignment, and to
 | 
| +    // modify the InitParams as necessary.
 | 
| +    popup_bubble_.reset(new WebNotificationBubbleWrapper(
 | 
| +        this,
 | 
| +        bubble,
 | 
| +        init_params,
 | 
| +        host_->GetBubbleWindowContainer(),
 | 
| +        host_->GetAnchorView()));
 | 
| +    bubble->ScheduleUpdate();
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +bool MessageCenterTray::HidePopupBubble() {
 | 
| +  if (!popup_bubble_.get())
 | 
| +    return false;
 | 
| +  popup_bubble_.reset();
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +views::TrayBubbleView* MessageCenterTray::GetPopupBubbleView() {
 | 
| +  if (popup_bubble_.get())
 | 
| +    return popup_bubble_->bubble_view();
 | 
| +  return NULL;
 | 
| +}
 | 
| +
 | 
| +views::TrayBubbleView* MessageCenterTray::GetMessageCenterBubbleView() {
 | 
| +  if (message_center_bubble_.get())
 | 
| +    return message_center_bubble_->bubble_view();
 | 
| +  return NULL;
 | 
| +}
 | 
| +
 | 
| +void MessageCenterTray::BubbleViewDestroyed() {
 | 
| +  if (message_center_bubble_.get())
 | 
| +    message_center_bubble_->message_bubble()->BubbleViewDestroyed();
 | 
| +  if (popup_bubble_.get())
 | 
| +    popup_bubble_->message_bubble()->BubbleViewDestroyed();
 | 
| +}
 | 
| +
 | 
| +void MessageCenterTray::OnMouseEnteredView() {
 | 
| +  if (popup_bubble_.get())
 | 
| +    popup_bubble_->message_bubble()->OnMouseEnteredView();
 | 
| +}
 | 
| +
 | 
| +void MessageCenterTray::OnMouseExitedView() {
 | 
| +  if (popup_bubble_.get())
 | 
| +    popup_bubble_->message_bubble()->OnMouseExitedView();
 | 
| +}
 | 
| +
 | 
| +string16 MessageCenterTray::GetAccessibleNameForBubble() {
 | 
| +  return host_->GetAccessibleNameForBubble();
 | 
| +}
 | 
| +
 | 
| +gfx::Rect MessageCenterTray::GetAnchorRect(views::Widget* anchor_widget,
 | 
| +                                           AnchorType anchor_type,
 | 
| +                                           AnchorAlignment anchor_alignment) {
 | 
| +  return host_->GetAnchorRect(anchor_widget, anchor_type, anchor_alignment);
 | 
| +}
 | 
| +
 | 
| +void MessageCenterTray::HideBubble(const views::TrayBubbleView* bubble_view) {
 | 
| +  if (message_center_bubble_.get() &&
 | 
| +      bubble_view == message_center_bubble_->bubble_view()) {
 | 
| +    HideMessageCenterBubble();
 | 
| +  } else if (popup_bubble_.get() &&
 | 
| +             bubble_view == popup_bubble_->bubble_view()) {
 | 
| +    HidePopupBubble();
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void MessageCenterTray::OnMessageCenterChanged(bool new_notification) {
 | 
| +  if (message_center_bubble_.get()) {
 | 
| +    if (message_center_->NotificationCount() == 0)
 | 
| +      HideMessageCenterBubble();
 | 
| +    else
 | 
| +      message_center_bubble_->message_bubble()->ScheduleUpdate();
 | 
| +  }
 | 
| +  if (popup_bubble_.get()) {
 | 
| +    if (message_center_->NotificationCount() == 0)
 | 
| +      HidePopupBubble();
 | 
| +    else
 | 
| +      popup_bubble_->message_bubble()->ScheduleUpdate();
 | 
| +  }
 | 
| +
 | 
| +  OnChanged();
 | 
| +  if (new_notification)
 | 
| +    ShowPopupBubble();
 | 
| +}
 | 
| +
 | 
| +void MessageCenterTray::OnChanged() {
 | 
| +  host_->OnMessageCenterTrayChanged();
 | 
| +}
 | 
| +
 | 
| +}  // namespace ui
 | 
| 
 |