Index: chrome/browser/ui/cocoa/download/download_shelf_controller.mm |
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_controller.mm b/chrome/browser/ui/cocoa/download/download_shelf_controller.mm |
index 16ea814138133fb0a5a7335bf60b4bd9ccc94fc5..9c66a90aa6329203c015dc71bcd3fb712edc07f4 100644 |
--- a/chrome/browser/ui/cocoa/download/download_shelf_controller.mm |
+++ b/chrome/browser/ui/cocoa/download/download_shelf_controller.mm |
@@ -71,16 +71,13 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 }; |
} // namespace |
@interface DownloadShelfController(Private) |
-- (void)showDownloadShelf:(BOOL)enable; |
+- (void)viewFrameDidChange:(NSNotification*)notification; |
- (void)layoutItems:(BOOL)skipFirst; |
- (void)closed; |
-- (BOOL)canAutoClose; |
- |
-- (void)viewFrameDidChange:(NSNotification*)notification; |
- |
+- (void)maybeAutoCloseAfterDelay; |
+- (void)autoClose; |
- (void)installTrackingArea; |
- (void)cancelAutoCloseAndRemoveTrackingArea; |
- |
- (void)willEnterFullscreen; |
- (void)willLeaveFullscreen; |
- (void)updateCloseButton; |
@@ -150,144 +147,44 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 }; |
[super dealloc]; |
} |
-// Called after the frame's rect has changed; usually when the height is |
-// animated. |
-- (void)viewFrameDidChange:(NSNotification*)notification { |
asanka
2013/03/22 20:11:01
Methods were re-ordered to match declaration order
Nico
2013/03/22 20:24:11
Can you land that part as a separate CL? That woul
asanka
2013/03/22 21:22:13
I undid the re-ordering. I see the point about mes
|
- // Anchor subviews at the top of |view|, so that it looks like the shelf |
- // is sliding out. |
- CGFloat newShelfHeight = NSHeight([[self view] frame]); |
- if (newShelfHeight == currentShelfHeight_) |
- return; |
- |
- for (NSView* view in [[self view] subviews]) { |
- NSRect frame = [view frame]; |
- frame.origin.y -= currentShelfHeight_ - newShelfHeight; |
- [view setFrame:frame]; |
- } |
- currentShelfHeight_ = newShelfHeight; |
-} |
- |
-- (AnimatableView*)animatableView { |
- return static_cast<AnimatableView*>([self view]); |
-} |
- |
-- (void)showDownloadsTab:(id)sender { |
+- (IBAction)showDownloadsTab:(id)sender { |
chrome::ShowDownloads(bridge_->browser()); |
} |
-- (void)remove:(DownloadItemController*)download { |
- // Look for the download in our controller array and remove it. This will |
- // explicity release it so that it removes itself as an Observer of the |
- // DownloadItem. We don't want to wait for autorelease since the DownloadItem |
- // we are observing will likely be gone by then. |
- [[NSNotificationCenter defaultCenter] removeObserver:download]; |
- |
- // TODO(dmaclach): Remove -- http://crbug.com/25845 |
- [[download view] removeFromSuperview]; |
- |
- [downloadItemControllers_ removeObject:download]; |
- |
- [self layoutItems]; |
- |
- // Check to see if we have any downloads remaining and if not, hide the shelf. |
- if (![downloadItemControllers_ count]) |
- [self showDownloadShelf:NO]; |
-} |
- |
-- (void)downloadWasOpened:(DownloadItemController*)item_controller { |
- // This should only be called on the main thead. |
- DCHECK([NSThread isMainThread]); |
- |
- if ([self canAutoClose]) |
- [self installTrackingArea]; |
+- (IBAction)handleClose:(id)sender { |
+ bridge_->Close(DownloadShelf::USER_ACTION); |
} |
-// We need to explicitly release our download controllers here since they need |
-// to remove themselves as observers before the remaining shutdown happens. |
-- (void)exiting { |
- [[self animatableView] stopAnimation]; |
- [self cancelAutoCloseAndRemoveTrackingArea]; |
- downloadItemControllers_.reset(); |
-} |
- |
-// Show or hide the bar based on the value of |enable|. Handles animating the |
-// resize of the content view. |
-- (void)showDownloadShelf:(BOOL)enable { |
- if ([self isVisible] == enable) |
+- (void)showDownloadShelf:(BOOL)show |
+ isUserAction:(BOOL)isUserAction { |
+ if ([self isVisible] == show) |
return; |
+ if (!show) { |
+ [self cancelAutoCloseAndRemoveTrackingArea]; |
+ int numInProgress = 0; |
+ for (NSUInteger i = 0; i < [downloadItemControllers_ count]; ++i) { |
+ if ([[downloadItemControllers_ objectAtIndex:i]download]->IsInProgress()) |
+ ++numInProgress; |
+ } |
+ download_util::RecordShelfClose( |
+ [downloadItemControllers_ count], numInProgress, !isUserAction); |
+ } |
// Animate the shelf out, but not in. |
// TODO(rohitrao): We do not animate on the way in because Cocoa is already |
// doing a lot of work to set up the download arrow animation. I've chosen to |
// do no animation over janky animation. Find a way to make animating in |
// smoother. |
AnimatableView* view = [self animatableView]; |
- if (enable) |
+ if (show) |
[view setHeight:maxShelfHeight_]; |
else |
[view animateToNewHeight:0 duration:kDownloadShelfCloseDuration]; |
- barIsVisible_ = enable; |
+ barIsVisible_ = show; |
[self updateCloseButton]; |
} |
-- (DownloadShelf*)bridge { |
- return bridge_.get(); |
-} |
- |
-- (BOOL)isVisible { |
- return barIsVisible_; |
-} |
- |
-- (void)show:(id)sender { |
- [self showDownloadShelf:YES]; |
-} |
- |
-- (void)hide:(id)sender { |
- [self cancelAutoCloseAndRemoveTrackingArea]; |
- |
- // If |sender| isn't nil, then we're being closed from the UI by the user and |
- // we need to tell our shelf implementation to close. Otherwise, we're being |
- // closed programmatically by our shelf implementation. |
- bool auto_closed = (sender == nil); |
- |
- int numInProgress = 0; |
- for (NSUInteger i = 0; i < [downloadItemControllers_ count]; ++i) { |
- if ([[downloadItemControllers_ objectAtIndex:i]download]->IsInProgress()) |
- ++numInProgress; |
- } |
- download_util::RecordShelfClose( |
- [downloadItemControllers_ count], numInProgress, auto_closed); |
- if (auto_closed) |
- [self showDownloadShelf:NO]; |
- else |
- bridge_->Close(); |
-} |
- |
-- (void)animationDidEnd:(NSAnimation*)animation { |
- if (![self isVisible]) |
- [self closed]; |
-} |
- |
-- (float)height { |
- return maxShelfHeight_; |
-} |
- |
-// If |skipFirst| is true, the frame of the leftmost item is not set. |
-- (void)layoutItems:(BOOL)skipFirst { |
- CGFloat currentX = 0; |
- for (DownloadItemController* itemController |
- in downloadItemControllers_.get()) { |
- NSRect frame = [[itemController view] frame]; |
- frame.origin.x = currentX; |
- frame.size.width = [itemController preferredSize].width; |
- if (!skipFirst) |
- [[[itemController view] animator] setFrame:frame]; |
- currentX += frame.size.width + kDownloadItemPadding; |
- skipFirst = NO; |
- } |
-} |
- |
- (void)layoutItems { |
[self layoutItems:NO]; |
} |
@@ -350,6 +247,91 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 }; |
[self layoutItems:YES]; |
} |
+- (void)remove:(DownloadItemController*)download { |
+ // Look for the download in our controller array and remove it. This will |
+ // explicity release it so that it removes itself as an Observer of the |
+ // DownloadItem. We don't want to wait for autorelease since the DownloadItem |
+ // we are observing will likely be gone by then. |
+ [[NSNotificationCenter defaultCenter] removeObserver:download]; |
+ |
+ // TODO(dmaclach): Remove -- http://crbug.com/25845 |
+ [[download view] removeFromSuperview]; |
+ |
+ [downloadItemControllers_ removeObject:download]; |
+ [self layoutItems]; |
+ |
+ // If there are no more downloads or if all the remaining downloads have been |
+ // opened, we can close the shelf. |
+ [self maybeAutoCloseAfterDelay]; |
+} |
+ |
+- (void)downloadWasOpened:(DownloadItemController*)item_controller { |
+ // This should only be called on the main thead. |
+ DCHECK([NSThread isMainThread]); |
+ [self maybeAutoCloseAfterDelay]; |
+} |
+ |
+// We need to explicitly release our download controllers here since they need |
+// to remove themselves as observers before the remaining shutdown happens. |
+- (void)exiting { |
+ [[self animatableView] stopAnimation]; |
+ [self cancelAutoCloseAndRemoveTrackingArea]; |
+ downloadItemControllers_.reset(); |
+} |
+ |
+- (AnimatableView*)animatableView { |
+ return static_cast<AnimatableView*>([self view]); |
+} |
+ |
+- (DownloadShelf*)bridge { |
+ return bridge_.get(); |
+} |
+ |
+- (BOOL)isVisible { |
+ return barIsVisible_; |
+} |
+ |
+- (float)height { |
+ return maxShelfHeight_; |
+} |
+ |
+// Called after the frame's rect has changed; usually when the height is |
+// animated. |
+- (void)viewFrameDidChange:(NSNotification*)notification { |
+ // Anchor subviews at the top of |view|, so that it looks like the shelf |
+ // is sliding out. |
+ CGFloat newShelfHeight = NSHeight([[self view] frame]); |
+ if (newShelfHeight == currentShelfHeight_) |
+ return; |
+ |
+ for (NSView* view in [[self view] subviews]) { |
+ NSRect frame = [view frame]; |
+ frame.origin.y -= currentShelfHeight_ - newShelfHeight; |
+ [view setFrame:frame]; |
+ } |
+ currentShelfHeight_ = newShelfHeight; |
+} |
+ |
+- (void)animationDidEnd:(NSAnimation*)animation { |
+ if (![self isVisible]) |
+ [self closed]; |
+} |
+ |
+// If |skipFirst| is true, the frame of the leftmost item is not set. |
+- (void)layoutItems:(BOOL)skipFirst { |
+ CGFloat currentX = 0; |
+ for (DownloadItemController* itemController |
+ in downloadItemControllers_.get()) { |
+ NSRect frame = [[itemController view] frame]; |
+ frame.origin.x = currentX; |
+ frame.size.width = [itemController preferredSize].width; |
+ if (!skipFirst) |
+ [[[itemController view] animator] setFrame:frame]; |
+ currentX += frame.size.width + kDownloadItemPadding; |
+ skipFirst = NO; |
+ } |
+} |
+ |
- (void)closed { |
// Don't remove completed downloads if the shelf is just being auto-hidden |
// rather than explicitly closed by the user. |
@@ -383,24 +365,41 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 }; |
- (void)mouseExited:(NSEvent*)event { |
// Cancel any previous hide requests, just to be safe. |
[NSObject cancelPreviousPerformRequestsWithTarget:self |
- selector:@selector(hide:) |
- object:self]; |
+ selector:@selector(autoClose) |
+ object:nil]; |
// Schedule an autoclose after a delay. If the mouse is moved back into the |
// view, or if an item is added to the shelf, the timer will be canceled. |
- [self performSelector:@selector(hide:) |
- withObject:self |
+ [self performSelector:@selector(autoClose) |
+ withObject:nil |
afterDelay:kAutoCloseDelaySeconds]; |
} |
-- (BOOL)canAutoClose { |
+- (void)maybeAutoCloseAfterDelay { |
+ // We can close the shelf automatically if all the downloads on the shelf have |
+ // been opened. |
for (NSUInteger i = 0; i < [downloadItemControllers_ count]; ++i) { |
DownloadItemController* itemController = |
[downloadItemControllers_ objectAtIndex:i]; |
if (![itemController download]->GetOpened()) |
- return NO; |
+ return; |
} |
- return YES; |
+ |
+ if ([self isVisible] && [downloadItemControllers_ count] > 0) { |
+ // If the shelf is visible and has download items remaining on it, close the |
+ // shelf after the user moves the mouse out of the download shelf. |
+ [self installTrackingArea]; |
+ } else { |
+ // We notify the DownloadShelf of our intention to close even if the shelf |
+ // is currently hidden. If the shelf was temporarily hidden (e.g. because |
+ // the browser window entered fullscreen mode), then this prevents the shelf |
+ // from being shown again when the browser exits fullscreen mode. |
+ [self autoClose]; |
+ } |
+} |
+ |
+- (void)autoClose { |
+ bridge_->Close(DownloadShelf::AUTOMATIC); |
} |
- (void)installTrackingArea { |
@@ -420,8 +419,8 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 }; |
- (void)cancelAutoCloseAndRemoveTrackingArea { |
[NSObject cancelPreviousPerformRequestsWithTarget:self |
- selector:@selector(hide:) |
- object:self]; |
+ selector:@selector(autoClose) |
+ object:nil]; |
if (trackingArea_.get()) { |
[[self view] removeTrackingArea:trackingArea_]; |