diff options
author | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-21 19:41:53 +0000 |
---|---|---|
committer | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-21 19:41:53 +0000 |
commit | c7594166521973b656f13d7c08b75db7b603246f (patch) | |
tree | f6bbc6d48b88e63676e5ddcaee51b47a6df7b427 | |
parent | 6ee6185045be58242771fe6e0504b4147e0c1a2d (diff) | |
download | chromium_src-c7594166521973b656f13d7c08b75db7b603246f.zip chromium_src-c7594166521973b656f13d7c08b75db7b603246f.tar.gz chromium_src-c7594166521973b656f13d7c08b75db7b603246f.tar.bz2 |
Use a real download item.
BUG=14659,17100
TEST=Download multiple things. Items should now be inserted from the left. When a download is in progress, the time to completion should be displayed, when it's done the time should fade out and the filename should move down. Download items should appear in a sweep animation. Clicking the download directly should open it; clicking the arrow on the right of the download item should show the correct context menu. If a download filename is long, it should be elided in the middle.
Review URL: http://codereview.chromium.org/159060
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21201 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/app/nibs/DownloadItem.xib | 265 | ||||
-rw-r--r-- | chrome/app/nibs/DownloadShelf.xib | 8 | ||||
-rw-r--r-- | chrome/browser/cocoa/download_item_cell.h | 56 | ||||
-rw-r--r-- | chrome/browser/cocoa/download_item_cell.mm | 437 | ||||
-rw-r--r-- | chrome/browser/cocoa/download_item_controller.h | 9 | ||||
-rw-r--r-- | chrome/browser/cocoa/download_item_controller.mm | 49 | ||||
-rw-r--r-- | chrome/browser/cocoa/download_shelf_controller.mm | 42 | ||||
-rw-r--r-- | chrome/browser/cocoa/gradient_button_cell.h | 12 | ||||
-rw-r--r-- | chrome/browser/cocoa/gradient_button_cell.mm | 136 | ||||
-rw-r--r-- | chrome/chrome.gyp | 2 |
10 files changed, 762 insertions, 254 deletions
diff --git a/chrome/app/nibs/DownloadItem.xib b/chrome/app/nibs/DownloadItem.xib index 44ed1d21..383612d 100644 --- a/chrome/app/nibs/DownloadItem.xib +++ b/chrome/app/nibs/DownloadItem.xib @@ -8,8 +8,8 @@ <string key="IBDocument.HIToolboxVersion">353.00</string> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> - <integer value="24"/> - <integer value="4"/> + <integer value="1"/> + <integer value="28"/> <integer value="13"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> @@ -38,88 +38,35 @@ </object> <object class="NSCustomView" id="1005"> <reference key="NSNextResponder"/> - <int key="NSvFlags">268</int> + <int key="NSvFlags">292</int> <object class="NSMutableArray" key="NSSubviews"> <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSPopUpButton" id="690119733"> + <object class="NSButton" id="575090266"> <reference key="NSNextResponder" ref="1005"/> - <int key="NSvFlags">268</int> - <string key="NSFrame">{{0, 3}, {200, 26}}</string> + <int key="NSvFlags">292</int> + <string key="NSFrameSize">{200, 34}</string> <reference key="NSSuperview" ref="1005"/> <bool key="NSEnabled">YES</bool> - <object class="NSPopUpButtonCell" key="NSCell" id="750218797"> - <int key="NSCellFlags">-2076049856</int> - <int key="NSCellFlags2">134219776</int> + <object class="NSButtonCell" key="NSCell" id="966513665"> + <int key="NSCellFlags">-2080244224</int> + <int key="NSCellFlags2">134217728</int> + <string key="NSContents">Button</string> <object class="NSFont" key="NSSupport"> <string key="NSName">LucidaGrande</string> <double key="NSSize">1.300000e+01</double> <int key="NSfFlags">1044</int> </object> - <reference key="NSControlView" ref="690119733"/> - <int key="NSButtonFlags">-2035269377</int> - <int key="NSButtonFlags2">129</int> - <object class="NSImage" key="NSNormalImage"> - <int key="NSImageFlags">549650432</int> - <string key="NSSize">{1, 1}</string> - <object class="NSMutableArray" key="NSReps"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray"> - <bool key="EncodedWithXMLCoder">YES</bool> - <integer value="0"/> - <object class="NSBitmapImageRep"> - <object class="NSData" key="NSTIFFRepresentation"> - <bytes key="NS.bytes">TU0AKgAAAAoAAAANAQAAAwAAAAEAAQAAAQEAAwAAAAEAAQAAAQIAAwAAAAIACAAIAQMAAwAAAAEAAQAA -AQYAAwAAAAEAAQAAAREABAAAAAEAAAAIARIAAwAAAAEAAQAAARUAAwAAAAEAAgAAARYAAwAAAAEQAAAA -ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> - </object> - </object> - </object> - </object> - <object class="NSColor" key="NSColor"> - <int key="NSColorSpace">3</int> - <bytes key="NSWhite">MCAwAA</bytes> - </object> - </object> + <reference key="NSControlView" ref="575090266"/> + <int key="NSButtonFlags">-2038284033</int> + <int key="NSButtonFlags2">162</int> <string key="NSAlternateContents"/> <string key="NSKeyEquivalent"/> - <int key="NSPeriodicDelay">400</int> - <int key="NSPeriodicInterval">75</int> - <object class="NSMenuItem" key="NSMenuItem" id="593643111"> - <reference key="NSMenu" ref="672782413"/> - <bool key="NSIsHidden">YES</bool> - <string key="NSTitle"/> - <string key="NSKeyEquiv"/> - <int key="NSKeyEquivModMask">1048576</int> - <int key="NSMnemonicLoc">2147483647</int> - <object class="NSCustomResource" key="NSOnImage" id="503301017"> - <string key="NSClassName">NSImage</string> - <string key="NSResourceName">NSMenuCheckmark</string> - </object> - <object class="NSCustomResource" key="NSMixedImage" id="246735032"> - <string key="NSClassName">NSImage</string> - <string key="NSResourceName">NSMenuMixedState</string> - </object> - <string key="NSAction">_popUpItemAction:</string> - <reference key="NSTarget" ref="750218797"/> - </object> - <bool key="NSMenuItemRespectAlignment">YES</bool> - <object class="NSMenu" key="NSMenu" id="672782413"> - <string key="NSTitle">Unused</string> - <object class="NSMutableArray" key="NSMenuItems"> - <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="593643111"/> - </object> - </object> - <int key="NSSelectedIndex">-1</int> - <bool key="NSPullDown">YES</bool> - <int key="NSPreferredEdge">1</int> - <bool key="NSUsesItemFromMenu">YES</bool> - <bool key="NSAltersState">YES</bool> - <int key="NSArrowPosition">2</int> + <int key="NSPeriodicDelay">200</int> + <int key="NSPeriodicInterval">25</int> </object> </object> </object> - <string key="NSFrameSize">{200, 32}</string> + <string key="NSFrameSize">{200, 34}</string> <reference key="NSSuperview"/> <string key="NSClassName">NSView</string> </object> @@ -134,8 +81,14 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> - <reference key="NSOnImage" ref="503301017"/> - <reference key="NSMixedImage" ref="246735032"/> + <object class="NSCustomResource" key="NSOnImage" id="948795975"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">NSMenuCheckmark</string> + </object> + <object class="NSCustomResource" key="NSMixedImage" id="423932028"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">NSMenuMixedState</string> + </object> <string key="NSAction">_popUpItemAction:</string> </object> <object class="NSMenuItem" id="770771657"> @@ -144,8 +97,8 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> - <reference key="NSOnImage" ref="503301017"/> - <reference key="NSMixedImage" ref="246735032"/> + <reference key="NSOnImage" ref="948795975"/> + <reference key="NSMixedImage" ref="423932028"/> <string key="NSAction">_popUpItemAction:</string> </object> <object class="NSMenuItem" id="530126839"> @@ -154,8 +107,8 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> - <reference key="NSOnImage" ref="503301017"/> - <reference key="NSMixedImage" ref="246735032"/> + <reference key="NSOnImage" ref="948795975"/> + <reference key="NSMixedImage" ref="423932028"/> <string key="NSAction">_popUpItemAction:</string> </object> <object class="NSMenuItem" id="812951457"> @@ -165,8 +118,8 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> - <reference key="NSOnImage" ref="503301017"/> - <reference key="NSMixedImage" ref="246735032"/> + <reference key="NSOnImage" ref="948795975"/> + <reference key="NSMixedImage" ref="423932028"/> </object> <object class="NSMenuItem" id="191249624"> <reference key="NSMenu" ref="571207526"/> @@ -174,8 +127,8 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> - <reference key="NSOnImage" ref="503301017"/> - <reference key="NSMixedImage" ref="246735032"/> + <reference key="NSOnImage" ref="948795975"/> + <reference key="NSMixedImage" ref="423932028"/> <string key="NSAction">_popUpItemAction:</string> </object> <object class="NSMenuItem" id="285298090"> @@ -185,8 +138,8 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> - <reference key="NSOnImage" ref="503301017"/> - <reference key="NSMixedImage" ref="246735032"/> + <reference key="NSOnImage" ref="948795975"/> + <reference key="NSMixedImage" ref="423932028"/> </object> <object class="NSMenuItem" id="693025028"> <reference key="NSMenu" ref="571207526"/> @@ -194,8 +147,8 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> - <reference key="NSOnImage" ref="503301017"/> - <reference key="NSMixedImage" ref="246735032"/> + <reference key="NSOnImage" ref="948795975"/> + <reference key="NSMixedImage" ref="423932028"/> <string key="NSAction">_popUpItemAction:</string> </object> </object> @@ -211,8 +164,8 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> - <reference key="NSOnImage" ref="503301017"/> - <reference key="NSMixedImage" ref="246735032"/> + <reference key="NSOnImage" ref="948795975"/> + <reference key="NSMixedImage" ref="423932028"/> <string key="NSAction">_popUpItemAction:</string> </object> <object class="NSMenuItem" id="514660119"> @@ -221,8 +174,8 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> - <reference key="NSOnImage" ref="503301017"/> - <reference key="NSMixedImage" ref="246735032"/> + <reference key="NSOnImage" ref="948795975"/> + <reference key="NSMixedImage" ref="423932028"/> <string key="NSAction">_popUpItemAction:</string> </object> <object class="NSMenuItem" id="769910664"> @@ -231,8 +184,8 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> - <reference key="NSOnImage" ref="503301017"/> - <reference key="NSMixedImage" ref="246735032"/> + <reference key="NSOnImage" ref="948795975"/> + <reference key="NSMixedImage" ref="423932028"/> <string key="NSAction">_popUpItemAction:</string> </object> <object class="NSMenuItem" id="858143630"> @@ -242,8 +195,8 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> - <reference key="NSOnImage" ref="503301017"/> - <reference key="NSMixedImage" ref="246735032"/> + <reference key="NSOnImage" ref="948795975"/> + <reference key="NSMixedImage" ref="423932028"/> </object> <object class="NSMenuItem" id="434679781"> <reference key="NSMenu" ref="231354576"/> @@ -251,8 +204,8 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> - <reference key="NSOnImage" ref="503301017"/> - <reference key="NSMixedImage" ref="246735032"/> + <reference key="NSOnImage" ref="948795975"/> + <reference key="NSMixedImage" ref="423932028"/> <string key="NSAction">_popUpItemAction:</string> </object> <object class="NSMenuItem" id="158646227"> @@ -262,8 +215,8 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string key="NSTitle"/> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> - <reference key="NSOnImage" ref="503301017"/> - <reference key="NSMixedImage" ref="246735032"/> + <reference key="NSOnImage" ref="948795975"/> + <reference key="NSMixedImage" ref="423932028"/> </object> <object class="NSMenuItem" id="93640760"> <reference key="NSMenu" ref="231354576"/> @@ -271,8 +224,8 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string key="NSKeyEquiv"/> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> - <reference key="NSOnImage" ref="503301017"/> - <reference key="NSMixedImage" ref="246735032"/> + <reference key="NSOnImage" ref="948795975"/> + <reference key="NSMixedImage" ref="423932028"/> <string key="NSAction">_popUpItemAction:</string> </object> </object> @@ -283,14 +236,6 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBConnectionRecord"> <object class="IBOutletConnection" key="connection"> - <string key="label">popupButton_</string> - <reference key="source" ref="1001"/> - <reference key="destination" ref="690119733"/> - </object> - <int key="connectionID">12</int> - </object> - <object class="IBConnectionRecord"> - <object class="IBOutletConnection" key="connection"> <string key="label">completeDownloadMenu_</string> <reference key="source" ref="1001"/> <reference key="destination" ref="571207526"/> @@ -377,6 +322,30 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> </object> <int key="connectionID">43</int> </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">progressView_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="575090266"/> + </object> + <int key="connectionID">61</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">handleButtonClick:</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="575090266"/> + </object> + <int key="connectionID">62</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">cell_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="966513665"/> + </object> + <int key="connectionID">63</int> + </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> @@ -412,43 +381,11 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <reference key="object" ref="1005"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="690119733"/> + <reference ref="575090266"/> </object> <reference key="parent" ref="1002"/> </object> <object class="IBObjectRecord"> - <int key="objectID">2</int> - <reference key="object" ref="690119733"/> - <object class="NSMutableArray" key="children"> - <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="750218797"/> - </object> - <reference key="parent" ref="1005"/> - </object> - <object class="IBObjectRecord"> - <int key="objectID">3</int> - <reference key="object" ref="750218797"/> - <object class="NSMutableArray" key="children"> - <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="672782413"/> - </object> - <reference key="parent" ref="690119733"/> - </object> - <object class="IBObjectRecord"> - <int key="objectID">4</int> - <reference key="object" ref="672782413"/> - <object class="NSMutableArray" key="children"> - <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="593643111"/> - </object> - <reference key="parent" ref="750218797"/> - </object> - <object class="IBObjectRecord"> - <int key="objectID">8</int> - <reference key="object" ref="593643111"/> - <reference key="parent" ref="672782413"/> - </object> - <object class="IBObjectRecord"> <int key="objectID">13</int> <reference key="object" ref="571207526"/> <object class="NSMutableArray" key="children"> @@ -548,6 +485,20 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <reference key="object" ref="514660119"/> <reference key="parent" ref="231354576"/> </object> + <object class="IBObjectRecord"> + <int key="objectID">59</int> + <reference key="object" ref="575090266"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="966513665"/> + </object> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">60</int> + <reference key="object" ref="966513665"/> + <reference key="parent" ref="575090266"/> + </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> @@ -569,7 +520,6 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string>17.IBPluginDependency</string> <string>18.IBPluginDependency</string> <string>19.IBPluginDependency</string> - <string>2.IBPluginDependency</string> <string>20.IBPluginDependency</string> <string>24.IBEditorWindowLastContentRect</string> <string>24.IBPluginDependency</string> @@ -578,19 +528,18 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string>27.IBPluginDependency</string> <string>28.IBPluginDependency</string> <string>29.IBPluginDependency</string> - <string>3.IBPluginDependency</string> <string>30.IBPluginDependency</string> <string>31.IBPluginDependency</string> - <string>4.IBEditorWindowLastContentRect</string> - <string>4.IBPluginDependency</string> - <string>8.IBPluginDependency</string> + <string>59.IBPluginDependency</string> + <string>60.CustomClassName</string> + <string>60.IBPluginDependency</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{348, 715}, {200, 32}}</string> + <string>{{348, 713}, {200, 34}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{628, 654}</string> <string>{{357, 416}, {480, 272}}</string> @@ -603,8 +552,7 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <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>{{337, 621}, {227, 123}}</string> + <string>{{52, 549}, {227, 123}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -614,8 +562,7 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{337, 721}, {200, 23}}</string> - <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>DownloadItemCell</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> </object> </object> @@ -639,12 +586,24 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> </object> </object> <nil key="sourceID"/> - <int key="maxID">43</int> + <int key="maxID">63</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBPartialClassDescription"> + <string key="className">DownloadItemCell</string> + <string key="superclassName">NSButtonCell</string> + <object class="NSMutableDictionary" key="actions"> + <string key="NS.key.0">updateTrackingAreas:</string> + <string key="NS.object.0">id</string> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/download_item_cell.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> <string key="className">DownloadItemController</string> <string key="superclassName">NSViewController</string> <object class="NSMutableDictionary" key="actions"> @@ -652,6 +611,7 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <object class="NSMutableArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>handleAlwaysOpen:</string> + <string>handleButtonClick:</string> <string>handleCancel:</string> <string>handleOpen:</string> <string>handleReveal:</string> @@ -662,6 +622,7 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <string>id</string> <string>id</string> <string>id</string> + <string>id</string> </object> </object> <object class="NSMutableDictionary" key="outlets"> @@ -669,14 +630,16 @@ ARcABAAAAAEAAAACARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <object class="NSMutableArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>activeDownloadMenu_</string> + <string>cell_</string> <string>completeDownloadMenu_</string> - <string>popupButton_</string> + <string>progressView_</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>NSMenu</string> + <string>DownloadItemCell</string> <string>NSMenu</string> - <string>NSPopUpButton</string> + <string>NSButton</string> </object> </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> diff --git a/chrome/app/nibs/DownloadShelf.xib b/chrome/app/nibs/DownloadShelf.xib index 24331a1..f38954e 100644 --- a/chrome/app/nibs/DownloadShelf.xib +++ b/chrome/app/nibs/DownloadShelf.xib @@ -8,7 +8,7 @@ <string key="IBDocument.HIToolboxVersion">353.00</string> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> - <integer value="10"/> + <integer value="1" id="9"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -84,7 +84,7 @@ <object class="NSTextView" id="550190606"> <reference key="NSNextResponder" ref="581923208"/> <int key="NSvFlags">2322</int> - <string key="NSFrameSize">{182, 45}</string> + <string key="NSFrameSize">{182, 31}</string> <reference key="NSSuperview" ref="581923208"/> <object class="NSTextContainer" key="NSTextContainer" id="526453298"> <object class="NSLayoutManager" key="NSLayoutManager"> @@ -273,14 +273,14 @@ <int key="NSColorSpace">1</int> <bytes key="NSRGB">MCAwIDEAA</bytes> </object> - <integer value="1"/> + <reference ref="9"/> </object> </object> <nil key="NSDefaultParagraphStyle"/> </object> <int key="NSTVFlags">6</int> <string key="NSMaxSize">{463, 1e+07}</string> - <string key="NSMinize">{63, 45}</string> + <string key="NSMinize">{63, 31}</string> <nil key="NSDelegate"/> </object> </object> diff --git a/chrome/browser/cocoa/download_item_cell.h b/chrome/browser/cocoa/download_item_cell.h new file mode 100644 index 0000000..e2c5162 --- /dev/null +++ b/chrome/browser/cocoa/download_item_cell.h @@ -0,0 +1,56 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_COCOA_DOWNLOAD_ITEM_CELL_H_ +#define CHROME_BROWSER_COCOA_DOWNLOAD_ITEM_CELL_H_ + +#import "chrome/browser/cocoa/gradient_button_cell.h" + +#include "base/file_path.h" + +class BaseDownloadItemModel; + +// A button cell that implements the weird button/popup button hybrid that is +// used by the download items. + +// The button represented by this cell consists of a button part on the left +// and a dropdown-menu part on the right. This enum describes which part the +// mouse cursor is over currently. +enum DownloadItemMousePosition { + kDownloadItemMouseOutside, + kDownloadItemMouseOverButtonPart, + kDownloadItemMouseOverDropdownPart +}; + +@interface DownloadItemCell : GradientButtonCell { + @private + // Track which part of the button the mouse is over + DownloadItemMousePosition mousePosition_; + int mouseInsideCount_; + scoped_nsobject<NSTrackingArea> trackingAreaButton_; + scoped_nsobject<NSTrackingArea> trackingAreaDropdown_; + + FilePath downloadPath_; // stored unelided + NSString* secondaryTitle_; + NSFont* secondaryFont_; + + BOOL isStatusTextVisible_; + CGFloat titleY_; + CGFloat statusAlpha_; + scoped_nsobject<NSAnimation> hideStatusAnimation_; +} + +- (void)setStateFromDownload:(BaseDownloadItemModel*)downloadModel; + +@property (copy) NSString* secondaryTitle; +@property (retain) NSFont* secondaryFont; + +// Valid to call in response to a click of the cell's button. Returns if the +// button part of the cell was clicked. +- (BOOL)isButtonPartPressed; + +@end + +#endif // CHROME_BROWSER_COCOA_DOWNLOAD_ITEM_CELL_H_ + diff --git a/chrome/browser/cocoa/download_item_cell.mm b/chrome/browser/cocoa/download_item_cell.mm new file mode 100644 index 0000000..62f0ec4 --- /dev/null +++ b/chrome/browser/cocoa/download_item_cell.mm @@ -0,0 +1,437 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/download_item_cell.h" + +#include "app/gfx/text_elider.h" +#include "app/l10n_util.h" +#include "base/mac_util.h" +#include "base/sys_string_conversions.h" +#import "chrome/browser/cocoa/download_item_cell.h" +#include "chrome/browser/download/download_item_model.h" +#include "chrome/browser/download/download_manager.h" +#import "third_party/GTM/AppKit/GTMTheme.h" + +namespace { + +// Distance from top border to icon +const CGFloat kImagePaddingTop = 1; + +// Distance from left border to icon +const CGFloat kImagePaddingLeft = 1; + +// Width of icon +const CGFloat kImageWidth = 32; + +// Height of icon +const CGFloat kImageHeight = 32; + +// x coordinate of download name string, in view coords +const CGFloat kTextPosLeft = kImagePaddingLeft + kImageWidth + 1; + +// Distance from end of download name string to dropdown area +const CGFloat kTextPaddingRight = 3; + +// y coordinate of download name string, in view coords, when status message +// is visible +const CGFloat kPrimaryTextPosTop = 5; + +// y coordinate of download name string, in view coords, when status message +// is not visible +const CGFloat kPrimaryTextOnlyPosTop = 10; + +// y coordinate of status message, in view coords +const CGFloat kSecondaryTextPosTop = 17; + +// Width of dropdown area on the right +const CGFloat kDropdownAreaWidth = 18; + +// Width of dropdown arrow +const CGFloat kDropdownArrowWidth = 5; + +// Height of dropdown arrow +const CGFloat kDropdownArrowHeight = 3; + +// Duration of the two-lines-to-one-line animation, in seconds +NSTimeInterval kHideStatusDuration = 0.3; + +} + +// This is a helper class to animate the fading out of the status text. +@interface HideSecondaryTitleAnimation : NSAnimation { + DownloadItemCell* cell_; +} +- (id)initWithDownloadItemCell:(DownloadItemCell*)cell; +@end + +@interface DownloadItemCell(Private) +- (void)updateTrackingAreas:(id)sender; +- (void)hideSecondaryTitle; +- (void)animationProgressed:(NSAnimationProgress)progress; +@end + +@implementation DownloadItemCell + +@synthesize secondaryTitle = secondaryTitle_; +@synthesize secondaryFont = secondaryFont_; + +- (void)setInitialState { + isStatusTextVisible_ = NO; + titleY_ = kPrimaryTextPosTop; + statusAlpha_ = 1.0; + + [self setFont:[NSFont systemFontOfSize: + [NSFont systemFontSizeForControlSize:NSSmallControlSize]]]; + [self setSecondaryFont:[NSFont systemFontOfSize: + [NSFont systemFontSizeForControlSize:NSMiniControlSize]]]; + + [self updateTrackingAreas:self]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(updateTrackingAreas:) + name:NSViewFrameDidChangeNotification + object:[self controlView]]; +} + +// For nib instantiations +- (id)initWithCoder:(NSCoder*)decoder { + if ((self = [super initWithCoder:decoder])) { + [self setInitialState]; + } + return self; +} + +// For programmatic instantiations +- (id)initTextCell:(NSString *)string { + if ((self = [super initTextCell:string])) { + [self setInitialState]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [secondaryTitle_ release]; + [secondaryFont_ release]; + [super dealloc]; +} + +- (void)setStateFromDownload:(BaseDownloadItemModel*)downloadModel { + // Set name and icon of download. + downloadPath_ = downloadModel->download()->GetFileName(); + + // TODO(paulg): Use IconManager for loading icons on the file thread + // (crbug.com/16226). + NSString* extension = base::SysUTF8ToNSString(downloadPath_.Extension()); + NSImage* icon = [[NSWorkspace sharedWorkspace] iconForFileType:extension]; + [self setImage:icon]; + + std::wstring statusText = downloadModel->GetStatusText(); + if (statusText.empty()) { + // Remove the status text label. + [self hideSecondaryTitle]; + isStatusTextVisible_ = NO; + } else { + // Set status text. + NSString* statusString = base::SysWideToNSString(statusText); + [self setSecondaryTitle:statusString]; + isStatusTextVisible_ = YES; + } +} + +- (void)updateTrackingAreas:(id)sender { + if (trackingAreaButton_) { + [[self controlView] removeTrackingArea:trackingAreaButton_.get()]; + trackingAreaButton_.reset(nil); + } + if (trackingAreaDropdown_) { + [[self controlView] removeTrackingArea:trackingAreaDropdown_.get()]; + trackingAreaDropdown_.reset(nil); + } + + // Use two distinct tracking rects for left and right parts. + NSRect bounds = [[self controlView] bounds]; + NSRect buttonRect, dropdownRect; + NSDivideRect(bounds, &dropdownRect, &buttonRect, + kDropdownAreaWidth, NSMaxXEdge); + + trackingAreaButton_.reset([[NSTrackingArea alloc] + initWithRect:buttonRect + options:(NSTrackingMouseEnteredAndExited | + NSTrackingActiveInActiveApp) + owner:self + userInfo:nil]); + [[self controlView] addTrackingArea:trackingAreaButton_.get()]; + + trackingAreaDropdown_.reset([[NSTrackingArea alloc] + initWithRect:dropdownRect + options:(NSTrackingMouseEnteredAndExited | + NSTrackingActiveInActiveApp) + owner:self + userInfo:nil]); + [[self controlView] addTrackingArea:trackingAreaDropdown_.get()]; +} + +- (void)setShowsBorderOnlyWhileMouseInside:(BOOL)showOnly { + // Override to make sure it doesn't do anything if it's called accidentally. +} + +- (void)mouseEntered:(NSEvent*)theEvent { + mouseInsideCount_++; + if ([theEvent trackingArea] == trackingAreaButton_.get()) + mousePosition_ = kDownloadItemMouseOverButtonPart; + else if ([theEvent trackingArea] == trackingAreaDropdown_.get()) + mousePosition_ = kDownloadItemMouseOverButtonPart; + [[self controlView] setNeedsDisplay:YES]; +} + +- (void)mouseExited:(NSEvent *)theEvent { + mouseInsideCount_--; + if (mouseInsideCount_ == 0) + mousePosition_ = kDownloadItemMouseOutside; + [[self controlView] setNeedsDisplay:YES]; +} + +- (BOOL)isMouseInside { + return mousePosition_ != kDownloadItemMouseOutside; +} + +- (BOOL)isMouseOverButtonPart { + return mousePosition_ == kDownloadItemMouseOverButtonPart; +} + +- (BOOL)isButtonPartPressed { + return [self isHighlighted] + && mousePosition_ == kDownloadItemMouseOverButtonPart; +} + +- (BOOL)isMouseOverDropdownPart { + return mousePosition_ == kDownloadItemMouseOverButtonPart; +} + +- (BOOL)isDropdownPartPressed { + return [self isHighlighted] + && mousePosition_ == kDownloadItemMouseOverButtonPart; +} + +- (NSBezierPath*)leftRoundedPath:(CGFloat)radius inRect:(NSRect)rect { + + NSPoint topLeft = NSMakePoint(NSMinX(rect), NSMaxY(rect)); + NSPoint topRight = NSMakePoint(NSMaxX(rect), NSMaxY(rect)); + NSPoint bottomRight = NSMakePoint(NSMaxX(rect) , NSMinY(rect)); + + NSBezierPath* path = [NSBezierPath bezierPath]; + [path moveToPoint:topRight]; + [path appendBezierPathWithArcFromPoint:topLeft + toPoint:rect.origin + radius:radius]; + [path appendBezierPathWithArcFromPoint:rect.origin + toPoint:bottomRight + radius:radius]; + [path lineToPoint:bottomRight]; + return path; +} + +- (NSBezierPath*)rightRoundedPath:(CGFloat)radius inRect:(NSRect)rect { + + NSPoint topLeft = NSMakePoint(NSMinX(rect), NSMaxY(rect)); + NSPoint topRight = NSMakePoint(NSMaxX(rect), NSMaxY(rect)); + NSPoint bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect)); + + NSBezierPath* path = [NSBezierPath bezierPath]; + [path moveToPoint:rect.origin]; + [path appendBezierPathWithArcFromPoint:bottomRight + toPoint:topRight + radius:radius]; + [path appendBezierPathWithArcFromPoint:topRight + toPoint:topLeft + radius:radius]; + [path lineToPoint:topLeft]; + [path closePath]; // Right path is closed + return path; +} + +- (void)elideTitle:(int)availableWidth { + NSFont* font = [self font]; + gfx::Font font_chr = + gfx::Font::CreateFont(base::SysNSStringToWide([font fontName]), + [font pointSize]); + + NSString* titleString = base::SysWideToNSString( + ElideFilename(downloadPath_, font_chr, availableWidth)); + [self setTitle:titleString]; +} + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { + + // Constants from Cole. Will kConstan them once the feedback loop + // is complete. + NSRect drawFrame = NSInsetRect(cellFrame, 0.5, 0.5); + NSRect innerFrame = NSInsetRect(cellFrame, 1, 1); + + const float radius = 3.5; + NSWindow* window = [controlView window]; + BOOL active = [window isKeyWindow] || [window isMainWindow]; + + GTMTheme* theme = [controlView gtm_theme]; + + NSRect buttonDrawRect, dropdownDrawRect; + NSDivideRect(drawFrame, &dropdownDrawRect, &buttonDrawRect, + kDropdownAreaWidth, NSMaxXEdge); + + NSRect buttonInnerRect, dropdownInnerRect; + NSDivideRect(innerFrame, &dropdownInnerRect, &buttonInnerRect, + kDropdownAreaWidth, NSMaxXEdge); + + NSBezierPath* buttonInnerPath = [self + leftRoundedPath:radius inRect:buttonDrawRect]; + NSBezierPath* buttonOuterPath = [self + leftRoundedPath:(radius + 1) + inRect:NSInsetRect(buttonDrawRect, -1, -1)]; + + NSBezierPath* dropdownInnerPath = [self + rightRoundedPath:radius inRect:dropdownDrawRect]; + NSBezierPath* dropdownOuterPath = [self + rightRoundedPath:(radius + 1) + inRect:NSInsetRect(dropdownDrawRect, -1, -1)]; + + // Stroke the borders and appropriate fill gradient. If we're borderless, + // the only time we want to draw the inner gradient is if we're highlighted. + if ([self isHighlighted] || [self isMouseInside]) { + [self drawBorderAndFillForTheme:theme + controlView:controlView + outerPath:buttonOuterPath + innerPath:buttonInnerPath + showHighlightGradient:[self isMouseOverButtonPart] + showClickedGradient:[self isButtonPartPressed] + active:active + cellFrame:cellFrame]; + + [self drawBorderAndFillForTheme: theme + controlView:controlView + outerPath:dropdownOuterPath + innerPath:dropdownInnerPath + showHighlightGradient:[self isMouseOverDropdownPart] + showClickedGradient:[self isDropdownPartPressed] + active:active + cellFrame:cellFrame]; + } + + [self drawInteriorWithFrame:innerFrame inView:controlView]; +} + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { + // Draw title + [self elideTitle:cellFrame.size.width - + (kTextPosLeft + kTextPaddingRight + kDropdownAreaWidth)]; + + NSColor* color = [self isButtonPartPressed] + ? [NSColor alternateSelectedControlTextColor] : [NSColor textColor]; + NSString* primaryText = [self title]; + + NSDictionary* primaryTextAttributes = [NSDictionary + dictionaryWithObjectsAndKeys: + color, NSForegroundColorAttributeName, + [self font], NSFontAttributeName, + nil]; + NSPoint primaryPos = NSMakePoint( + cellFrame.origin.x + kTextPosLeft, + titleY_); + + [primaryText drawAtPoint:primaryPos withAttributes:primaryTextAttributes]; + + // Draw secondary title, if any + if ([self secondaryTitle] != nil && statusAlpha_ > 0) { + NSString* secondaryText = [self secondaryTitle]; + NSColor* secondaryColor = [color colorWithAlphaComponent:statusAlpha_]; + NSDictionary* secondaryTextAttributes = [NSDictionary + dictionaryWithObjectsAndKeys: + secondaryColor, NSForegroundColorAttributeName, + [self secondaryFont], NSFontAttributeName, + nil]; + NSPoint secondaryPos = NSMakePoint( + cellFrame.origin.x + kTextPosLeft, + kSecondaryTextPosTop); + [secondaryText drawAtPoint:secondaryPos + withAttributes:secondaryTextAttributes]; + } + + // Draw icon + NSRect imageRect = NSZeroRect; + imageRect.size = [[self image] size]; + [[self image] setFlipped:[controlView isFlipped]]; + [[self image] drawInRect:[self imageRectForBounds:cellFrame] + fromRect:imageRect + operation:NSCompositeSourceOver + fraction:[self isEnabled] ? 1.0 : 0.5]; + + // Popup arrow. Put center of mass of the arrow in the center of the + // dropdown area. + CGFloat cx = NSMaxX(cellFrame) - kDropdownAreaWidth/2; + CGFloat cy = NSMidY(cellFrame); + NSPoint p1 = NSMakePoint(cx - kDropdownArrowWidth/2, + cy - kDropdownArrowHeight/3); + NSPoint p2 = NSMakePoint(cx + kDropdownArrowWidth/2, + cy - kDropdownArrowHeight/3); + NSPoint p3 = NSMakePoint(cx, cy + kDropdownArrowHeight*2/3); + NSBezierPath *triangle = [NSBezierPath bezierPath]; + [triangle moveToPoint:p1]; + [triangle lineToPoint:p2]; + [triangle lineToPoint:p3]; + [triangle closePath]; + + NSColor* fill = [self isDropdownPartPressed] + ? [NSColor alternateSelectedControlTextColor] : [NSColor textColor]; + [fill setFill]; + [triangle fill]; +} + +- (NSRect)imageRectForBounds:(NSRect)cellFrame { + return NSMakeRect( + kImagePaddingLeft, kImagePaddingTop, kImageWidth, kImageHeight); +} + +- (void)hideSecondaryTitle { + if (isStatusTextVisible_) { + // No core animation -- text in CA layers is not subpixel antialiased :-/ + hideStatusAnimation_.reset([[HideSecondaryTitleAnimation alloc] + initWithDownloadItemCell:self]); + [hideStatusAnimation_.get() setDelegate:self]; + [hideStatusAnimation_.get() startAnimation]; + } else { + // If the download is done so quickly that the status line is never visible, + // don't show an animation + [self animationProgressed:1.0]; + } +} + +- (void)animationProgressed:(NSAnimationProgress)progress { + titleY_ = progress*kPrimaryTextOnlyPosTop + (1 - progress)*kPrimaryTextPosTop; + statusAlpha_ = 1 - progress; + [[self controlView] setNeedsDisplay:YES]; +} + +- (void)animationDidEnd:(NSAnimation *)animation { + hideStatusAnimation_.reset(); +} + +@end + +@implementation HideSecondaryTitleAnimation + +- (id)initWithDownloadItemCell:(DownloadItemCell*)cell { + if ((self = [super initWithDuration:kHideStatusDuration + animationCurve:NSAnimationEaseIn])) { + cell_ = cell; + [self setAnimationBlockingMode:NSAnimationNonblocking]; + } + return self; +} + +- (void)setCurrentProgress:(NSAnimationProgress)progress { + [super setCurrentProgress:progress]; + [cell_ animationProgressed:progress]; +} + +@end diff --git a/chrome/browser/cocoa/download_item_controller.h b/chrome/browser/cocoa/download_item_controller.h index dec9f7c..30bc28e 100644 --- a/chrome/browser/cocoa/download_item_controller.h +++ b/chrome/browser/cocoa/download_item_controller.h @@ -7,6 +7,7 @@ #include "base/scoped_ptr.h" class BaseDownloadItemModel; +@class DownloadItemCell; class DownloadItemMac; class DownloadShelfContextMenuMac; @class DownloadShelfController; @@ -15,11 +16,14 @@ class DownloadShelfContextMenuMac; @interface DownloadItemController : NSViewController { @private - IBOutlet NSPopUpButton* popupButton_; + IBOutlet NSButton* progressView_; + IBOutlet DownloadItemCell* cell_; IBOutlet NSMenu* activeDownloadMenu_; IBOutlet NSMenu* completeDownloadMenu_; + NSMenu* currentMenu_; // points to one of the two menus above + scoped_ptr<DownloadItemMac> bridge_; scoped_ptr<DownloadShelfContextMenuMac> menuBridge_; @@ -38,6 +42,9 @@ class DownloadShelfContextMenuMac; // Remove ourself from the download UI. - (void)remove; +// Download item button clicked +- (IBAction)handleButtonClick:(id)sender; + // Context menu handlers. - (IBAction)handleOpen:(id)sender; - (IBAction)handleAlwaysOpen:(id)sender; diff --git a/chrome/browser/cocoa/download_item_controller.mm b/chrome/browser/cocoa/download_item_controller.mm index aa0d8a5..f5d2836 100644 --- a/chrome/browser/cocoa/download_item_controller.mm +++ b/chrome/browser/cocoa/download_item_controller.mm @@ -4,12 +4,13 @@ #import "chrome/browser/cocoa/download_item_controller.h" -#include "app/l10n_util.h" #include "base/mac_util.h" -#include "base/sys_string_conversions.h" +#import "chrome/browser/cocoa/download_item_cell.h" #include "chrome/browser/cocoa/download_item_mac.h" #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_shelf.h" +#include "chrome/browser/download/download_util.h" + // A class for the chromium-side part of the download shelf context menu. @@ -59,32 +60,12 @@ class DownloadShelfContextMenuMac : public DownloadShelfContextMenu { // Set correct popup menu. if (downloadModel->download()->state() == DownloadItem::COMPLETE) - [popupButton_ setMenu:completeDownloadMenu_]; + currentMenu_ = completeDownloadMenu_; else - [popupButton_ setMenu:activeDownloadMenu_]; - - // Set name and icon of download. - FilePath downloadPath = downloadModel->download()->GetFileName(); - - // TODO(thakis): use filename eliding like gtk/windows versions. - NSString* titleString = base::SysWideToNSString(downloadPath.ToWStringHack()); - [[popupButton_ itemAtIndex:0] setTitle:titleString]; - - // TODO(paulg): Use IconManager for loading icons on the file thread - // (crbug.com/16226). - NSString* extension = base::SysUTF8ToNSString(downloadPath.Extension()); - [[popupButton_ itemAtIndex:0] setImage: - [[NSWorkspace sharedWorkspace] iconForFileType:extension]]; - - // Set status text. - std::wstring statusText = downloadModel->GetStatusText(); - // Remove the status text label. - if (statusText.empty()) { - // TODO(thakis): Once there is a status label, hide it here. - return; - } + currentMenu_ = activeDownloadMenu_; - // TODO(thakis): Set status_text as status label. + [progressView_ setMenu:currentMenu_]; // for context menu + [cell_ setStateFromDownload:downloadModel]; } - (void)remove { @@ -92,6 +73,22 @@ class DownloadShelfContextMenuMac : public DownloadShelfContextMenu { [shelf_ remove:self]; } +- (IBAction)handleButtonClick:(id)sender { + if ([cell_ isButtonPartPressed]) { + DownloadItem* download = bridge_->download_model()->download(); + if (download->state() == DownloadItem::IN_PROGRESS) { + download->set_open_when_complete(!download->open_when_complete()); + } else if (download->state() == DownloadItem::COMPLETE) { + download_util::OpenDownload(download); + } + } else { + // TODO(thakis): Align menu nicely with left view edge + [NSMenu popUpContextMenu:currentMenu_ + withEvent:[NSApp currentEvent] + forView:progressView_]; + } +} + // Sets the enabled and checked state of a particular menu item for this // download. We translate the NSMenuItem selection to menu selections understood // by the non platform specific download context menu. diff --git a/chrome/browser/cocoa/download_shelf_controller.mm b/chrome/browser/cocoa/download_shelf_controller.mm index 896b72e..ccb672d 100644 --- a/chrome/browser/cocoa/download_shelf_controller.mm +++ b/chrome/browser/cocoa/download_shelf_controller.mm @@ -17,20 +17,21 @@ namespace { -// TODO(thakis): These are all temporary until there's a download item view. - // Border padding of a download item. -const int kDownloadItemBorderPadding = 4; +const int kDownloadItemBorderPadding = 3; -// Width of a download item. +// Width of a download item, must match width in DownloadItem.xib. const int kDownloadItemWidth = 200; -// Height of a download item. -const int kDownloadItemHeight = 32; +// Height of a download item, must match height in DownloadItem.xib. +const int kDownloadItemHeight = 34; // Horizontal padding between two download items. const int kDownloadItemPadding = 10; +// Duration for the open-new-leftmost-item animation, in seconds. +const NSTimeInterval kDownloadItemOpenDuration = 0.8; + } // namespace @interface DownloadShelfController(Private) @@ -69,7 +70,7 @@ const int kDownloadItemPadding = 10; [paragraphStyle.get() setAlignment:NSRightTextAlignment]; NSDictionary* linkAttributes = [NSDictionary dictionaryWithObjectsAndKeys: - self, NSLinkAttributeName, + @"", NSLinkAttributeName, [NSCursor pointingHandCursor], NSCursorAttributeName, paragraphStyle.get(), NSParagraphStyleAttributeName, nil]; @@ -191,17 +192,21 @@ const int kDownloadItemPadding = 10; } - (void)addDownloadItem:(BaseDownloadItemModel*)model { - // TODO(thakis): we need to delete these at some point. There's no explicit - // mass delete on windows, figure out where they do it. - // TODO(thakis): RTL support? // (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) - int startX = kDownloadItemBorderPadding + - (kDownloadItemWidth + kDownloadItemPadding) * - [downloadItemControllers_ count]; + // Shift all existing items to the right + 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; + + // Start at width 0... NSRect position = NSMakeRect(startX, kDownloadItemBorderPadding, - kDownloadItemWidth, kDownloadItemHeight); + 0, kDownloadItemHeight); scoped_nsobject<DownloadItemController> controller( [[DownloadItemController alloc] initWithFrame:position model:model @@ -209,6 +214,15 @@ const int kDownloadItemPadding = 10; [downloadItemControllers_ addObject:controller.get()]; [[self view] addSubview:[controller.get() view]]; + + // ...then animate in + NSRect frame = [[controller.get() view] frame]; + frame.size.width = kDownloadItemWidth; + + [NSAnimationContext beginGrouping]; + [[NSAnimationContext currentContext] setDuration:kDownloadItemOpenDuration]; + [[[controller.get() view] animator] setFrame:frame]; + [NSAnimationContext endGrouping]; } @end diff --git a/chrome/browser/cocoa/gradient_button_cell.h b/chrome/browser/cocoa/gradient_button_cell.h index f0039e9..61c9a4f 100644 --- a/chrome/browser/cocoa/gradient_button_cell.h +++ b/chrome/browser/cocoa/gradient_button_cell.h @@ -9,12 +9,15 @@ #include "base/scoped_nsobject.h" +@class GTMTheme; + // Base class for button cells for toolbar and bookmark bar. // // This is a button cell that handles drawing/highlighting of buttons. // The appearance is determined by setting the cell's tag (not the // view's) to one of the constants below (ButtonType). +// Set this as the cell's tag. enum { kLeftButtonType = -1, kLeftButtonWithShadowType = -2, @@ -37,6 +40,15 @@ typedef NSInteger ButtonType; // Turn off theming. Temporary work-around. - (void)setShouldTheme:(BOOL)shouldTheme; +- (void)drawBorderAndFillForTheme:(GTMTheme*)theme + controlView:(NSView*)controlView + outerPath:(NSBezierPath*)outerPath + innerPath:(NSBezierPath*)innerPath + showHighlightGradient:(BOOL)showHighlightGradient + showClickedGradient:(BOOL)showClickedGradient + active:(BOOL)active + cellFrame:(NSRect)cellFrame; + // An image to underlay beneath the existing image; not themed. May be nil. - (NSImage*)underlayImage; - (void)setUnderlayImage:(NSImage*)image; diff --git a/chrome/browser/cocoa/gradient_button_cell.mm b/chrome/browser/cocoa/gradient_button_cell.mm index dbc80af..a0b31522 100644 --- a/chrome/browser/cocoa/gradient_button_cell.mm +++ b/chrome/browser/cocoa/gradient_button_cell.mm @@ -89,6 +89,76 @@ } } +- (void)drawBorderAndFillForTheme:(GTMTheme*)theme + controlView:(NSView*)controlView + outerPath:(NSBezierPath*)outerPath + innerPath:(NSBezierPath*)innerPath + showHighlightGradient:(BOOL)showHighlightGradient + showClickedGradient:(BOOL)showClickedGradient + active:(BOOL)active + cellFrame:(NSRect)cellFrame { + [[NSColor colorWithCalibratedWhite:1.0 alpha:0.25] set]; + [outerPath stroke]; + + NSImage* backgroundImage = + [theme backgroundImageForStyle:GTMThemeStyleToolBarButton state:YES]; + + if (backgroundImage) { + NSColor* patternColor = [NSColor colorWithPatternImage:backgroundImage]; + [patternColor set]; + // Set the phase to match window. + NSRect trueRect = [controlView convertRectToBase:cellFrame]; + [[NSGraphicsContext currentContext] + setPatternPhase:NSMakePoint(NSMinX(trueRect), NSMaxY(trueRect))]; + [innerPath fill]; + } else { + if (showClickedGradient) { + NSGradient* gradient = + [theme gradientForStyle:GTMThemeStyleToolBarButtonPressed + state:active]; + [gradient drawInBezierPath:innerPath angle:90.0]; + } + } + + if (!showClickedGradient && showHighlightGradient) { + [NSGraphicsContext saveGraphicsState]; + [innerPath addClip]; + + // Draw the inner glow. + [innerPath setLineWidth:2]; + [[NSColor colorWithCalibratedWhite:1.0 alpha:0.9] setStroke]; + [innerPath stroke]; + + [[NSColor colorWithCalibratedWhite:1.0 alpha:0.9] setStroke]; + [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2] setFill]; + + // Draw the top inner highlight. + NSAffineTransform* highlightTransform = [NSAffineTransform transform]; + [highlightTransform translateXBy:1 yBy:1]; + scoped_nsobject<NSBezierPath> highlightPath([innerPath copy]); + [highlightPath transformUsingAffineTransform:highlightTransform]; + + [highlightPath stroke]; + + NSColor* startColor = [NSColor colorWithCalibratedWhite:1.0 alpha:0.666]; + NSColor* endColor = [NSColor colorWithCalibratedWhite:1.0 alpha:0.333]; + scoped_nsobject<NSBezierPath> gradient([[NSGradient alloc] + initWithColorsAndLocations:startColor, 0.33, endColor, 1.0, nil]); + + [gradient drawInBezierPath:innerPath angle:90.0]; + + [NSGraphicsContext restoreGraphicsState]; + } + + NSColor* stroke = [theme strokeColorForStyle:GTMThemeStyleToolBarButton + state:active]; + [stroke setStroke]; + + [innerPath setLineWidth:1]; + [innerPath stroke]; +} + + - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { // Constants from Cole. Will kConstant them once the feedback loop // is complete. @@ -129,65 +199,15 @@ if (([self isBordered] && ![self showsBorderOnlyWhileMouseInside]) || pressed || [self isMouseInside]) { - [[NSColor colorWithCalibratedWhite:1.0 alpha:0.25] set]; - [outerPath stroke]; - - NSImage* backgroundImage = - [theme backgroundImageForStyle:GTMThemeStyleToolBarButton state:YES]; - - if (backgroundImage) { - NSColor* patternColor = [NSColor colorWithPatternImage:backgroundImage]; - [patternColor set]; - // Set the phase to match window. - NSRect trueRect = [controlView convertRectToBase:cellFrame]; - [[NSGraphicsContext currentContext] - setPatternPhase:NSMakePoint(NSMinX(trueRect), NSMaxY(trueRect))]; - [innerPath fill]; - } else { - if (pressed) { - NSGradient* gradient = - [theme gradientForStyle:GTMThemeStyleToolBarButtonPressed - state:active]; - [gradient drawInBezierPath:innerPath angle:90.0]; - } - } - - if (!pressed) { - [NSGraphicsContext saveGraphicsState]; - [innerPath addClip]; - - // Draw the inner glow. - [innerPath setLineWidth:2]; - [[NSColor colorWithCalibratedWhite:1.0 alpha:0.9] setStroke]; - [innerPath stroke]; - - [[NSColor colorWithCalibratedWhite:1.0 alpha:0.9] setStroke]; - [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2] setFill]; - - // Draw the top inner highlight. - NSAffineTransform* highlightTransform = [NSAffineTransform transform]; - [highlightTransform translateXBy:1 yBy:1]; - scoped_nsobject<NSBezierPath> highlightPath([innerPath copy]); - [highlightPath transformUsingAffineTransform:highlightTransform]; - - [highlightPath stroke]; - NSColor* startColor = [NSColor colorWithCalibratedWhite:1.0 alpha:0.666]; - NSColor* endColor = [NSColor colorWithCalibratedWhite:1.0 alpha:0.333]; - scoped_nsobject<NSBezierPath> gradient([[NSGradient alloc] - initWithColorsAndLocations:startColor, 0.33, endColor, 1.0, nil]); - - [gradient drawInBezierPath:innerPath angle:90.0]; - - [NSGraphicsContext restoreGraphicsState]; - } - - NSColor* stroke = [theme strokeColorForStyle:GTMThemeStyleToolBarButton - state:active]; - [stroke setStroke]; - - [innerPath setLineWidth:1]; - [innerPath stroke]; + [self drawBorderAndFillForTheme:theme + controlView:controlView + outerPath:outerPath + innerPath:innerPath + showHighlightGradient:YES + showClickedGradient:pressed + active:active + cellFrame:cellFrame]; } // If this is the left side of a segmented button, draw a slight shadow. diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index fd5ff00..8c20b27 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -776,6 +776,8 @@ 'browser/cocoa/command_observer_bridge.mm', 'browser/cocoa/custom_home_pages_model.h', 'browser/cocoa/custom_home_pages_model.mm', + 'browser/cocoa/download_item_cell.h', + 'browser/cocoa/download_item_cell.mm', 'browser/cocoa/download_item_controller.h', 'browser/cocoa/download_item_controller.mm', 'browser/cocoa/download_item_mac.h', |