| Index: ui/message_center/cocoa/tray_view_controller.mm
|
| diff --git a/ui/message_center/cocoa/tray_view_controller.mm b/ui/message_center/cocoa/tray_view_controller.mm
|
| deleted file mode 100644
|
| index a63f3d3ccc02721f37cc127762e222053f207f21..0000000000000000000000000000000000000000
|
| --- a/ui/message_center/cocoa/tray_view_controller.mm
|
| +++ /dev/null
|
| @@ -1,810 +0,0 @@
|
| -// Copyright (c) 2013 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.
|
| -
|
| -#import "ui/message_center/cocoa/tray_view_controller.h"
|
| -
|
| -#include <cmath>
|
| -
|
| -#include "base/mac/scoped_nsautorelease_pool.h"
|
| -#include "base/time/time.h"
|
| -#include "skia/ext/skia_utils_mac.h"
|
| -#import "ui/base/cocoa/hover_image_button.h"
|
| -#include "ui/base/l10n/l10n_util_mac.h"
|
| -#include "ui/base/resource/resource_bundle.h"
|
| -#import "ui/message_center/cocoa/notification_controller.h"
|
| -#import "ui/message_center/cocoa/opaque_views.h"
|
| -#import "ui/message_center/cocoa/settings_controller.h"
|
| -#include "ui/message_center/message_center.h"
|
| -#include "ui/message_center/message_center_style.h"
|
| -#include "ui/message_center/notifier_settings.h"
|
| -#include "ui/resources/grit/ui_resources.h"
|
| -#include "ui/strings/grit/ui_strings.h"
|
| -
|
| -const int kBackButtonSize = 16;
|
| -
|
| -// NSClipView subclass.
|
| -@interface MCClipView : NSClipView {
|
| - // If this is set, the visible document area will remain intact no matter how
|
| - // the user scrolls or drags the thumb.
|
| - BOOL frozen_;
|
| -}
|
| -@end
|
| -
|
| -@implementation MCClipView
|
| -- (void)setFrozen:(BOOL)frozen {
|
| - frozen_ = frozen;
|
| -}
|
| -
|
| -- (NSPoint)constrainScrollPoint:(NSPoint)proposedNewOrigin {
|
| - return frozen_ ? [self documentVisibleRect].origin :
|
| - [super constrainScrollPoint:proposedNewOrigin];
|
| -}
|
| -@end
|
| -
|
| -@interface MCTrayViewController (Private)
|
| -// Creates all the views for the control area of the tray.
|
| -- (void)layoutControlArea;
|
| -
|
| -// Update both tray view and window by resizing it to fit its content.
|
| -- (void)updateTrayViewAndWindow;
|
| -
|
| -// Remove notifications dismissed by the user. It is done in the following
|
| -// 3 steps.
|
| -- (void)closeNotificationsByUser;
|
| -
|
| -// Step 1: hide all notifications pending removal with fade-out animation.
|
| -- (void)hideNotificationsPendingRemoval;
|
| -
|
| -// Step 2: move up all remaining notifications to take over the available space
|
| -// due to hiding notifications. The scroll view and the window remain unchanged.
|
| -- (void)moveUpRemainingNotifications;
|
| -
|
| -// Step 3: finalize the tray view and window to get rid of the empty space.
|
| -- (void)finalizeTrayViewAndWindow;
|
| -
|
| -// Clear a notification by sliding it out from left to right. This occurs when
|
| -// "Clear All" is clicked.
|
| -- (void)clearOneNotification;
|
| -
|
| -// When all visible notifications slide out, re-enable controls and remove
|
| -// notifications from the message center.
|
| -- (void)finalizeClearAll;
|
| -
|
| -// Sets the images of the quiet mode button based on the message center state.
|
| -- (void)updateQuietModeButtonImage;
|
| -@end
|
| -
|
| -namespace {
|
| -
|
| -// The duration of fade-out and bounds animation.
|
| -const NSTimeInterval kAnimationDuration = 0.2;
|
| -
|
| -// The delay to start animating clearing next notification since current
|
| -// animation starts.
|
| -const NSTimeInterval kAnimateClearingNextNotificationDelay = 0.04;
|
| -
|
| -// The height of the bar at the top of the tray that contains buttons.
|
| -const CGFloat kControlAreaHeight = 50;
|
| -
|
| -// Amount of spacing between control buttons. There is kMarginBetweenItems
|
| -// between a button and the edge of the tray, though.
|
| -const CGFloat kButtonXMargin = 20;
|
| -
|
| -// Amount of padding to leave between the bottom of the screen and the bottom
|
| -// of the message center tray.
|
| -const CGFloat kTrayBottomMargin = 75;
|
| -
|
| -} // namespace
|
| -
|
| -@implementation MCTrayViewController
|
| -
|
| -- (id)initWithMessageCenter:(message_center::MessageCenter*)messageCenter {
|
| - if ((self = [super initWithNibName:nil bundle:nil])) {
|
| - messageCenter_ = messageCenter;
|
| - animationDuration_ = kAnimationDuration;
|
| - animateClearingNextNotificationDelay_ =
|
| - kAnimateClearingNextNotificationDelay;
|
| - notifications_.reset([[NSMutableArray alloc] init]);
|
| - notificationsPendingRemoval_.reset([[NSMutableArray alloc] init]);
|
| - }
|
| - return self;
|
| -}
|
| -
|
| -- (NSString*)trayTitle {
|
| - return [title_ stringValue];
|
| -}
|
| -
|
| -- (void)setTrayTitle:(NSString*)title {
|
| - [title_ setStringValue:title];
|
| - [title_ sizeToFit];
|
| -}
|
| -
|
| -- (void)onWindowClosing {
|
| - if (animation_) {
|
| - [animation_ stopAnimation];
|
| - [animation_ setDelegate:nil];
|
| - animation_.reset();
|
| - }
|
| - if (clearAllInProgress_) {
|
| - // To stop chain of clearOneNotification calls to start new animations.
|
| - [NSObject cancelPreviousPerformRequestsWithTarget:self];
|
| -
|
| - for (NSViewAnimation* animation in clearAllAnimations_.get()) {
|
| - [animation stopAnimation];
|
| - [animation setDelegate:nil];
|
| - }
|
| - [clearAllAnimations_ removeAllObjects];
|
| - [self finalizeClearAll];
|
| - }
|
| -}
|
| -
|
| -- (void)loadView {
|
| - // Configure the root view as a background-colored box.
|
| - base::scoped_nsobject<NSBox> view([[NSBox alloc] initWithFrame:NSMakeRect(
|
| - 0, 0, [MCTrayViewController trayWidth], kControlAreaHeight)]);
|
| - [view setBorderType:NSNoBorder];
|
| - [view setBoxType:NSBoxCustom];
|
| - [view setContentViewMargins:NSZeroSize];
|
| - [view setFillColor:gfx::SkColorToCalibratedNSColor(
|
| - message_center::kMessageCenterBackgroundColor)];
|
| - [view setTitlePosition:NSNoTitle];
|
| - [view setWantsLayer:YES]; // Needed for notification view shadows.
|
| - [self setView:view];
|
| -
|
| - [self layoutControlArea];
|
| -
|
| - // Configure the scroll view in which all the notifications go.
|
| - base::scoped_nsobject<NSView> documentView(
|
| - [[NSView alloc] initWithFrame:NSZeroRect]);
|
| - scrollView_.reset([[NSScrollView alloc] initWithFrame:[view frame]]);
|
| - clipView_.reset(
|
| - [[MCClipView alloc] initWithFrame:[[scrollView_ contentView] frame]]);
|
| - [scrollView_ setContentView:clipView_];
|
| - [scrollView_ setAutohidesScrollers:YES];
|
| - [scrollView_ setAutoresizingMask:NSViewHeightSizable | NSViewMaxYMargin];
|
| - [scrollView_ setDocumentView:documentView];
|
| - [scrollView_ setDrawsBackground:NO];
|
| - [scrollView_ setHasHorizontalScroller:NO];
|
| - [scrollView_ setHasVerticalScroller:YES];
|
| - [view addSubview:scrollView_];
|
| -
|
| - [self onMessageCenterTrayChanged];
|
| -}
|
| -
|
| -- (void)onMessageCenterTrayChanged {
|
| - if (settingsController_)
|
| - return [self updateTrayViewAndWindow];
|
| -
|
| - std::map<std::string, MCNotificationController*> newMap;
|
| -
|
| - base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
|
| - [shadow setShadowColor:[NSColor colorWithDeviceWhite:0 alpha:0.55]];
|
| - [shadow setShadowOffset:NSMakeSize(0, -1)];
|
| - [shadow setShadowBlurRadius:2.0];
|
| -
|
| - CGFloat minY = message_center::kMarginBetweenItems;
|
| -
|
| - // Iterate over the notifications in reverse, since the Cocoa coordinate
|
| - // origin is in the lower-left. Remove from |notificationsMap_| all the
|
| - // ones still in the updated model, so that those that should be removed
|
| - // will remain in the map.
|
| - const auto& modelNotifications = messageCenter_->GetVisibleNotifications();
|
| - for (auto it = modelNotifications.rbegin();
|
| - it != modelNotifications.rend();
|
| - ++it) {
|
| - // Check if this notification is already in the tray.
|
| - const auto& existing = notificationsMap_.find((*it)->id());
|
| - MCNotificationController* notification = nil;
|
| - if (existing == notificationsMap_.end()) {
|
| - base::scoped_nsobject<MCNotificationController> controller(
|
| - [[MCNotificationController alloc]
|
| - initWithNotification:*it
|
| - messageCenter:messageCenter_]);
|
| - [[controller view] setShadow:shadow];
|
| - [[scrollView_ documentView] addSubview:[controller view]];
|
| -
|
| - [notifications_ addObject:controller]; // Transfer ownership.
|
| - messageCenter_->DisplayedNotification(
|
| - (*it)->id(), message_center::DISPLAY_SOURCE_MESSAGE_CENTER);
|
| -
|
| - notification = controller.get();
|
| - } else {
|
| - notification = existing->second;
|
| - [notification updateNotification:*it];
|
| - notificationsMap_.erase(existing);
|
| - }
|
| -
|
| - DCHECK(notification);
|
| -
|
| - NSRect frame = [[notification view] frame];
|
| - frame.origin.x = message_center::kMarginBetweenItems;
|
| - frame.origin.y = minY;
|
| - [[notification view] setFrame:frame];
|
| -
|
| - newMap.insert(std::make_pair((*it)->id(), notification));
|
| -
|
| - minY = NSMaxY(frame) + message_center::kMarginBetweenItems;
|
| - }
|
| -
|
| - // Remove any notifications that are no longer in the model.
|
| - for (const auto& pair : notificationsMap_) {
|
| - [[pair.second view] removeFromSuperview];
|
| - [notifications_ removeObject:pair.second];
|
| - }
|
| -
|
| - // Copy the new map of notifications to replace the old.
|
| - notificationsMap_ = newMap;
|
| -
|
| - [self updateTrayViewAndWindow];
|
| -}
|
| -
|
| -- (void)toggleQuietMode:(id)sender {
|
| - if (messageCenter_->IsQuietMode())
|
| - messageCenter_->SetQuietMode(false);
|
| - else
|
| - messageCenter_->EnterQuietModeWithExpire(base::TimeDelta::FromDays(1));
|
| -
|
| - [self updateQuietModeButtonImage];
|
| -}
|
| -
|
| -- (void)clearAllNotifications:(id)sender {
|
| - if ([self isAnimating]) {
|
| - clearAllDelayed_ = YES;
|
| - return;
|
| - }
|
| -
|
| - // Build a list for all notifications within the visible scroll range
|
| - // in preparation to slide them out one by one.
|
| - NSRect visibleScrollRect = [scrollView_ documentVisibleRect];
|
| - for (MCNotificationController* notification in notifications_.get()) {
|
| - NSRect rect = [[notification view] frame];
|
| - if (!NSIsEmptyRect(NSIntersectionRect(visibleScrollRect, rect))) {
|
| - visibleNotificationsPendingClear_.push_back(notification);
|
| - }
|
| - }
|
| - if (visibleNotificationsPendingClear_.empty())
|
| - return;
|
| -
|
| - // Disbale buttons and freeze scroll bar to prevent the user from clicking on
|
| - // them accidentally.
|
| - [pauseButton_ setEnabled:NO];
|
| - [clearAllButton_ setEnabled:NO];
|
| - [settingsButton_ setEnabled:NO];
|
| - [clipView_ setFrozen:YES];
|
| -
|
| - // Start sliding out the top notification.
|
| - clearAllAnimations_.reset([[NSMutableArray alloc] init]);
|
| - [self clearOneNotification];
|
| -
|
| - clearAllInProgress_ = YES;
|
| -}
|
| -
|
| -- (void)showSettings:(id)sender {
|
| - if (settingsController_)
|
| - return [self showMessages:sender];
|
| -
|
| - message_center::NotifierSettingsProvider* provider =
|
| - messageCenter_->GetNotifierSettingsProvider();
|
| - settingsController_.reset(
|
| - [[MCSettingsController alloc] initWithProvider:provider
|
| - trayViewController:self]);
|
| -
|
| - [[self view] addSubview:[settingsController_ view]];
|
| -
|
| - NSRect titleFrame = [title_ frame];
|
| - titleFrame.origin.x =
|
| - NSMaxX([backButton_ frame]) + message_center::kMarginBetweenItems / 2;
|
| - [title_ setFrame:titleFrame];
|
| - [backButton_ setHidden:NO];
|
| - [clearAllButton_ setEnabled:NO];
|
| -
|
| - [scrollView_ setHidden:YES];
|
| -
|
| - [[[self view] window] recalculateKeyViewLoop];
|
| - messageCenter_->SetVisibility(message_center::VISIBILITY_SETTINGS);
|
| -
|
| - [self updateTrayViewAndWindow];
|
| -}
|
| -
|
| -- (void)updateSettings {
|
| - // TODO(jianli): This class should not be calling -loadView, but instead
|
| - // should just observe a resize notification.
|
| - // (http://crbug.com/270251)
|
| - [[settingsController_ view] removeFromSuperview];
|
| - [settingsController_ loadView];
|
| - [[self view] addSubview:[settingsController_ view]];
|
| -
|
| - [self updateTrayViewAndWindow];
|
| -}
|
| -
|
| -- (void)showMessages:(id)sender {
|
| - messageCenter_->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER);
|
| - [self cleanupSettings];
|
| - [[[self view] window] recalculateKeyViewLoop];
|
| - [self updateTrayViewAndWindow];
|
| -}
|
| -
|
| -- (void)cleanupSettings {
|
| - [scrollView_ setHidden:NO];
|
| -
|
| - [[settingsController_ view] removeFromSuperview];
|
| - settingsController_.reset();
|
| -
|
| - NSRect titleFrame = [title_ frame];
|
| - titleFrame.origin.x = NSMinX([backButton_ frame]);
|
| - [title_ setFrame:titleFrame];
|
| - [backButton_ setHidden:YES];
|
| - [clearAllButton_ setEnabled:YES];
|
| -
|
| -}
|
| -
|
| -- (void)scrollToTop {
|
| - NSPoint topPoint =
|
| - NSMakePoint(0.0, [[scrollView_ documentView] bounds].size.height);
|
| - [[scrollView_ documentView] scrollPoint:topPoint];
|
| -}
|
| -
|
| -- (BOOL)isAnimating {
|
| - return [animation_ isAnimating] || [clearAllAnimations_ count];
|
| -}
|
| -
|
| -+ (CGFloat)maxTrayClientHeight {
|
| - NSRect screenFrame = [[[NSScreen screens] objectAtIndex:0] visibleFrame];
|
| - return NSHeight(screenFrame) - kTrayBottomMargin - kControlAreaHeight;
|
| -}
|
| -
|
| -+ (CGFloat)trayWidth {
|
| - return message_center::kNotificationWidth +
|
| - 2 * message_center::kMarginBetweenItems;
|
| -}
|
| -
|
| -// Testing API /////////////////////////////////////////////////////////////////
|
| -
|
| -- (NSBox*)divider {
|
| - return divider_.get();
|
| -}
|
| -
|
| -- (NSTextField*)emptyDescription {
|
| - return emptyDescription_.get();
|
| -}
|
| -
|
| -- (NSScrollView*)scrollView {
|
| - return scrollView_.get();
|
| -}
|
| -
|
| -- (HoverImageButton*)pauseButton {
|
| - return pauseButton_.get();
|
| -}
|
| -
|
| -- (HoverImageButton*)clearAllButton {
|
| - return clearAllButton_.get();
|
| -}
|
| -
|
| -- (void)setAnimationDuration:(NSTimeInterval)duration {
|
| - animationDuration_ = duration;
|
| -}
|
| -
|
| -- (void)setAnimateClearingNextNotificationDelay:(NSTimeInterval)delay {
|
| - animateClearingNextNotificationDelay_ = delay;
|
| -}
|
| -
|
| -- (void)setAnimationEndedCallback:
|
| - (message_center::TrayAnimationEndedCallback)callback {
|
| - testingAnimationEndedCallback_.reset(Block_copy(callback));
|
| -}
|
| -
|
| -// Private /////////////////////////////////////////////////////////////////////
|
| -
|
| -- (void)layoutControlArea {
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| - NSView* view = [self view];
|
| -
|
| - // Create the "Notifications" label at the top of the tray.
|
| - NSFont* font = [NSFont labelFontOfSize:message_center::kTitleFontSize];
|
| - NSColor* color = gfx::SkColorToCalibratedNSColor(
|
| - message_center::kMessageCenterBackgroundColor);
|
| - title_.reset(
|
| - [[MCTextField alloc] initWithFrame:NSZeroRect backgroundColor:color]);
|
| -
|
| - [title_ setFont:font];
|
| - [title_ setStringValue:
|
| - l10n_util::GetNSString(IDS_MESSAGE_CENTER_FOOTER_TITLE)];
|
| - [title_ setTextColor:gfx::SkColorToCalibratedNSColor(
|
| - message_center::kRegularTextColor)];
|
| - [title_ sizeToFit];
|
| -
|
| - NSRect titleFrame = [title_ frame];
|
| - titleFrame.origin.x = message_center::kMarginBetweenItems;
|
| - titleFrame.origin.y = kControlAreaHeight/2 - NSMidY(titleFrame);
|
| - [title_ setFrame:titleFrame];
|
| - [view addSubview:title_];
|
| -
|
| - auto configureButton = ^(HoverImageButton* button) {
|
| - [[button cell] setHighlightsBy:NSOnState];
|
| - [button setTrackingEnabled:YES];
|
| - [button setBordered:NO];
|
| - [button setAutoresizingMask:NSViewMinYMargin];
|
| - [button setTarget:self];
|
| - };
|
| -
|
| - // Back button. On top of the "Notifications" label, hidden by default.
|
| - NSRect backButtonFrame =
|
| - NSMakeRect(NSMinX(titleFrame),
|
| - (kControlAreaHeight - kBackButtonSize) / 2,
|
| - kBackButtonSize,
|
| - kBackButtonSize);
|
| - backButton_.reset([[HoverImageButton alloc] initWithFrame:backButtonFrame]);
|
| - [backButton_ setDefaultImage:
|
| - rb.GetNativeImageNamed(IDR_NOTIFICATION_ARROW).ToNSImage()];
|
| - [backButton_ setHoverImage:
|
| - rb.GetNativeImageNamed(IDR_NOTIFICATION_ARROW_HOVER).ToNSImage()];
|
| - [backButton_ setPressedImage:
|
| - rb.GetNativeImageNamed(IDR_NOTIFICATION_ARROW_PRESSED).ToNSImage()];
|
| - [backButton_ setAction:@selector(showMessages:)];
|
| - configureButton(backButton_);
|
| - [backButton_ setHidden:YES];
|
| - [backButton_ setKeyEquivalent:@"\e"];
|
| - [backButton_ setToolTip:l10n_util::GetNSString(
|
| - IDS_MESSAGE_CENTER_SETTINGS_GO_BACK_BUTTON_TOOLTIP)];
|
| - [[backButton_ cell]
|
| - accessibilitySetOverrideValue:[backButton_ toolTip]
|
| - forAttribute:NSAccessibilityDescriptionAttribute];
|
| - [[self view] addSubview:backButton_];
|
| -
|
| - // Create the divider line between the control area and the notifications.
|
| - divider_.reset(
|
| - [[NSBox alloc] initWithFrame:NSMakeRect(0, 0, NSWidth([view frame]), 1)]);
|
| - [divider_ setAutoresizingMask:NSViewMinYMargin];
|
| - [divider_ setBorderType:NSNoBorder];
|
| - [divider_ setBoxType:NSBoxCustom];
|
| - [divider_ setContentViewMargins:NSZeroSize];
|
| - [divider_ setFillColor:gfx::SkColorToCalibratedNSColor(
|
| - message_center::kFooterDelimiterColor)];
|
| - [divider_ setTitlePosition:NSNoTitle];
|
| - [view addSubview:divider_];
|
| -
|
| -
|
| - auto getButtonFrame = ^NSRect(CGFloat maxX, NSImage* image) {
|
| - NSSize size = [image size];
|
| - return NSMakeRect(
|
| - maxX - size.width,
|
| - kControlAreaHeight/2 - size.height/2,
|
| - size.width,
|
| - size.height);
|
| - };
|
| -
|
| - // Create the settings button at the far-right.
|
| - NSImage* defaultImage =
|
| - rb.GetNativeImageNamed(IDR_NOTIFICATION_SETTINGS).ToNSImage();
|
| - NSRect settingsButtonFrame = getButtonFrame(
|
| - NSWidth([view frame]) - message_center::kMarginBetweenItems,
|
| - defaultImage);
|
| - settingsButton_.reset(
|
| - [[HoverImageButton alloc] initWithFrame:settingsButtonFrame]);
|
| - [settingsButton_ setDefaultImage:defaultImage];
|
| - [settingsButton_ setHoverImage:
|
| - rb.GetNativeImageNamed(IDR_NOTIFICATION_SETTINGS_HOVER).ToNSImage()];
|
| - [settingsButton_ setPressedImage:
|
| - rb.GetNativeImageNamed(IDR_NOTIFICATION_SETTINGS_PRESSED).ToNSImage()];
|
| - [settingsButton_ setToolTip:
|
| - l10n_util::GetNSString(IDS_MESSAGE_CENTER_SETTINGS_BUTTON_LABEL)];
|
| - [[settingsButton_ cell]
|
| - accessibilitySetOverrideValue:[settingsButton_ toolTip]
|
| - forAttribute:NSAccessibilityDescriptionAttribute];
|
| - [settingsButton_ setAction:@selector(showSettings:)];
|
| - configureButton(settingsButton_);
|
| - [view addSubview:settingsButton_];
|
| -
|
| - // Create the clear all button.
|
| - defaultImage = rb.GetNativeImageNamed(IDR_NOTIFICATION_CLEAR_ALL).ToNSImage();
|
| - NSRect clearAllButtonFrame = getButtonFrame(
|
| - NSMinX(settingsButtonFrame) - kButtonXMargin,
|
| - defaultImage);
|
| - clearAllButton_.reset(
|
| - [[HoverImageButton alloc] initWithFrame:clearAllButtonFrame]);
|
| - [clearAllButton_ setDefaultImage:defaultImage];
|
| - [clearAllButton_ setHoverImage:
|
| - rb.GetNativeImageNamed(IDR_NOTIFICATION_CLEAR_ALL_HOVER).ToNSImage()];
|
| - [clearAllButton_ setPressedImage:
|
| - rb.GetNativeImageNamed(IDR_NOTIFICATION_CLEAR_ALL_PRESSED).ToNSImage()];
|
| - [clearAllButton_ setToolTip:
|
| - l10n_util::GetNSString(IDS_MESSAGE_CENTER_CLEAR_ALL)];
|
| - [[clearAllButton_ cell]
|
| - accessibilitySetOverrideValue:[clearAllButton_ toolTip]
|
| - forAttribute:NSAccessibilityDescriptionAttribute];
|
| - [clearAllButton_ setAction:@selector(clearAllNotifications:)];
|
| - configureButton(clearAllButton_);
|
| - [view addSubview:clearAllButton_];
|
| -
|
| - // Create the pause button.
|
| - NSRect pauseButtonFrame = getButtonFrame(
|
| - NSMinX(clearAllButtonFrame) - kButtonXMargin,
|
| - defaultImage);
|
| - pauseButton_.reset([[HoverImageButton alloc] initWithFrame:pauseButtonFrame]);
|
| - [self updateQuietModeButtonImage];
|
| - [pauseButton_ setHoverImage: rb.GetNativeImageNamed(
|
| - IDR_NOTIFICATION_DO_NOT_DISTURB_HOVER).ToNSImage()];
|
| - [pauseButton_ setToolTip:
|
| - l10n_util::GetNSString(IDS_MESSAGE_CENTER_QUIET_MODE_BUTTON_TOOLTIP)];
|
| - [[pauseButton_ cell]
|
| - accessibilitySetOverrideValue:[pauseButton_ toolTip]
|
| - forAttribute:NSAccessibilityDescriptionAttribute];
|
| - [pauseButton_ setAction:@selector(toggleQuietMode:)];
|
| - configureButton(pauseButton_);
|
| - [view addSubview:pauseButton_];
|
| -
|
| - // Create the description field for the empty message center. Initially it is
|
| - // invisible.
|
| - emptyDescription_.reset(
|
| - [[MCTextField alloc] initWithFrame:NSZeroRect backgroundColor:color]);
|
| -
|
| - NSFont* smallFont =
|
| - [NSFont labelFontOfSize:message_center::kEmptyCenterFontSize];
|
| - [emptyDescription_ setFont:smallFont];
|
| - [emptyDescription_ setStringValue:
|
| - l10n_util::GetNSString(IDS_MESSAGE_CENTER_NO_MESSAGES)];
|
| - [emptyDescription_ setTextColor:gfx::SkColorToCalibratedNSColor(
|
| - message_center::kDimTextColor)];
|
| - [emptyDescription_ sizeToFit];
|
| - [emptyDescription_ setHidden:YES];
|
| -
|
| - [view addSubview:emptyDescription_];
|
| -}
|
| -
|
| -- (void)updateTrayViewAndWindow {
|
| - CGFloat scrollContentHeight = message_center::kMinScrollViewHeight;
|
| - if ([notifications_ count]) {
|
| - [emptyDescription_ setHidden:YES];
|
| - [scrollView_ setHidden:NO];
|
| - [divider_ setHidden:NO];
|
| - scrollContentHeight = NSMaxY([[[notifications_ lastObject] view] frame]) +
|
| - message_center::kMarginBetweenItems;;
|
| - } else {
|
| - [emptyDescription_ setHidden:NO];
|
| - [scrollView_ setHidden:YES];
|
| - [divider_ setHidden:YES];
|
| -
|
| - NSRect centeredFrame = [emptyDescription_ frame];
|
| - NSPoint centeredOrigin = NSMakePoint(
|
| - floor((NSWidth([[self view] frame]) - NSWidth(centeredFrame))/2 + 0.5),
|
| - floor((scrollContentHeight - NSHeight(centeredFrame))/2 + 0.5));
|
| -
|
| - centeredFrame.origin = centeredOrigin;
|
| - [emptyDescription_ setFrame:centeredFrame];
|
| - }
|
| -
|
| - // Resize the scroll view's content.
|
| - NSRect scrollViewFrame = [scrollView_ frame];
|
| - NSRect documentFrame = [[scrollView_ documentView] frame];
|
| - documentFrame.size.width = NSWidth(scrollViewFrame);
|
| - documentFrame.size.height = scrollContentHeight;
|
| - [[scrollView_ documentView] setFrame:documentFrame];
|
| -
|
| - // Resize the container view.
|
| - NSRect frame = [[self view] frame];
|
| - CGFloat oldHeight = NSHeight(frame);
|
| - if (settingsController_) {
|
| - frame.size.height = NSHeight([[settingsController_ view] frame]);
|
| - } else {
|
| - frame.size.height = std::min([MCTrayViewController maxTrayClientHeight],
|
| - scrollContentHeight);
|
| - }
|
| - frame.size.height += kControlAreaHeight;
|
| - CGFloat newHeight = NSHeight(frame);
|
| - [[self view] setFrame:frame];
|
| -
|
| - // Resize the scroll view.
|
| - scrollViewFrame.size.height = NSHeight(frame) - kControlAreaHeight;
|
| - [scrollView_ setFrame:scrollViewFrame];
|
| -
|
| - // Resize the window.
|
| - NSRect windowFrame = [[[self view] window] frame];
|
| - CGFloat delta = newHeight - oldHeight;
|
| - windowFrame.origin.y -= delta;
|
| - windowFrame.size.height += delta;
|
| -
|
| - [[[self view] window] setFrame:windowFrame display:YES];
|
| - // Hide the clear-all button if there are no notifications. Simply swap the
|
| - // X position of it and the pause button in that case.
|
| - BOOL hidden = ![notifications_ count];
|
| - if ([clearAllButton_ isHidden] != hidden) {
|
| - [clearAllButton_ setHidden:hidden];
|
| -
|
| - NSRect pauseButtonFrame = [pauseButton_ frame];
|
| - NSRect clearAllButtonFrame = [clearAllButton_ frame];
|
| - std::swap(clearAllButtonFrame.origin.x, pauseButtonFrame.origin.x);
|
| - [pauseButton_ setFrame:pauseButtonFrame];
|
| - [clearAllButton_ setFrame:clearAllButtonFrame];
|
| - }
|
| -}
|
| -
|
| -- (void)animationDidEnd:(NSAnimation*)animation {
|
| - if (clearAllInProgress_) {
|
| - // For clear-all animation.
|
| - [clearAllAnimations_ removeObject:animation];
|
| - if (![clearAllAnimations_ count] &&
|
| - visibleNotificationsPendingClear_.empty()) {
|
| - [self finalizeClearAll];
|
| - }
|
| - } else {
|
| - // For notification removal and reposition animation.
|
| - if ([notificationsPendingRemoval_ count]) {
|
| - [self moveUpRemainingNotifications];
|
| - } else {
|
| - [self finalizeTrayViewAndWindow];
|
| -
|
| - if (clearAllDelayed_)
|
| - [self clearAllNotifications:nil];
|
| - }
|
| - }
|
| -
|
| - // Give the testing code a chance to do something, i.e. quitting the test
|
| - // run loop.
|
| - if (![self isAnimating] && testingAnimationEndedCallback_)
|
| - testingAnimationEndedCallback_.get()();
|
| -}
|
| -
|
| -- (void)closeNotificationsByUser {
|
| - // No need to close individual notification if clear-all is in progress.
|
| - if (clearAllInProgress_)
|
| - return;
|
| -
|
| - if ([self isAnimating])
|
| - return;
|
| - [self hideNotificationsPendingRemoval];
|
| -}
|
| -
|
| -- (void)hideNotificationsPendingRemoval {
|
| - base::scoped_nsobject<NSMutableArray> animationDataArray(
|
| - [[NSMutableArray alloc] init]);
|
| -
|
| - // Fade-out those notifications pending removal.
|
| - for (MCNotificationController* notification in notifications_.get()) {
|
| - if (messageCenter_->FindVisibleNotificationById(
|
| - [notification notificationID]))
|
| - continue;
|
| - [notificationsPendingRemoval_ addObject:notification];
|
| - [animationDataArray addObject:@{
|
| - NSViewAnimationTargetKey : [notification view],
|
| - NSViewAnimationEffectKey : NSViewAnimationFadeOutEffect
|
| - }];
|
| - }
|
| -
|
| - if ([notificationsPendingRemoval_ count] == 0)
|
| - return;
|
| -
|
| - for (MCNotificationController* notification in
|
| - notificationsPendingRemoval_.get()) {
|
| - [notifications_ removeObject:notification];
|
| - }
|
| -
|
| - // Start the animation.
|
| - animation_.reset([[NSViewAnimation alloc]
|
| - initWithViewAnimations:animationDataArray]);
|
| - [animation_ setDuration:animationDuration_];
|
| - [animation_ setDelegate:self];
|
| - [animation_ startAnimation];
|
| -}
|
| -
|
| -- (void)moveUpRemainingNotifications {
|
| - base::scoped_nsobject<NSMutableArray> animationDataArray(
|
| - [[NSMutableArray alloc] init]);
|
| -
|
| - // Compute the position where the remaining notifications should start.
|
| - CGFloat minY = message_center::kMarginBetweenItems;
|
| - for (MCNotificationController* notification in
|
| - notificationsPendingRemoval_.get()) {
|
| - NSView* view = [notification view];
|
| - minY += NSHeight([view frame]) + message_center::kMarginBetweenItems;
|
| - }
|
| -
|
| - // Reposition the remaining notifications starting at the computed position.
|
| - for (MCNotificationController* notification in notifications_.get()) {
|
| - NSView* view = [notification view];
|
| - NSRect frame = [view frame];
|
| - NSRect oldFrame = frame;
|
| - frame.origin.y = minY;
|
| - if (!NSEqualRects(oldFrame, frame)) {
|
| - [animationDataArray addObject:@{
|
| - NSViewAnimationTargetKey : view,
|
| - NSViewAnimationEndFrameKey : [NSValue valueWithRect:frame]
|
| - }];
|
| - }
|
| - minY = NSMaxY(frame) + message_center::kMarginBetweenItems;
|
| - }
|
| -
|
| - // Now remove notifications pending removal.
|
| - for (MCNotificationController* notification in
|
| - notificationsPendingRemoval_.get()) {
|
| - [[notification view] removeFromSuperview];
|
| - notificationsMap_.erase([notification notificationID]);
|
| - }
|
| - [notificationsPendingRemoval_ removeAllObjects];
|
| -
|
| - // Start the animation.
|
| - animation_.reset([[NSViewAnimation alloc]
|
| - initWithViewAnimations:animationDataArray]);
|
| - [animation_ setDuration:animationDuration_];
|
| - [animation_ setDelegate:self];
|
| - [animation_ startAnimation];
|
| -}
|
| -
|
| -- (void)finalizeTrayViewAndWindow {
|
| - // Reposition the remaining notifications starting at the bottom.
|
| - CGFloat minY = message_center::kMarginBetweenItems;
|
| - for (MCNotificationController* notification in notifications_.get()) {
|
| - NSView* view = [notification view];
|
| - NSRect frame = [view frame];
|
| - NSRect oldFrame = frame;
|
| - frame.origin.y = minY;
|
| - if (!NSEqualRects(oldFrame, frame))
|
| - [view setFrame:frame];
|
| - minY = NSMaxY(frame) + message_center::kMarginBetweenItems;
|
| - }
|
| -
|
| - [self updateTrayViewAndWindow];
|
| -
|
| - // Check if there're more notifications pending removal.
|
| - [self closeNotificationsByUser];
|
| -}
|
| -
|
| -- (void)clearOneNotification {
|
| - DCHECK(!visibleNotificationsPendingClear_.empty());
|
| -
|
| - MCNotificationController* notification =
|
| - visibleNotificationsPendingClear_.back();
|
| - visibleNotificationsPendingClear_.pop_back();
|
| -
|
| - // Slide out the notification from left to right with fade-out simultaneously.
|
| - NSRect newFrame = [[notification view] frame];
|
| - newFrame.origin.x = NSMaxX(newFrame) + message_center::kMarginBetweenItems;
|
| - NSDictionary* animationDict = @{
|
| - NSViewAnimationTargetKey : [notification view],
|
| - NSViewAnimationEndFrameKey : [NSValue valueWithRect:newFrame],
|
| - NSViewAnimationEffectKey : NSViewAnimationFadeOutEffect
|
| - };
|
| - base::scoped_nsobject<NSViewAnimation> animation([[NSViewAnimation alloc]
|
| - initWithViewAnimations:[NSArray arrayWithObject:animationDict]]);
|
| - [animation setDuration:animationDuration_];
|
| - [animation setDelegate:self];
|
| - [animation startAnimation];
|
| - [clearAllAnimations_ addObject:animation];
|
| -
|
| - // Schedule to start sliding out next notification after a short delay.
|
| - if (!visibleNotificationsPendingClear_.empty()) {
|
| - [self performSelector:@selector(clearOneNotification)
|
| - withObject:nil
|
| - afterDelay:animateClearingNextNotificationDelay_];
|
| - }
|
| -}
|
| -
|
| -- (void)finalizeClearAll {
|
| - DCHECK(clearAllInProgress_);
|
| - clearAllInProgress_ = NO;
|
| -
|
| - DCHECK(![clearAllAnimations_ count]);
|
| - clearAllAnimations_.reset();
|
| -
|
| - [pauseButton_ setEnabled:YES];
|
| - [clearAllButton_ setEnabled:YES];
|
| - [settingsButton_ setEnabled:YES];
|
| - [clipView_ setFrozen:NO];
|
| -
|
| - messageCenter_->RemoveAllVisibleNotifications(true);
|
| -}
|
| -
|
| -- (void)updateQuietModeButtonImage {
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| - if (messageCenter_->IsQuietMode()) {
|
| - [pauseButton_ setTrackingEnabled:NO];
|
| - [pauseButton_ setDefaultImage: rb.GetNativeImageNamed(
|
| - IDR_NOTIFICATION_DO_NOT_DISTURB_PRESSED).ToNSImage()];
|
| - } else {
|
| - [pauseButton_ setTrackingEnabled:YES];
|
| - [pauseButton_ setDefaultImage:
|
| - rb.GetNativeImageNamed(IDR_NOTIFICATION_DO_NOT_DISTURB).ToNSImage()];
|
| - }
|
| -}
|
| -
|
| -@end
|
|
|