diff options
author | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-28 00:25:05 +0000 |
---|---|---|
committer | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-28 00:25:05 +0000 |
commit | 58a994249edb6c7b722c0d653c7490d517ba99a9 (patch) | |
tree | da49596f7694ab3d5ab3607b3115faebb781a3b0 /chrome/browser | |
parent | 93795fc2c67cfe9f607fe2354c1c17d3fa2f572f (diff) | |
download | chromium_src-58a994249edb6c7b722c0d653c7490d517ba99a9.zip chromium_src-58a994249edb6c7b722c0d653c7490d517ba99a9.tar.gz chromium_src-58a994249edb6c7b722c0d653c7490d517ba99a9.tar.bz2 |
First stab at download item overflow. Also add the image to the left of "Show all downloads" to the shelf.
BUG=14672,14665
TEST=Download several items. They should now no longer overlap the "Open all downloads" link.
Review URL: http://codereview.chromium.org/159384
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21759 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/cocoa/download_item_controller.h | 4 | ||||
-rw-r--r-- | chrome/browser/cocoa/download_item_controller.mm | 13 | ||||
-rw-r--r-- | chrome/browser/cocoa/download_shelf_controller.h | 25 | ||||
-rw-r--r-- | chrome/browser/cocoa/download_shelf_controller.mm | 82 |
4 files changed, 113 insertions, 11 deletions
diff --git a/chrome/browser/cocoa/download_item_controller.h b/chrome/browser/cocoa/download_item_controller.h index 8fa3831..7dc5e7e 100644 --- a/chrome/browser/cocoa/download_item_controller.h +++ b/chrome/browser/cocoa/download_item_controller.h @@ -42,6 +42,10 @@ class DownloadShelfContextMenuMac; // Remove ourself from the download UI. - (void)remove; +// Update item's visibility depending on if the item is still completely +// contained in its parent. +- (void)updateVisibility:(id)sender; + // Asynchronous icon loading callback. - (void)setIcon:(NSImage*)icon; diff --git a/chrome/browser/cocoa/download_item_controller.mm b/chrome/browser/cocoa/download_item_controller.mm index d00fd58..52ac1a1 100644 --- a/chrome/browser/cocoa/download_item_controller.mm +++ b/chrome/browser/cocoa/download_item_controller.mm @@ -29,6 +29,7 @@ class DownloadShelfContextMenuMac : public DownloadShelfContextMenu { using DownloadShelfContextMenu::CANCEL; }; + // Implementation of DownloadItemController @implementation DownloadItemController @@ -55,9 +56,7 @@ class DownloadShelfContextMenuMac : public DownloadShelfContextMenu { } - (void)setStateFromDownload:(BaseDownloadItemModel*)downloadModel { - // TODO(thakis): The windows version of this does all kinds of things - // (gratituous use of animation, special handling of dangerous downloads) - // that we don't currently do. + // TODO(thakis): handling of dangerous downloads -- crbug.com/14667 // Set the correct popup menu. if (downloadModel->download()->state() == DownloadItem::COMPLETE) @@ -78,6 +77,14 @@ class DownloadShelfContextMenuMac : public DownloadShelfContextMenu { [shelf_ remove:self]; } +- (void)updateVisibility:(id)sender { + // TODO(thakis): Make this prettier, by fading the items out or overlaying + // the partial visible one with a horizontal alpha gradient -- crbug.com/17830 + NSView* view = [self view]; + NSRect containerFrame = [[view superview] frame]; + [view setHidden:(NSMaxX([view frame]) > NSWidth(containerFrame))]; +} + - (IBAction)handleButtonClick:(id)sender { if ([cell_ isButtonPartPressed]) { DownloadItem* download = bridge_->download_model()->download(); diff --git a/chrome/browser/cocoa/download_shelf_controller.h b/chrome/browser/cocoa/download_shelf_controller.h index f598d5c..c72538a 100644 --- a/chrome/browser/cocoa/download_shelf_controller.h +++ b/chrome/browser/cocoa/download_shelf_controller.h @@ -14,12 +14,30 @@ class Browser; class DownloadShelf; @class DownloadShelfView; -// A controller class that manages the download shelf for one window. +// A controller class that manages the download shelf for one window. It is +// responsible for the behavior of the shelf itself (showing/hiding, handling +// the link, layout) as well as for managing the download items it contains. +// +// All the files in cocoa/downloads_* are related as follows: +// +// download_shelf_mac bridges calls from chromium's c++ world to the objc +// download_shelf_controller for the shelf (this file). The shelf's background +// is drawn by download_shelf_view. Every item in a shelf is controlled by a +// download_item_controller. +// +// download_item_mac bridges calls from chromium's c++ world to the objc +// download_item_controller, which is responsible for managing a single item +// on the shelf. The item controller loads its UI from a xib file, where the +// UI of an item itself is represented by a button that is drawn by +// download_item_cell. @interface DownloadShelfController : NSViewController { @private + IBOutlet NSScrollView* linkContainer_; IBOutlet NSTextView* showAllDownloadsLink_; + IBOutlet NSImageView* image_; + // Currently these two are always the same, but they mean slightly different // things. |contentAreaHasOffset_| is an implementation detail of the download // shelf visibility. @@ -27,11 +45,14 @@ class DownloadShelf; BOOL barIsVisible_; scoped_ptr<DownloadShelf> bridge_; - NSView* contentArea_; + NSView* contentArea_; // the browser's content area float shelfHeight_; // The download items we have added to our shelf. scoped_nsobject<NSMutableArray> downloadItemControllers_; + + // The container that contains (and clamps) all the download items. + IBOutlet NSView* itemContainerView_; }; - (id)initWithBrowser:(Browser*)browser contentArea:(NSView*)content; diff --git a/chrome/browser/cocoa/download_shelf_controller.mm b/chrome/browser/cocoa/download_shelf_controller.mm index ccb672d..0cb170a 100644 --- a/chrome/browser/cocoa/download_shelf_controller.mm +++ b/chrome/browser/cocoa/download_shelf_controller.mm @@ -17,6 +17,10 @@ namespace { +// Max number of download views we'll contain. Any time a view is added and +// we already have this many download views, one is removed. +const size_t kMaxDownloadItemCount = 16; + // Border padding of a download item. const int kDownloadItemBorderPadding = 3; @@ -38,6 +42,7 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8; - (void)applyContentAreaOffset:(BOOL)apply; - (void)positionBar; - (void)showDownloadShelf:(BOOL)enable; +- (void)resizeDownloadLinkToFit; @end @@ -81,6 +86,47 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8; [[showAllDownloadsLink_ textStorage] setAttributedString:linkText.get()]; [showAllDownloadsLink_ setDelegate:self]; + + [self resizeDownloadLinkToFit]; +} + +- (void)dealloc { + for (DownloadItemController* itemController + in downloadItemControllers_.get()) { + [[NSNotificationCenter defaultCenter] removeObserver:itemController]; + } + [super dealloc]; +} + +- (void)resizeDownloadLinkToFit { + // Get width required by localized download link text. + // http://developer.apple.com/documentation/Cocoa/Conceptual/TextLayout/Tasks/StringHeight.html + [[showAllDownloadsLink_ textContainer] setLineFragmentPadding:0.0]; + (void)[[showAllDownloadsLink_ layoutManager]glyphRangeForTextContainer: + [showAllDownloadsLink_ textContainer]]; + NSRect textRect = [[showAllDownloadsLink_ layoutManager] + usedRectForTextContainer:[showAllDownloadsLink_ textContainer]]; + + int offsetX = [showAllDownloadsLink_ frame].size.width - textRect.size.width; + + // Fit link itself. + NSRect linkFrame = [linkContainer_ frame]; + linkFrame.origin.x += offsetX; + linkFrame.size.width -= offsetX; + [linkContainer_ setFrame:linkFrame]; + [linkContainer_ setNeedsDisplay:YES]; + + // Move image. + NSRect imageFrame = [image_ frame]; + imageFrame.origin.x += offsetX; + [image_ setFrame:imageFrame]; + [image_ setNeedsDisplay:YES]; + + // Change item container size. + NSRect itemFrame = [itemContainerView_ frame]; + itemFrame.size.width += offsetX; + [itemContainerView_ setFrame:itemFrame]; + [itemContainerView_ setNeedsDisplay:YES]; } - (BOOL)textView:(NSTextView *)aTextView @@ -115,9 +161,13 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8; // 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]; [[download view] removeFromSuperview]; [downloadItemControllers_ removeObject:download]; + // TODO(thakis): Need to relayout the remaining item views here ( + // crbug.com/17831 ). + // Check to see if we have any downloads remaining and if not, hide the shelf. if (![downloadItemControllers_ count]) [self showDownloadShelf:NO]; @@ -195,17 +245,16 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8; // TODO(thakis): RTL support? // (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) // Shift all existing items to the right - for (DownloadItemController* itemController in downloadItemControllers_.get()) { + for (DownloadItemController* itemController + in downloadItemControllers_.get()) { NSRect frame = [[itemController view] frame]; frame.origin.x += kDownloadItemWidth + kDownloadItemPadding; [[[itemController view] animator] setFrame:frame]; } - // Insert new item at the left - int startX = kDownloadItemBorderPadding; - + // Insert new item at the left. // Start at width 0... - NSRect position = NSMakeRect(startX, kDownloadItemBorderPadding, + NSRect position = NSMakeRect(0, kDownloadItemBorderPadding, 0, kDownloadItemHeight); scoped_nsobject<DownloadItemController> controller( [[DownloadItemController alloc] initWithFrame:position @@ -213,7 +262,18 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8; shelf:self]); [downloadItemControllers_ addObject:controller.get()]; - [[self view] addSubview:[controller.get() view]]; + [itemContainerView_ addSubview:[controller.get() view]]; + + [[NSNotificationCenter defaultCenter] + addObserver:controller + selector:@selector(updateVisibility:) + name:NSViewFrameDidChangeNotification + object:[controller view]]; + [[NSNotificationCenter defaultCenter] + addObserver:controller + selector:@selector(updateVisibility:) + name:NSViewFrameDidChangeNotification + object:itemContainerView_]; // ...then animate in NSRect frame = [[controller.get() view] frame]; @@ -223,6 +283,16 @@ const NSTimeInterval kDownloadItemOpenDuration = 0.8; [[NSAnimationContext currentContext] setDuration:kDownloadItemOpenDuration]; [[[controller.get() view] animator] setFrame:frame]; [NSAnimationContext endGrouping]; + + // Keep only a limited number of items in the shelf. + if ([downloadItemControllers_ count] > kMaxDownloadItemCount) { + DCHECK(kMaxDownloadItemCount > 0); + + // Since no user will ever see the item being removed (needs a horizontal + // screen resolution greater than 3200 at 16 items at 200 pixels each), + // there's no point in animating the removal. + [self remove:[downloadItemControllers_ objectAtIndex:0]]; + } } @end |