Home | History | Annotate | Download | only in notifications
      1 // Copyright (c) 2013 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 #include "chrome/browser/ui/cocoa/notifications/message_center_tray_bridge.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/i18n/number_formatting.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "base/prefs/pref_service.h"
     11 #include "chrome/browser/browser_process.h"
     12 #include "chrome/common/pref_names.h"
     13 #include "chrome/grit/chromium_strings.h"
     14 #include "chrome/grit/generated_resources.h"
     15 #include "ui/base/l10n/l10n_util.h"
     16 #import "ui/base/l10n/l10n_util_mac.h"
     17 #import "ui/message_center/cocoa/popup_collection.h"
     18 #import "ui/message_center/cocoa/status_item_view.h"
     19 #import "ui/message_center/cocoa/tray_controller.h"
     20 #import "ui/message_center/cocoa/tray_view_controller.h"
     21 #include "ui/message_center/message_center.h"
     22 #include "ui/message_center/message_center_tray.h"
     23 
     24 namespace message_center {
     25 
     26 MessageCenterTrayDelegate* CreateMessageCenterTray() {
     27   return new MessageCenterTrayBridge(g_browser_process->message_center());
     28 }
     29 
     30 }  // namespace message_center
     31 
     32 MessageCenterTrayBridge::MessageCenterTrayBridge(
     33     message_center::MessageCenter* message_center)
     34     : message_center_(message_center),
     35       tray_(new message_center::MessageCenterTray(this, message_center)),
     36       weak_ptr_factory_(this) {
     37   show_status_item_.Init(
     38       prefs::kMessageCenterShowIcon,
     39       g_browser_process->local_state(),
     40       base::Bind(&MessageCenterTrayBridge::OnShowStatusItemChanged,
     41                  weak_ptr_factory_.GetWeakPtr()));
     42 }
     43 
     44 MessageCenterTrayBridge::~MessageCenterTrayBridge() {
     45   [status_item_view_ removeItem];
     46 }
     47 
     48 void MessageCenterTrayBridge::OnMessageCenterTrayChanged() {
     49   // Update the status item on the next run of the message loop so that if a
     50   // popup is displayed, the item doesn't flash the unread count.
     51   base::MessageLoop::current()->PostTask(FROM_HERE,
     52       base::Bind(&MessageCenterTrayBridge::UpdateStatusItem,
     53                  weak_ptr_factory_.GetWeakPtr()));
     54 
     55   [tray_controller_ onMessageCenterTrayChanged];
     56 }
     57 
     58 bool MessageCenterTrayBridge::ShowPopups() {
     59   popup_collection_.reset(
     60       [[MCPopupCollection alloc] initWithMessageCenter:message_center_]);
     61   return true;
     62 }
     63 
     64 void MessageCenterTrayBridge::HidePopups() {
     65   popup_collection_.reset();
     66 }
     67 
     68 bool MessageCenterTrayBridge::ShowMessageCenter() {
     69   if (tray_controller_)
     70     return false;
     71 
     72   OpenTrayWindow();
     73   return true;
     74 }
     75 
     76 void MessageCenterTrayBridge::HideMessageCenter() {
     77   [status_item_view_ setHighlight:NO];
     78   [tray_controller_ close];
     79   tray_controller_.autorelease();
     80   UpdateStatusItem();
     81 }
     82 
     83 bool MessageCenterTrayBridge::ShowNotifierSettings() {
     84   // This method needs to be implemented when the context menu of each
     85   // notification is ready and it contains 'settings' menu item.
     86   return false;
     87 }
     88 
     89 bool MessageCenterTrayBridge::IsContextMenuEnabled() const {
     90   // Cocoa message center doesn't support context menu yet.
     91   return false;
     92 }
     93 
     94 message_center::MessageCenterTray*
     95 MessageCenterTrayBridge::GetMessageCenterTray() {
     96   return tray_.get();
     97 }
     98 
     99 void MessageCenterTrayBridge::UpdateStatusItem() {
    100   // Only show the status item if there are notifications.
    101   if (!ShouldShowStatusItem()) {
    102     [status_item_view_ removeItem];
    103     status_item_view_.reset();
    104     return;
    105   }
    106 
    107   if (!status_item_view_) {
    108     status_item_view_.reset([[MCStatusItemView alloc] init]);
    109     [status_item_view_ setCallback:^{ tray_->ToggleMessageCenterBubble(); }];
    110   }
    111 
    112   // We want a static message center icon while it's visible.
    113   if (message_center()->IsMessageCenterVisible())
    114     return;
    115 
    116   size_t unread_count = message_center_->UnreadNotificationCount();
    117   bool quiet_mode = message_center_->IsQuietMode();
    118   [status_item_view_ setUnreadCount:unread_count withQuietMode:quiet_mode];
    119 
    120   if (unread_count > 0) {
    121     base::string16 unread_count_string = base::FormatNumber(unread_count);
    122     [status_item_view_ setToolTip:
    123         l10n_util::GetNSStringF(IDS_MESSAGE_CENTER_TOOLTIP_UNREAD,
    124             unread_count_string)];
    125   } else {
    126     [status_item_view_ setToolTip:
    127         l10n_util::GetNSString(IDS_MESSAGE_CENTER_TOOLTIP)];
    128   }
    129 }
    130 
    131 void MessageCenterTrayBridge::OpenTrayWindow() {
    132   DCHECK(!tray_controller_);
    133   tray_controller_.reset(
    134       [[MCTrayController alloc] initWithMessageCenterTray:tray_.get()]);
    135   [[tray_controller_ viewController] setTrayTitle:
    136       l10n_util::GetNSStringF(IDS_MESSAGE_CENTER_FOOTER_WITH_PRODUCT_TITLE,
    137           l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME))];
    138 
    139   UpdateStatusItem();
    140 
    141   DCHECK(status_item_view_);
    142   [status_item_view_ setHighlight:YES];
    143   NSRect frame = [[status_item_view_ window] frame];
    144   [tray_controller_ showTrayAtRightOf:NSMakePoint(NSMinX(frame),
    145                                                   NSMinY(frame))
    146                              atLeftOf:NSMakePoint(NSMaxX(frame),
    147                                                   NSMinY(frame))];
    148 }
    149 
    150 bool MessageCenterTrayBridge::ShouldShowStatusItem() const {
    151   return g_browser_process->local_state()->GetBoolean(
    152       prefs::kMessageCenterShowIcon);
    153 }
    154 
    155 void MessageCenterTrayBridge::OnShowStatusItemChanged() {
    156   UpdateStatusItem();
    157 }
    158