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 |