Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1050)

Unified Diff: chrome/browser/ui/cocoa/download/download_shelf_controller.mm

Issue 3400027: [Mac] Makes the download shelf auto-close after the user opens all downloads... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/ui/cocoa/download/download_shelf_controller.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/ui/cocoa/download/download_shelf_controller.mm
===================================================================
--- chrome/browser/ui/cocoa/download/download_shelf_controller.mm (revision 69709)
+++ chrome/browser/ui/cocoa/download/download_shelf_controller.mm (working copy)
@@ -24,6 +24,24 @@
#include "grit/theme_resources.h"
#import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
+// Download shelf autoclose behavior:
+//
+// The download shelf autocloses if all of this is true:
+// 1) An item on the shelf has just been opened.
+// 2) All remaining items on the shelf have been opened in the past.
+// 3) The mouse leaves the shelf and remains off the shelf for 5 seconds.
+//
+// If the mouse re-enters the shelf within the 5 second grace period, the
+// autoclose is canceled. An autoclose can only be scheduled in response to a
+// shelf item being opened or removed. If an item is opened and then the
+// resulting autoclose is canceled, subsequent mouse exited events will NOT
+// trigger an autoclose.
+//
+// If the shelf is manually closed while a download is still in progress, that
+// download is marked as "opened" for these purposes. If the shelf is later
+// reopened, these previously-in-progress download will not block autoclose,
+// even if that download was never actually clicked on and opened.
+
namespace {
// Max number of download views we'll contain. Any time a view is added and
@@ -39,16 +57,24 @@
// Duration for download shelf closing animation, in seconds.
const NSTimeInterval kDownloadShelfCloseDuration = 0.12;
+// Amount of time between when the mouse is moved off the shelf and the shelf is
+// autoclosed, in seconds.
+const NSTimeInterval kAutoCloseDelaySeconds = 5;
+
} // namespace
@interface DownloadShelfController(Private)
- (void)showDownloadShelf:(BOOL)enable;
- (void)layoutItems:(BOOL)skipFirst;
- (void)closed;
+- (BOOL)canAutoClose;
- (void)updateTheme;
- (void)themeDidChangeNotification:(NSNotification*)notification;
- (void)viewFrameDidChange:(NSNotification*)notification;
+
+- (void)installTrackingArea;
+- (void)cancelAutoCloseAndRemoveTrackingArea;
@end
@@ -100,6 +126,7 @@
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
+ [self cancelAutoCloseAndRemoveTrackingArea];
// The controllers will unregister themselves as observers when they are
// deallocated. No need to do that here.
@@ -173,10 +200,19 @@
[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];
+}
+
// 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();
}
@@ -216,6 +252,8 @@
}
- (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.
@@ -255,6 +293,8 @@
- (void)addDownloadItem:(BaseDownloadItemModel*)model {
DCHECK([NSThread isMainThread]);
+ [self cancelAutoCloseAndRemoveTrackingArea];
+
// Insert new item at the left.
scoped_nsobject<DownloadItemController> controller(
[[DownloadItemController alloc] initWithModel:model shelf:self]);
@@ -312,16 +352,75 @@
while (i < [downloadItemControllers_ count]) {
DownloadItemController* itemController =
[downloadItemControllers_ objectAtIndex:i];
+ DownloadItem* download = [itemController download];
bool isTransferDone =
- [itemController download]->state() == DownloadItem::COMPLETE ||
- [itemController download]->state() == DownloadItem::CANCELLED;
+ download->state() == DownloadItem::COMPLETE ||
+ download->state() == DownloadItem::CANCELLED;
if (isTransferDone &&
- [itemController download]->safety_state() != DownloadItem::DANGEROUS) {
+ download->safety_state() != DownloadItem::DANGEROUS) {
[self remove:itemController];
} else {
+ // Treat the item as opened when we close. This way if we get shown again
+ // the user need not open this item for the shelf to auto-close.
+ download->set_opened(true);
++i;
}
}
}
+- (void)mouseEntered:(NSEvent*)event {
+ // If the mouse re-enters the download shelf, cancel the auto-close. Further
+ // mouse exits should not trigger autoclose, so also remove the tracking area.
+ [self cancelAutoCloseAndRemoveTrackingArea];
+}
+
+- (void)mouseExited:(NSEvent*)event {
+ // Cancel any previous hide requests, just to be safe.
+ [NSObject cancelPreviousPerformRequestsWithTarget:self
+ selector:@selector(hide:)
+ object:self];
+
+ // 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
+ afterDelay:kAutoCloseDelaySeconds];
+}
+
+- (BOOL)canAutoClose {
+ for (NSUInteger i = 0; i < [downloadItemControllers_ count]; ++i) {
+ DownloadItemController* itemController =
+ [downloadItemControllers_ objectAtIndex:i];
+ if (![itemController download]->opened())
+ return NO;
+ }
+ return YES;
+}
+
+- (void)installTrackingArea {
+ // Install the tracking area to listen for mouseExited messages and trigger
+ // the shelf autoclose.
+ if (trackingArea_.get())
+ return;
+
+ trackingArea_.reset([[NSTrackingArea alloc]
+ initWithRect:[[self view] bounds]
+ options:NSTrackingMouseEnteredAndExited |
+ NSTrackingActiveAlways
+ owner:self
+ userInfo:nil]);
+ [[self view] addTrackingArea:trackingArea_];
+}
+
+- (void)cancelAutoCloseAndRemoveTrackingArea {
+ [NSObject cancelPreviousPerformRequestsWithTarget:self
+ selector:@selector(hide:)
+ object:self];
+
+ if (trackingArea_.get()) {
+ [[self view] removeTrackingArea:trackingArea_];
+ trackingArea_.reset(nil);
+ }
+}
+
@end
« no previous file with comments | « chrome/browser/ui/cocoa/download/download_shelf_controller.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698