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