| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "chrome/browser/cocoa/info_bubble_window.h" | 5 #import "chrome/browser/cocoa/info_bubble_window.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/scoped_nsobject.h" | 8 #include "base/scoped_nsobject.h" |
| 9 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h" | 9 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h" |
| 10 | 10 |
| 11 namespace { | 11 namespace { |
| 12 const CGFloat kOrderInSlideOffset = 10; | 12 const CGFloat kOrderInSlideOffset = 10; |
| 13 const NSTimeInterval kOrderInAnimationDuration = 0.2; | 13 const NSTimeInterval kOrderInAnimationDuration = 0.2; |
| 14 const NSTimeInterval kOrderOutAnimationDuration = 0.15; | 14 const NSTimeInterval kOrderOutAnimationDuration = 0.15; |
| 15 // The minimum representable time interval. This can be used as the value |
| 16 // passed to +[NSAnimationContext setDuration:] to stop an in-progress |
| 17 // animation as quickly as possible. |
| 18 const NSTimeInterval kMinimumTimeInterval = |
| 19 std::numeric_limits<NSTimeInterval>::min(); |
| 15 } | 20 } |
| 16 | 21 |
| 17 @interface InfoBubbleWindow (Private) | 22 @interface InfoBubbleWindow(Private) |
| 23 - (void)appIsTerminating; |
| 18 - (void)finishCloseAfterAnimation; | 24 - (void)finishCloseAfterAnimation; |
| 19 @end | 25 @end |
| 20 | 26 |
| 21 // A delegate object for watching the alphaValue animation on InfoBubbleWindows. | 27 // A delegate object for watching the alphaValue animation on InfoBubbleWindows. |
| 22 // An InfoBubbleWindow instance cannot be the delegate for its own animation | 28 // An InfoBubbleWindow instance cannot be the delegate for its own animation |
| 23 // because CAAnimations retain their delegates, and since the InfoBubbleWindow | 29 // because CAAnimations retain their delegates, and since the InfoBubbleWindow |
| 24 // retains its animations a retain loop would be formed. | 30 // retains its animations a retain loop would be formed. |
| 25 @interface InfoBubbleWindowCloser : NSObject { | 31 @interface InfoBubbleWindowCloser : NSObject { |
| 26 @private | 32 @private |
| 27 InfoBubbleWindow* window_; // Weak. Window to close. | 33 InfoBubbleWindow* window_; // Weak. Window to close. |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 // Notice that only the alphaValue Animation is replaced in case | 82 // Notice that only the alphaValue Animation is replaced in case |
| 77 // superclasses set up animations. | 83 // superclasses set up animations. |
| 78 CAAnimation* alphaAnimation = [CABasicAnimation animation]; | 84 CAAnimation* alphaAnimation = [CABasicAnimation animation]; |
| 79 scoped_nsobject<InfoBubbleWindowCloser> delegate( | 85 scoped_nsobject<InfoBubbleWindowCloser> delegate( |
| 80 [[InfoBubbleWindowCloser alloc] initWithWindow:self]); | 86 [[InfoBubbleWindowCloser alloc] initWithWindow:self]); |
| 81 [alphaAnimation setDelegate:delegate]; | 87 [alphaAnimation setDelegate:delegate]; |
| 82 NSMutableDictionary* animations = | 88 NSMutableDictionary* animations = |
| 83 [NSMutableDictionary dictionaryWithDictionary:[self animations]]; | 89 [NSMutableDictionary dictionaryWithDictionary:[self animations]]; |
| 84 [animations setObject:alphaAnimation forKey:@"alphaValue"]; | 90 [animations setObject:alphaAnimation forKey:@"alphaValue"]; |
| 85 [self setAnimations:animations]; | 91 [self setAnimations:animations]; |
| 92 |
| 93 [[NSNotificationCenter defaultCenter] |
| 94 addObserver:self |
| 95 selector:@selector(appIsTerminating) |
| 96 name:NSApplicationWillTerminateNotification |
| 97 object:[NSApplication sharedApplication]]; |
| 86 } | 98 } |
| 87 return self; | 99 return self; |
| 88 } | 100 } |
| 89 | 101 |
| 102 - (void)dealloc { |
| 103 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 104 [super dealloc]; |
| 105 } |
| 106 |
| 90 // According to | 107 // According to |
| 91 // http://www.cocoabuilder.com/archive/message/cocoa/2006/6/19/165953, | 108 // http://www.cocoabuilder.com/archive/message/cocoa/2006/6/19/165953, |
| 92 // NSBorderlessWindowMask windows cannot become key or main. In this | 109 // NSBorderlessWindowMask windows cannot become key or main. In this |
| 93 // case, this is not a desired behavior. As an example, the bubble could have | 110 // case, this is not a desired behavior. As an example, the bubble could have |
| 94 // buttons. | 111 // buttons. |
| 95 - (BOOL)canBecomeKeyWindow { | 112 - (BOOL)canBecomeKeyWindow { |
| 96 return YES; | 113 return YES; |
| 97 } | 114 } |
| 98 | 115 |
| 99 - (void)close { | 116 - (void)close { |
| 100 // Block the window from receiving events while it fades out. | 117 // Block the window from receiving events while it fades out. |
| 101 closing_ = YES; | 118 closing_ = YES; |
| 102 | 119 |
| 103 if (!delayOnClose_) { | 120 if (!delayOnClose_) { |
| 104 [self finishCloseAfterAnimation]; | 121 [self finishCloseAfterAnimation]; |
| 105 } else { | 122 } else { |
| 106 // Apply animations to hide self. | 123 // Apply animations to hide self. |
| 107 [NSAnimationContext beginGrouping]; | 124 [NSAnimationContext beginGrouping]; |
| 108 [[NSAnimationContext currentContext] | 125 [[NSAnimationContext currentContext] |
| 109 gtm_setDuration:kOrderOutAnimationDuration]; | 126 gtm_setDuration:kOrderOutAnimationDuration]; |
| 110 [[self animator] setAlphaValue:0.0]; | 127 [[self animator] setAlphaValue:0.0]; |
| 111 [NSAnimationContext endGrouping]; | 128 [NSAnimationContext endGrouping]; |
| 112 } | 129 } |
| 113 } | 130 } |
| 114 | 131 |
| 132 // If the app is terminating but the window is still fading out, cancel |
| 133 // the animation and close the window to prevent it from leaking. |
| 134 - (void)appIsTerminating { |
| 135 if (!delayOnClose_) |
| 136 return; // The close has already happened with no Core Animation. |
| 137 |
| 138 // Cancel the current animation so that it closes immediately, triggering |
| 139 // |finishCloseAfterAnimation|. |
| 140 [NSAnimationContext beginGrouping]; |
| 141 [[NSAnimationContext currentContext] setDuration:kMinimumTimeInterval]; |
| 142 [[self animator] setAlphaValue:0.0]; |
| 143 [NSAnimationContext endGrouping]; |
| 144 } |
| 145 |
| 115 // Called by InfoBubbleWindowCloser when the window is to be really closed | 146 // Called by InfoBubbleWindowCloser when the window is to be really closed |
| 116 // after the fading animation is complete. | 147 // after the fading animation is complete. |
| 117 - (void)finishCloseAfterAnimation { | 148 - (void)finishCloseAfterAnimation { |
| 118 if (closing_) | 149 if (closing_) |
| 119 [super close]; | 150 [super close]; |
| 120 } | 151 } |
| 121 | 152 |
| 122 // Adds animation for info bubbles being ordered to the front. | 153 // Adds animation for info bubbles being ordered to the front. |
| 123 - (void)orderWindow:(NSWindowOrderingMode)orderingMode | 154 - (void)orderWindow:(NSWindowOrderingMode)orderingMode |
| 124 relativeTo:(NSInteger)otherWindowNumber { | 155 relativeTo:(NSInteger)otherWindowNumber { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 152 - (void)sendEvent:(NSEvent*)theEvent { | 183 - (void)sendEvent:(NSEvent*)theEvent { |
| 153 if (!closing_) | 184 if (!closing_) |
| 154 [super sendEvent:theEvent]; | 185 [super sendEvent:theEvent]; |
| 155 } | 186 } |
| 156 | 187 |
| 157 - (BOOL)isClosing { | 188 - (BOOL)isClosing { |
| 158 return closing_; | 189 return closing_; |
| 159 } | 190 } |
| 160 | 191 |
| 161 @end | 192 @end |
| OLD | NEW |