summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorthakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-28 00:25:05 +0000
committerthakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-28 00:25:05 +0000
commit58a994249edb6c7b722c0d653c7490d517ba99a9 (patch)
treeda49596f7694ab3d5ab3607b3115faebb781a3b0 /chrome/browser
parent93795fc2c67cfe9f607fe2354c1c17d3fa2f572f (diff)
downloadchromium_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.h4
-rw-r--r--chrome/browser/cocoa/download_item_controller.mm13
-rw-r--r--chrome/browser/cocoa/download_shelf_controller.h25
-rw-r--r--chrome/browser/cocoa/download_shelf_controller.mm82
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