| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "ui/message_center/cocoa/tray_view_controller.h" | 5 #import "ui/message_center/cocoa/tray_view_controller.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "base/mac/scoped_nsautorelease_pool.h" | 9 #include "base/mac/scoped_nsautorelease_pool.h" |
| 10 #include "base/time.h" | 10 #include "base/time.h" |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 [animation stopAnimation]; | 118 [animation stopAnimation]; |
| 119 [animation setDelegate:nil]; | 119 [animation setDelegate:nil]; |
| 120 } | 120 } |
| 121 [clearAllAnimations_ removeAllObjects]; | 121 [clearAllAnimations_ removeAllObjects]; |
| 122 [self finalizeClearAll]; | 122 [self finalizeClearAll]; |
| 123 } | 123 } |
| 124 } | 124 } |
| 125 | 125 |
| 126 - (void)loadView { | 126 - (void)loadView { |
| 127 // Configure the root view as a background-colored box. | 127 // Configure the root view as a background-colored box. |
| 128 scoped_nsobject<NSBox> view([[NSBox alloc] initWithFrame:NSMakeRect( | 128 base::scoped_nsobject<NSBox> view([[NSBox alloc] initWithFrame:NSMakeRect( |
| 129 0, 0, [MCTrayViewController trayWidth], kControlAreaHeight)]); | 129 0, 0, [MCTrayViewController trayWidth], kControlAreaHeight)]); |
| 130 [view setBorderType:NSNoBorder]; | 130 [view setBorderType:NSNoBorder]; |
| 131 [view setBoxType:NSBoxCustom]; | 131 [view setBoxType:NSBoxCustom]; |
| 132 [view setContentViewMargins:NSZeroSize]; | 132 [view setContentViewMargins:NSZeroSize]; |
| 133 [view setFillColor:gfx::SkColorToCalibratedNSColor( | 133 [view setFillColor:gfx::SkColorToCalibratedNSColor( |
| 134 message_center::kMessageCenterBackgroundColor)]; | 134 message_center::kMessageCenterBackgroundColor)]; |
| 135 [view setTitlePosition:NSNoTitle]; | 135 [view setTitlePosition:NSNoTitle]; |
| 136 [view setWantsLayer:YES]; // Needed for notification view shadows. | 136 [view setWantsLayer:YES]; // Needed for notification view shadows. |
| 137 [self setView:view]; | 137 [self setView:view]; |
| 138 | 138 |
| 139 [self layoutControlArea]; | 139 [self layoutControlArea]; |
| 140 | 140 |
| 141 // Configure the scroll view in which all the notifications go. | 141 // Configure the scroll view in which all the notifications go. |
| 142 scoped_nsobject<NSView> documentView( | 142 base::scoped_nsobject<NSView> documentView( |
| 143 [[NSView alloc] initWithFrame:NSZeroRect]); | 143 [[NSView alloc] initWithFrame:NSZeroRect]); |
| 144 scrollView_.reset([[NSScrollView alloc] initWithFrame:[view frame]]); | 144 scrollView_.reset([[NSScrollView alloc] initWithFrame:[view frame]]); |
| 145 clipView_.reset( | 145 clipView_.reset( |
| 146 [[MCClipView alloc] initWithFrame:[[scrollView_ contentView] frame]]); | 146 [[MCClipView alloc] initWithFrame:[[scrollView_ contentView] frame]]); |
| 147 [scrollView_ setContentView:clipView_]; | 147 [scrollView_ setContentView:clipView_]; |
| 148 [scrollView_ setAutohidesScrollers:YES]; | 148 [scrollView_ setAutohidesScrollers:YES]; |
| 149 [scrollView_ setAutoresizingMask:NSViewHeightSizable | NSViewMaxYMargin]; | 149 [scrollView_ setAutoresizingMask:NSViewHeightSizable | NSViewMaxYMargin]; |
| 150 [scrollView_ setDocumentView:documentView]; | 150 [scrollView_ setDocumentView:documentView]; |
| 151 [scrollView_ setDrawsBackground:NO]; | 151 [scrollView_ setDrawsBackground:NO]; |
| 152 [scrollView_ setHasHorizontalScroller:NO]; | 152 [scrollView_ setHasHorizontalScroller:NO]; |
| 153 [scrollView_ setHasVerticalScroller:YES]; | 153 [scrollView_ setHasVerticalScroller:YES]; |
| 154 [view addSubview:scrollView_]; | 154 [view addSubview:scrollView_]; |
| 155 | 155 |
| 156 [self onMessageCenterTrayChanged]; | 156 [self onMessageCenterTrayChanged]; |
| 157 } | 157 } |
| 158 | 158 |
| 159 - (void)onMessageCenterTrayChanged { | 159 - (void)onMessageCenterTrayChanged { |
| 160 if (settingsController_) | 160 if (settingsController_) |
| 161 return [self updateTrayViewAndWindow]; | 161 return [self updateTrayViewAndWindow]; |
| 162 | 162 |
| 163 // When the window is visible, the only update is to remove notifications | 163 // When the window is visible, the only update is to remove notifications |
| 164 // dismissed by the user. | 164 // dismissed by the user. |
| 165 if ([[[self view] window] isVisible]) { | 165 if ([[[self view] window] isVisible]) { |
| 166 [self closeNotificationsByUser]; | 166 [self closeNotificationsByUser]; |
| 167 return; | 167 return; |
| 168 } | 168 } |
| 169 | 169 |
| 170 std::map<std::string, MCNotificationController*> newMap; | 170 std::map<std::string, MCNotificationController*> newMap; |
| 171 | 171 |
| 172 scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]); | 172 base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]); |
| 173 [shadow setShadowColor:[NSColor colorWithDeviceWhite:0 alpha:0.55]]; | 173 [shadow setShadowColor:[NSColor colorWithDeviceWhite:0 alpha:0.55]]; |
| 174 [shadow setShadowOffset:NSMakeSize(0, -1)]; | 174 [shadow setShadowOffset:NSMakeSize(0, -1)]; |
| 175 [shadow setShadowBlurRadius:2.0]; | 175 [shadow setShadowBlurRadius:2.0]; |
| 176 | 176 |
| 177 CGFloat minY = message_center::kMarginBetweenItems; | 177 CGFloat minY = message_center::kMarginBetweenItems; |
| 178 | 178 |
| 179 // Iterate over the notifications in reverse, since the Cocoa coordinate | 179 // Iterate over the notifications in reverse, since the Cocoa coordinate |
| 180 // origin is in the lower-left. Remove from |notificationsMap_| all the | 180 // origin is in the lower-left. Remove from |notificationsMap_| all the |
| 181 // ones still in the updated model, so that those that should be removed | 181 // ones still in the updated model, so that those that should be removed |
| 182 // will remain in the map. | 182 // will remain in the map. |
| 183 const auto& modelNotifications = messageCenter_->GetNotifications(); | 183 const auto& modelNotifications = messageCenter_->GetNotifications(); |
| 184 for (auto it = modelNotifications.rbegin(); | 184 for (auto it = modelNotifications.rbegin(); |
| 185 it != modelNotifications.rend(); | 185 it != modelNotifications.rend(); |
| 186 ++it) { | 186 ++it) { |
| 187 // Check if this notification is already in the tray. | 187 // Check if this notification is already in the tray. |
| 188 const auto& existing = notificationsMap_.find((*it)->id()); | 188 const auto& existing = notificationsMap_.find((*it)->id()); |
| 189 MCNotificationController* notification = nil; | 189 MCNotificationController* notification = nil; |
| 190 if (existing == notificationsMap_.end()) { | 190 if (existing == notificationsMap_.end()) { |
| 191 scoped_nsobject<MCNotificationController> controller( | 191 base::scoped_nsobject<MCNotificationController> controller( |
| 192 [[MCNotificationController alloc] | 192 [[MCNotificationController alloc] |
| 193 initWithNotification:*it | 193 initWithNotification:*it |
| 194 messageCenter:messageCenter_]); | 194 messageCenter:messageCenter_]); |
| 195 [[controller view] setShadow:shadow]; | 195 [[controller view] setShadow:shadow]; |
| 196 [[scrollView_ documentView] addSubview:[controller view]]; | 196 [[scrollView_ documentView] addSubview:[controller view]]; |
| 197 | 197 |
| 198 [notifications_ addObject:controller]; // Transfer ownership. | 198 [notifications_ addObject:controller]; // Transfer ownership. |
| 199 messageCenter_->DisplayedNotification((*it)->id()); | 199 messageCenter_->DisplayedNotification((*it)->id()); |
| 200 | 200 |
| 201 notification = controller.get(); | 201 notification = controller.get(); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 [backButton_ setHidden:YES]; | 418 [backButton_ setHidden:YES]; |
| 419 [backButton_ setKeyEquivalent:@"\e"]; | 419 [backButton_ setKeyEquivalent:@"\e"]; |
| 420 [backButton_ setToolTip:l10n_util::GetNSString( | 420 [backButton_ setToolTip:l10n_util::GetNSString( |
| 421 IDS_MESSAGE_CENTER_SETTINGS_GO_BACK_BUTTON_TOOLTIP)]; | 421 IDS_MESSAGE_CENTER_SETTINGS_GO_BACK_BUTTON_TOOLTIP)]; |
| 422 [[backButton_ cell] | 422 [[backButton_ cell] |
| 423 accessibilitySetOverrideValue:[backButton_ toolTip] | 423 accessibilitySetOverrideValue:[backButton_ toolTip] |
| 424 forAttribute:NSAccessibilityDescriptionAttribute]; | 424 forAttribute:NSAccessibilityDescriptionAttribute]; |
| 425 [[self view] addSubview:backButton_]; | 425 [[self view] addSubview:backButton_]; |
| 426 | 426 |
| 427 // Create the divider line between the control area and the notifications. | 427 // Create the divider line between the control area and the notifications. |
| 428 scoped_nsobject<NSBox> divider( | 428 base::scoped_nsobject<NSBox> divider( |
| 429 [[NSBox alloc] initWithFrame:NSMakeRect(0, 0, NSWidth([view frame]), 1)]); | 429 [[NSBox alloc] initWithFrame:NSMakeRect(0, 0, NSWidth([view frame]), 1)]); |
| 430 [divider setAutoresizingMask:NSViewMinYMargin]; | 430 [divider setAutoresizingMask:NSViewMinYMargin]; |
| 431 [divider setBorderType:NSNoBorder]; | 431 [divider setBorderType:NSNoBorder]; |
| 432 [divider setBoxType:NSBoxCustom]; | 432 [divider setBoxType:NSBoxCustom]; |
| 433 [divider setContentViewMargins:NSZeroSize]; | 433 [divider setContentViewMargins:NSZeroSize]; |
| 434 [divider setFillColor:gfx::SkColorToCalibratedNSColor( | 434 [divider setFillColor:gfx::SkColorToCalibratedNSColor( |
| 435 message_center::kFooterDelimiterColor)]; | 435 message_center::kFooterDelimiterColor)]; |
| 436 [divider setTitlePosition:NSNoTitle]; | 436 [divider setTitlePosition:NSNoTitle]; |
| 437 [view addSubview:divider]; | 437 [view addSubview:divider]; |
| 438 | 438 |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 // No need to close individual notification if clear-all is in progress. | 591 // No need to close individual notification if clear-all is in progress. |
| 592 if (clearAllInProgress_) | 592 if (clearAllInProgress_) |
| 593 return; | 593 return; |
| 594 | 594 |
| 595 if ([self isAnimating]) | 595 if ([self isAnimating]) |
| 596 return; | 596 return; |
| 597 [self hideNotificationsPendingRemoval]; | 597 [self hideNotificationsPendingRemoval]; |
| 598 } | 598 } |
| 599 | 599 |
| 600 - (void)hideNotificationsPendingRemoval { | 600 - (void)hideNotificationsPendingRemoval { |
| 601 scoped_nsobject<NSMutableArray> animationDataArray( | 601 base::scoped_nsobject<NSMutableArray> animationDataArray( |
| 602 [[NSMutableArray alloc] init]); | 602 [[NSMutableArray alloc] init]); |
| 603 | 603 |
| 604 // Fade-out those notifications pending removal. | 604 // Fade-out those notifications pending removal. |
| 605 for (MCNotificationController* notification in notifications_.get()) { | 605 for (MCNotificationController* notification in notifications_.get()) { |
| 606 if (messageCenter_->HasNotification([notification notificationID])) | 606 if (messageCenter_->HasNotification([notification notificationID])) |
| 607 continue; | 607 continue; |
| 608 [notificationsPendingRemoval_ addObject:notification]; | 608 [notificationsPendingRemoval_ addObject:notification]; |
| 609 [animationDataArray addObject:@{ | 609 [animationDataArray addObject:@{ |
| 610 NSViewAnimationTargetKey : [notification view], | 610 NSViewAnimationTargetKey : [notification view], |
| 611 NSViewAnimationEffectKey : NSViewAnimationFadeOutEffect | 611 NSViewAnimationEffectKey : NSViewAnimationFadeOutEffect |
| (...skipping 10 matching lines...) Expand all Loading... |
| 622 | 622 |
| 623 // Start the animation. | 623 // Start the animation. |
| 624 animation_.reset([[NSViewAnimation alloc] | 624 animation_.reset([[NSViewAnimation alloc] |
| 625 initWithViewAnimations:animationDataArray]); | 625 initWithViewAnimations:animationDataArray]); |
| 626 [animation_ setDuration:animationDuration_]; | 626 [animation_ setDuration:animationDuration_]; |
| 627 [animation_ setDelegate:self]; | 627 [animation_ setDelegate:self]; |
| 628 [animation_ startAnimation]; | 628 [animation_ startAnimation]; |
| 629 } | 629 } |
| 630 | 630 |
| 631 - (void)moveUpRemainingNotifications { | 631 - (void)moveUpRemainingNotifications { |
| 632 scoped_nsobject<NSMutableArray> animationDataArray( | 632 base::scoped_nsobject<NSMutableArray> animationDataArray( |
| 633 [[NSMutableArray alloc] init]); | 633 [[NSMutableArray alloc] init]); |
| 634 | 634 |
| 635 // Compute the position where the remaining notifications should start. | 635 // Compute the position where the remaining notifications should start. |
| 636 CGFloat minY = message_center::kMarginBetweenItems; | 636 CGFloat minY = message_center::kMarginBetweenItems; |
| 637 for (MCNotificationController* notification in | 637 for (MCNotificationController* notification in |
| 638 notificationsPendingRemoval_.get()) { | 638 notificationsPendingRemoval_.get()) { |
| 639 NSView* view = [notification view]; | 639 NSView* view = [notification view]; |
| 640 minY += NSHeight([view frame]) + message_center::kMarginBetweenItems; | 640 minY += NSHeight([view frame]) + message_center::kMarginBetweenItems; |
| 641 } | 641 } |
| 642 | 642 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 visibleNotificationsPendingClear_.pop_back(); | 698 visibleNotificationsPendingClear_.pop_back(); |
| 699 | 699 |
| 700 // Slide out the notification from left to right with fade-out simultaneously. | 700 // Slide out the notification from left to right with fade-out simultaneously. |
| 701 NSRect newFrame = [[notification view] frame]; | 701 NSRect newFrame = [[notification view] frame]; |
| 702 newFrame.origin.x = NSMaxX(newFrame) + message_center::kMarginBetweenItems; | 702 newFrame.origin.x = NSMaxX(newFrame) + message_center::kMarginBetweenItems; |
| 703 NSDictionary* animationDict = @{ | 703 NSDictionary* animationDict = @{ |
| 704 NSViewAnimationTargetKey : [notification view], | 704 NSViewAnimationTargetKey : [notification view], |
| 705 NSViewAnimationEndFrameKey : [NSValue valueWithRect:newFrame], | 705 NSViewAnimationEndFrameKey : [NSValue valueWithRect:newFrame], |
| 706 NSViewAnimationEffectKey : NSViewAnimationFadeOutEffect | 706 NSViewAnimationEffectKey : NSViewAnimationFadeOutEffect |
| 707 }; | 707 }; |
| 708 scoped_nsobject<NSViewAnimation> animation([[NSViewAnimation alloc] | 708 base::scoped_nsobject<NSViewAnimation> animation([[NSViewAnimation alloc] |
| 709 initWithViewAnimations:[NSArray arrayWithObject:animationDict]]); | 709 initWithViewAnimations:[NSArray arrayWithObject:animationDict]]); |
| 710 [animation setDuration:animationDuration_]; | 710 [animation setDuration:animationDuration_]; |
| 711 [animation setDelegate:self]; | 711 [animation setDelegate:self]; |
| 712 [animation startAnimation]; | 712 [animation startAnimation]; |
| 713 [clearAllAnimations_ addObject:animation]; | 713 [clearAllAnimations_ addObject:animation]; |
| 714 | 714 |
| 715 // Schedule to start sliding out next notification after a short delay. | 715 // Schedule to start sliding out next notification after a short delay. |
| 716 if (!visibleNotificationsPendingClear_.empty()) { | 716 if (!visibleNotificationsPendingClear_.empty()) { |
| 717 [self performSelector:@selector(clearOneNotification) | 717 [self performSelector:@selector(clearOneNotification) |
| 718 withObject:nil | 718 withObject:nil |
| (...skipping 10 matching lines...) Expand all Loading... |
| 729 | 729 |
| 730 [pauseButton_ setEnabled:YES]; | 730 [pauseButton_ setEnabled:YES]; |
| 731 [clearAllButton_ setEnabled:YES]; | 731 [clearAllButton_ setEnabled:YES]; |
| 732 [settingsButton_ setEnabled:YES]; | 732 [settingsButton_ setEnabled:YES]; |
| 733 [clipView_ setFrozen:NO]; | 733 [clipView_ setFrozen:NO]; |
| 734 | 734 |
| 735 messageCenter_->RemoveAllNotifications(true); | 735 messageCenter_->RemoveAllNotifications(true); |
| 736 } | 736 } |
| 737 | 737 |
| 738 @end | 738 @end |
| OLD | NEW |