diff options
-rw-r--r-- | chrome/app/nibs/DownloadShelf.xib | 127 | ||||
-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 | ||||
-rw-r--r-- | chrome/chrome.gyp | 1 |
6 files changed, 232 insertions, 20 deletions
diff --git a/chrome/app/nibs/DownloadShelf.xib b/chrome/app/nibs/DownloadShelf.xib index f38954e..a910eab 100644 --- a/chrome/app/nibs/DownloadShelf.xib +++ b/chrome/app/nibs/DownloadShelf.xib @@ -84,7 +84,7 @@ <object class="NSTextView" id="550190606"> <reference key="NSNextResponder" ref="581923208"/> <int key="NSvFlags">2322</int> - <string key="NSFrameSize">{182, 31}</string> + <string key="NSFrameSize">{182, 12}</string> <reference key="NSSuperview" ref="581923208"/> <object class="NSTextContainer" key="NSTextContainer" id="526453298"> <object class="NSLayoutManager" key="NSLayoutManager"> @@ -280,7 +280,7 @@ </object> <int key="NSTVFlags">6</int> <string key="NSMaxSize">{463, 1e+07}</string> - <string key="NSMinize">{63, 31}</string> + <string key="NSMinize">{63, 3}</string> <nil key="NSDelegate"/> </object> </object> @@ -300,7 +300,6 @@ <int key="NSvFlags">256</int> <string key="NSFrame">{{-100, -100}, {15, 12}}</string> <reference key="NSSuperview" ref="433009119"/> - <bool key="NSEnabled">YES</bool> <reference key="NSTarget" ref="433009119"/> <string key="NSAction">_doScroller:</string> <double key="NSPercent">1.369863e-02</double> @@ -320,11 +319,50 @@ <string key="NSFrame">{{266, 13}, {182, 14}}</string> <reference key="NSSuperview" ref="1005"/> <reference key="NSNextKeyView" ref="581923208"/> - <int key="NSsFlags">64</int> + <int key="NSsFlags">0</int> <reference key="NSVScroller" ref="888760421"/> <reference key="NSHScroller" ref="199551096"/> <reference key="NSContentView" ref="581923208"/> </object> + <object class="NSCustomView" id="931787328"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">290</int> + <string key="NSFrame">{{3, 0}, {240, 40}}</string> + <reference key="NSSuperview" ref="1005"/> + <string key="NSClassName">NSView</string> + </object> + <object class="NSImageView" id="663605208"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">289</int> + <object class="NSMutableSet" key="NSDragTypes"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="set.sortedObjects"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>Apple PDF pasteboard type</string> + <string>Apple PICT pasteboard type</string> + <string>Apple PNG pasteboard type</string> + <string>NSFilenamesPboardType</string> + <string>NeXT Encapsulated PostScript v1.2 pasteboard type</string> + <string>NeXT TIFF v4.0 pasteboard type</string> + </object> + </object> + <string key="NSFrame">{{245, 11}, {16, 16}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSImageCell" key="NSCell" id="673439633"> + <int key="NSCellFlags">130560</int> + <int key="NSCellFlags2">33554432</int> + <object class="NSCustomResource" key="NSContents"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">downloads_favicon</string> + </object> + <int key="NSAlign">0</int> + <int key="NSScale">0</int> + <int key="NSStyle">0</int> + <bool key="NSAnimates">NO</bool> + </object> + <bool key="NSEditable">YES</bool> + </object> </object> <string key="NSFrameSize">{480, 40}</string> <reference key="NSSuperview"/> @@ -358,6 +396,30 @@ </object> <int key="connectionID">15</int> </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">linkContainer_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="433009119"/> + </object> + <int key="connectionID">18</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">itemContainerView_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="931787328"/> + </object> + <int key="connectionID">19</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">image_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="663605208"/> + </object> + <int key="connectionID">22</int> + </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> @@ -395,6 +457,8 @@ <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="538957441"/> <reference ref="433009119"/> + <reference ref="931787328"/> + <reference ref="663605208"/> </object> <reference key="parent" ref="1002"/> </object> @@ -438,6 +502,25 @@ <reference key="object" ref="550190606"/> <reference key="parent" ref="433009119"/> </object> + <object class="IBObjectRecord"> + <int key="objectID">16</int> + <reference key="object" ref="931787328"/> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">20</int> + <reference key="object" ref="663605208"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="673439633"/> + </object> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">21</int> + <reference key="object" ref="673439633"/> + <reference key="parent" ref="663605208"/> + </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> @@ -455,6 +538,9 @@ <string>11.IBPluginDependency</string> <string>12.IBPluginDependency</string> <string>13.IBPluginDependency</string> + <string>16.IBPluginDependency</string> + <string>20.IBPluginDependency</string> + <string>21.IBPluginDependency</string> <string>3.IBPluginDependency</string> <string>4.IBPluginDependency</string> </object> @@ -463,7 +549,7 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{79, 87}, {480, 40}}</string> + <string>{{845, 30}, {480, 40}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{628, 654}</string> <string>{{357, 416}, {480, 272}}</string> @@ -473,6 +559,9 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> </object> </object> <object class="NSMutableDictionary" key="unlocalizedProperties"> @@ -495,7 +584,7 @@ </object> </object> <nil key="sourceID"/> - <int key="maxID">15</int> + <int key="maxID">22</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> @@ -517,8 +606,21 @@ </object> </object> <object class="NSMutableDictionary" key="outlets"> - <string key="NS.key.0">showAllDownloadsLink_</string> - <string key="NS.object.0">NSTextView</string> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>image_</string> + <string>itemContainerView_</string> + <string>linkContainer_</string> + <string>showAllDownloadsLink_</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>NSImageView</string> + <string>NSView</string> + <string>NSScrollView</string> + <string>NSTextView</string> + </object> </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> @@ -537,13 +639,20 @@ <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/status_bubble_mac.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> <string key="minorKey">browser/cocoa/tab_strip_model_observer_bridge.h</string> </object> </object> </object> </object> <int key="IBDocument.localizationMode">0</int> - <string key="IBDocument.LastKnownRelativeProjectPath">../../../chrome.xcodeproj</string> + <string key="IBDocument.LastKnownRelativeProjectPath">../../chrome.xcodeproj</string> <int key="IBDocument.defaultPropertyAccessControl">3</int> </data> </archive> 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 diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index c353740..49a778e 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -2686,6 +2686,7 @@ 'app/theme/close_bar.pdf', 'app/theme/close_bar_h.pdf', 'app/theme/close_bar_p.pdf', + 'app/theme/downloads_favicon.png', 'app/theme/forward_Template.pdf', 'app/theme/frozen_tab.png', 'app/theme/go_Template.pdf', |