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