diff options
-rw-r--r-- | chrome/app/nibs/InfoBar.xib | 420 | ||||
-rw-r--r-- | chrome/browser/cocoa/infobar_container_controller.h | 30 | ||||
-rw-r--r-- | chrome/browser/cocoa/infobar_container_controller.mm | 55 | ||||
-rw-r--r-- | chrome/browser/cocoa/infobar_container_controller_unittest.mm | 18 | ||||
-rw-r--r-- | chrome/browser/cocoa/infobar_controller.h | 20 | ||||
-rw-r--r-- | chrome/browser/cocoa/infobar_controller.mm | 99 | ||||
-rw-r--r-- | chrome/browser/cocoa/infobar_controller_unittest.mm | 44 | ||||
-rw-r--r-- | chrome/browser/cocoa/view_resizer.h | 2 |
8 files changed, 458 insertions, 230 deletions
diff --git a/chrome/app/nibs/InfoBar.xib b/chrome/app/nibs/InfoBar.xib index 4f5cb15..8c61ab6 100644 --- a/chrome/app/nibs/InfoBar.xib +++ b/chrome/app/nibs/InfoBar.xib @@ -2,13 +2,13 @@ <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03"> <data> <int key="IBDocument.SystemTarget">1050</int> - <string key="IBDocument.SystemVersion">9L30</string> + <string key="IBDocument.SystemVersion">9L31a</string> <string key="IBDocument.InterfaceBuilderVersion">677</string> <string key="IBDocument.AppKitVersion">949.54</string> <string key="IBDocument.HIToolboxVersion">353.00</string> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> - <integer value="1"/> + <integer value="30"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -34,153 +34,163 @@ <object class="NSCustomObject" id="1004"> <string key="NSClassName">NSApplication</string> </object> - <object class="NSCustomView" id="1005"> + <object class="NSCustomView" id="374699732"> <reference key="NSNextResponder"/> <int key="NSvFlags">290</int> <object class="NSMutableArray" key="NSSubviews"> <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSTextField" id="293244832"> - <reference key="NSNextResponder" ref="1005"/> - <int key="NSvFlags">258</int> - <string key="NSFrame">{{36, 7}, {205, 17}}</string> - <reference key="NSSuperview" ref="1005"/> - <bool key="NSEnabled">YES</bool> - <object class="NSTextFieldCell" key="NSCell" id="963811960"> - <int key="NSCellFlags">67239488</int> - <int key="NSCellFlags2">272631808</int> - <string key="NSContents">InfoBar text</string> - <object class="NSFont" key="NSSupport" id="3997082"> - <string key="NSName">LucidaGrande</string> - <double key="NSSize">1.300000e+01</double> - <int key="NSfFlags">1044</int> - </object> - <reference key="NSControlView" ref="293244832"/> - <object class="NSColor" key="NSBackgroundColor"> - <int key="NSColorSpace">6</int> - <string key="NSCatalogName">System</string> - <string key="NSColorName">controlColor</string> - <object class="NSColor" key="NSColor"> - <int key="NSColorSpace">3</int> - <bytes key="NSWhite">MC42NjY2NjY2OQA</bytes> + <object class="NSCustomView" id="1005"> + <reference key="NSNextResponder" ref="374699732"/> + <int key="NSvFlags">290</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSTextField" id="293244832"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">258</int> + <string key="NSFrame">{{36, 7}, {205, 17}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSTextFieldCell" key="NSCell" id="963811960"> + <int key="NSCellFlags">67239488</int> + <int key="NSCellFlags2">272631808</int> + <string key="NSContents">InfoBar text</string> + <object class="NSFont" key="NSSupport" id="3997082"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">1.300000e+01</double> + <int key="NSfFlags">1044</int> + </object> + <reference key="NSControlView" ref="293244832"/> + <object class="NSColor" key="NSBackgroundColor"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MC42NjY2NjY2OQA</bytes> + </object> + </object> + <object class="NSColor" key="NSTextColor"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlTextColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MAA</bytes> + </object> + </object> </object> </object> - <object class="NSColor" key="NSTextColor"> - <int key="NSColorSpace">6</int> - <string key="NSCatalogName">System</string> - <string key="NSColorName">controlTextColor</string> - <object class="NSColor" key="NSColor"> - <int key="NSColorSpace">3</int> - <bytes key="NSWhite">MAA</bytes> + <object class="NSImageView" id="724203299"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">300</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">{{3, 1}, {29, 29}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSImageCell" key="NSCell" id="905047690"> + <int key="NSCellFlags">130560</int> + <int key="NSCellFlags2">33554432</int> + <int key="NSAlign">0</int> + <int key="NSScale">3</int> + <int key="NSStyle">0</int> + <bool key="NSAnimates">NO</bool> + </object> + <bool key="NSEditable">YES</bool> </object> - </object> - </object> - <object class="NSImageView" id="724203299"> - <reference key="NSNextResponder" ref="1005"/> - <int key="NSvFlags">300</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">{{3, 1}, {29, 29}}</string> - <reference key="NSSuperview" ref="1005"/> - <bool key="NSEnabled">YES</bool> - <object class="NSImageCell" key="NSCell" id="905047690"> - <int key="NSCellFlags">130560</int> - <int key="NSCellFlags2">33554432</int> - <int key="NSAlign">0</int> - <int key="NSScale">3</int> - <int key="NSStyle">0</int> - <bool key="NSAnimates">NO</bool> - </object> - <bool key="NSEditable">YES</bool> - </object> - <object class="NSButton" id="861420161"> - <reference key="NSNextResponder" ref="1005"/> - <int key="NSvFlags">297</int> - <string key="NSFrame">{{454, 8}, {16, 16}}</string> - <reference key="NSSuperview" ref="1005"/> - <bool key="NSEnabled">YES</bool> - <object class="NSButtonCell" key="NSCell" id="1030694164"> - <int key="NSCellFlags">67239424</int> - <int key="NSCellFlags2">134217728</int> - <string key="NSContents"/> - <reference key="NSSupport" ref="3997082"/> - <reference key="NSControlView" ref="861420161"/> - <int key="NSButtonFlags">139215103</int> - <int key="NSButtonFlags2">6</int> - <object class="NSCustomResource" key="NSNormalImage"> - <string key="NSClassName">NSImage</string> - <string key="NSResourceName">close_bar</string> + <object class="NSButton" id="861420161"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">297</int> + <string key="NSFrame">{{454, 8}, {16, 16}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSButtonCell" key="NSCell" id="1030694164"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">134217728</int> + <string key="NSContents"/> + <reference key="NSSupport" ref="3997082"/> + <reference key="NSControlView" ref="861420161"/> + <int key="NSButtonFlags">139215103</int> + <int key="NSButtonFlags2">6</int> + <object class="NSCustomResource" key="NSNormalImage"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">close_bar</string> + </object> + <object class="NSCustomResource" key="NSAlternateImage"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">close_bar_p</string> + </object> + <string key="NSAlternateContents"/> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">200</int> + <int key="NSPeriodicInterval">25</int> + </object> </object> - <object class="NSCustomResource" key="NSAlternateImage"> - <string key="NSClassName">NSImage</string> - <string key="NSResourceName">close_bar_p</string> + <object class="NSButton" id="488415728"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">265</int> + <string key="NSFrame">{{350, 6}, {96, 19}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSButtonCell" key="NSCell" id="24619168"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">134217728</int> + <string key="NSContents">CancelBtn</string> + <object class="NSFont" key="NSSupport" id="751943183"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">1.100000e+01</double> + <int key="NSfFlags">16</int> + </object> + <reference key="NSControlView" ref="488415728"/> + <int key="NSButtonFlags">-2038284033</int> + <int key="NSButtonFlags2">164</int> + <reference key="NSAlternateImage" ref="751943183"/> + <string key="NSAlternateContents"/> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">200</int> + <int key="NSPeriodicInterval">25</int> + </object> </object> - <string key="NSAlternateContents"/> - <string key="NSKeyEquivalent"/> - <int key="NSPeriodicDelay">200</int> - <int key="NSPeriodicInterval">25</int> - </object> - </object> - <object class="NSButton" id="488415728"> - <reference key="NSNextResponder" ref="1005"/> - <int key="NSvFlags">265</int> - <string key="NSFrame">{{350, 6}, {96, 19}}</string> - <reference key="NSSuperview" ref="1005"/> - <bool key="NSEnabled">YES</bool> - <object class="NSButtonCell" key="NSCell" id="24619168"> - <int key="NSCellFlags">67239424</int> - <int key="NSCellFlags2">134217728</int> - <string key="NSContents">CancelBtn</string> - <object class="NSFont" key="NSSupport" id="751943183"> - <string key="NSName">LucidaGrande</string> - <double key="NSSize">1.100000e+01</double> - <int key="NSfFlags">16</int> + <object class="NSButton" id="11488953"> + <reference key="NSNextResponder" ref="1005"/> + <int key="NSvFlags">265</int> + <string key="NSFrame">{{246, 6}, {96, 19}}</string> + <reference key="NSSuperview" ref="1005"/> + <bool key="NSEnabled">YES</bool> + <object class="NSButtonCell" key="NSCell" id="900516520"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">134217728</int> + <string key="NSContents">OKBtn</string> + <reference key="NSSupport" ref="751943183"/> + <reference key="NSControlView" ref="11488953"/> + <int key="NSButtonFlags">-2038284033</int> + <int key="NSButtonFlags2">164</int> + <reference key="NSAlternateImage" ref="751943183"/> + <string key="NSAlternateContents"/> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">200</int> + <int key="NSPeriodicInterval">25</int> + </object> </object> - <reference key="NSControlView" ref="488415728"/> - <int key="NSButtonFlags">-2038284033</int> - <int key="NSButtonFlags2">164</int> - <reference key="NSAlternateImage" ref="751943183"/> - <string key="NSAlternateContents"/> - <string key="NSKeyEquivalent"/> - <int key="NSPeriodicDelay">200</int> - <int key="NSPeriodicInterval">25</int> - </object> - </object> - <object class="NSButton" id="11488953"> - <reference key="NSNextResponder" ref="1005"/> - <int key="NSvFlags">265</int> - <string key="NSFrame">{{246, 6}, {96, 19}}</string> - <reference key="NSSuperview" ref="1005"/> - <bool key="NSEnabled">YES</bool> - <object class="NSButtonCell" key="NSCell" id="900516520"> - <int key="NSCellFlags">67239424</int> - <int key="NSCellFlags2">134217728</int> - <string key="NSContents">OKBtn</string> - <reference key="NSSupport" ref="751943183"/> - <reference key="NSControlView" ref="11488953"/> - <int key="NSButtonFlags">-2038284033</int> - <int key="NSButtonFlags2">164</int> - <reference key="NSAlternateImage" ref="751943183"/> - <string key="NSAlternateContents"/> - <string key="NSKeyEquivalent"/> - <int key="NSPeriodicDelay">200</int> - <int key="NSPeriodicInterval">25</int> </object> + <string key="NSFrameSize">{480, 31}</string> + <reference key="NSSuperview" ref="374699732"/> + <string key="NSClassName">InfoBarGradientView</string> </object> </object> <string key="NSFrameSize">{480, 31}</string> <reference key="NSSuperview"/> - <string key="NSClassName">InfoBarGradientView</string> + <string key="NSClassName">AnimatableView</string> </object> </object> <object class="IBObjectContainer" key="IBDocument.Objects"> @@ -203,14 +213,6 @@ <int key="connectionID">11</int> </object> <object class="IBConnectionRecord"> - <object class="IBOutletConnection" key="connection"> - <string key="label">view</string> - <reference key="source" ref="1001"/> - <reference key="destination" ref="1005"/> - </object> - <int key="connectionID">12</int> - </object> - <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">dismiss:</string> <reference key="source" ref="1001"/> @@ -258,6 +260,30 @@ </object> <int key="connectionID">29</int> </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">view</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="374699732"/> + </object> + <int key="connectionID">31</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">infoBarView_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="1005"/> + </object> + <int key="connectionID">32</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">delegate_</string> + <reference key="source" ref="374699732"/> + <reference key="destination" ref="1001"/> + </object> + <int key="connectionID">33</int> + </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> @@ -289,47 +315,46 @@ <string key="objectName">Application</string> </object> <object class="IBObjectRecord"> + <int key="objectID">30</int> + <reference key="object" ref="374699732"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="1005"/> + </object> + <reference key="parent" ref="1002"/> + </object> + <object class="IBObjectRecord"> <int key="objectID">1</int> <reference key="object" ref="1005"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="293244832"/> - <reference ref="724203299"/> - <reference ref="488415728"/> - <reference ref="11488953"/> <reference ref="861420161"/> + <reference ref="11488953"/> + <reference ref="488415728"/> + <reference ref="724203299"/> + <reference ref="293244832"/> </object> - <reference key="parent" ref="1002"/> + <reference key="parent" ref="374699732"/> </object> <object class="IBObjectRecord"> - <int key="objectID">2</int> - <reference key="object" ref="293244832"/> + <int key="objectID">15</int> + <reference key="object" ref="861420161"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="963811960"/> + <reference ref="1030694164"/> </object> <reference key="parent" ref="1005"/> </object> <object class="IBObjectRecord"> - <int key="objectID">3</int> - <reference key="object" ref="963811960"/> - <reference key="parent" ref="293244832"/> - </object> - <object class="IBObjectRecord"> - <int key="objectID">4</int> - <reference key="object" ref="724203299"/> + <int key="objectID">22</int> + <reference key="object" ref="11488953"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="905047690"/> + <reference ref="900516520"/> </object> <reference key="parent" ref="1005"/> </object> <object class="IBObjectRecord"> - <int key="objectID">5</int> - <reference key="object" ref="905047690"/> - <reference key="parent" ref="724203299"/> - </object> - <object class="IBObjectRecord"> <int key="objectID">20</int> <reference key="object" ref="488415728"/> <object class="NSMutableArray" key="children"> @@ -339,34 +364,44 @@ <reference key="parent" ref="1005"/> </object> <object class="IBObjectRecord"> - <int key="objectID">21</int> - <reference key="object" ref="24619168"/> - <reference key="parent" ref="488415728"/> + <int key="objectID">4</int> + <reference key="object" ref="724203299"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="905047690"/> + </object> + <reference key="parent" ref="1005"/> </object> <object class="IBObjectRecord"> - <int key="objectID">22</int> - <reference key="object" ref="11488953"/> + <int key="objectID">2</int> + <reference key="object" ref="293244832"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="900516520"/> + <reference ref="963811960"/> </object> <reference key="parent" ref="1005"/> </object> <object class="IBObjectRecord"> + <int key="objectID">3</int> + <reference key="object" ref="963811960"/> + <reference key="parent" ref="293244832"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">5</int> + <reference key="object" ref="905047690"/> + <reference key="parent" ref="724203299"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">21</int> + <reference key="object" ref="24619168"/> + <reference key="parent" ref="488415728"/> + </object> + <object class="IBObjectRecord"> <int key="objectID">23</int> <reference key="object" ref="900516520"/> <reference key="parent" ref="11488953"/> </object> <object class="IBObjectRecord"> - <int key="objectID">15</int> - <reference key="object" ref="861420161"/> - <object class="NSMutableArray" key="children"> - <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="1030694164"/> - </object> - <reference key="parent" ref="1005"/> - </object> - <object class="IBObjectRecord"> <int key="objectID">16</int> <reference key="object" ref="1030694164"/> <reference key="parent" ref="861420161"/> @@ -393,6 +428,8 @@ <string>22.IBPluginDependency</string> <string>23.IBPluginDependency</string> <string>3.IBPluginDependency</string> + <string>30.IBEditorWindowLastContentRect</string> + <string>30.IBPluginDependency</string> <string>4.IBPluginDependency</string> <string>5.IBPluginDependency</string> </object> @@ -414,6 +451,8 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{0, 1503}, {480, 31}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> </object> @@ -438,12 +477,33 @@ </object> </object> <nil key="sourceID"/> - <int key="maxID">29</int> + <int key="maxID">33</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBPartialClassDescription"> + <string key="className">AnimatableView</string> + <string key="superclassName">NSView</string> + <object class="NSMutableDictionary" key="outlets"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>delegate_</string> + <string>resizeDelegate_</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>id</string> + <string>id</string> + </object> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/animatable_view.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> <string key="className">InfoBarController</string> <string key="superclassName">NSViewController</string> <object class="NSMutableDictionary" key="actions"> @@ -466,14 +526,18 @@ <object class="NSMutableArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>cancelButton_</string> + <string>containerController_</string> <string>image_</string> + <string>infoBarView_</string> <string>label_</string> <string>okButton_</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>NSButton</string> + <string>id</string> <string>NSImageView</string> + <string>NSView</string> <string>NSTextField</string> <string>NSButton</string> </object> diff --git a/chrome/browser/cocoa/infobar_container_controller.h b/chrome/browser/cocoa/infobar_container_controller.h index 22077ac..81e82f4 100644 --- a/chrome/browser/cocoa/infobar_container_controller.h +++ b/chrome/browser/cocoa/infobar_container_controller.h @@ -9,18 +9,27 @@ #import "chrome/browser/cocoa/view_resizer.h" #include "chrome/common/notification_registrar.h" +@class InfoBarController; class InfoBarDelegate; class InfoBarNotificationObserver; class TabContents; class TabStripModel; class TabStripModelObserverBridge; +// Protocol for basic container methods, as needed by an InfoBarController. +// This protocol exists to make mocking easier in unittests. +@protocol InfoBarContainer +- (void)removeDelegate:(InfoBarDelegate*)delegate; +- (void)removeController:(InfoBarController*)controller; +@end + // Controller for the infobar container view, which is the superview // of all the infobar views. This class owns zero or more // InfoBarControllers, which manage the infobar views. This class // also receives tab strip model notifications and handles // adding/removing infobars when needed. -@interface InfoBarContainerController : NSViewController { +@interface InfoBarContainerController : NSViewController <ViewResizer, + InfoBarContainer> { @private // Needed to send resize messages when infobars are added or removed. id<ViewResizer> resizeDelegate_; // weak @@ -51,21 +60,26 @@ class TabStripModelObserverBridge; // infobar was closed. - (void)removeDelegate:(InfoBarDelegate*)delegate; +// Removes |controller| from the list of controllers in this container and +// removes its view from the view hierarchy. This method is safe to call while +// |controller| is still on the call stack. +- (void)removeController:(InfoBarController*)controller; + @end @interface InfoBarContainerController (ForTheObserverAndTesting) -// Adds an infobar view for the given delegate. Callers must call -// positionInfoBarsAndRedraw after calling this method. -- (void)addInfoBar:(InfoBarDelegate*)delegate; +// Adds an infobar view for the given delegate. +- (void)addInfoBar:(InfoBarDelegate*)delegate animate:(BOOL)animate; -// Removes all the infobar views for a given delegate. Callers must -// call positionInfoBarsAndRedraw after calling this method. -- (void)removeInfoBarsForDelegate:(InfoBarDelegate*)delegate; +// Closes all the infobar views for a given delegate, either immediately or by +// starting a close animation. +- (void)closeInfoBarsForDelegate:(InfoBarDelegate*)delegate + animate:(BOOL)animate; // Replaces all info bars for the delegate with a new info bar. -// This simply calls removeInfoBarsForDelegate: and then addInfoBar:. +// This simply calls closeInfoBarsForDelegate: and then addInfoBar:. - (void)replaceInfoBarsForDelegate:(InfoBarDelegate*)old_delegate with:(InfoBarDelegate*)new_delegate; diff --git a/chrome/browser/cocoa/infobar_container_controller.mm b/chrome/browser/cocoa/infobar_container_controller.mm index 832a014..b09c580 100644 --- a/chrome/browser/cocoa/infobar_container_controller.mm +++ b/chrome/browser/cocoa/infobar_container_controller.mm @@ -4,6 +4,7 @@ #include "base/logging.h" #include "base/mac_util.h" +#import "chrome/browser/cocoa/animatable_view.h" #include "chrome/browser/cocoa/infobar.h" #import "chrome/browser/cocoa/infobar_container_controller.h" #import "chrome/browser/cocoa/infobar_controller.h" @@ -27,11 +28,13 @@ class InfoBarNotificationObserver : public NotificationObserver { const NotificationDetails& details) { switch (type.value) { case NotificationType::TAB_CONTENTS_INFOBAR_ADDED: - [controller_ addInfoBar:Details<InfoBarDelegate>(details).ptr()]; + [controller_ addInfoBar:Details<InfoBarDelegate>(details).ptr() + animate:YES]; break; case NotificationType::TAB_CONTENTS_INFOBAR_REMOVED: [controller_ - removeInfoBarsForDelegate:Details<InfoBarDelegate>(details).ptr()]; + closeInfoBarsForDelegate:Details<InfoBarDelegate>(details).ptr() + animate:YES]; break; case NotificationType::TAB_CONTENTS_INFOBAR_REPLACED: { typedef std::pair<InfoBarDelegate*, InfoBarDelegate*> @@ -97,6 +100,16 @@ class InfoBarNotificationObserver : public NotificationObserver { currentTabContents_->RemoveInfoBar(delegate); } +- (void)removeController:(InfoBarController*)controller { + // This code can be executed while InfoBarController is still on the stack, so + // we retain and autorelease the controller to prevent it from being + // dealloc'ed too early. + [[controller retain] autorelease]; + [[controller view] removeFromSuperview]; + [infobarControllers_ removeObject:controller]; + [self positionInfoBarsAndRedraw]; +} + // TabStripModelObserverBridge notifications - (void)selectTabWithContents:(TabContents*)newContents previousContents:(TabContents*)oldContents @@ -110,6 +123,13 @@ class InfoBarNotificationObserver : public NotificationObserver { [self changeTabContents:NULL]; } +- (void)resizeView:(NSView*)view newHeight:(float)height { + NSRect frame = [view frame]; + frame.size.height = height; + [view setFrame:frame]; + [self positionInfoBarsAndRedraw]; +} + @end @implementation InfoBarContainerController (PrivateMethods) @@ -131,7 +151,8 @@ class InfoBarNotificationObserver : public NotificationObserver { currentTabContents_ = contents; if (currentTabContents_) { for (int i = 0; i < currentTabContents_->infobar_delegate_count(); ++i) { - [self addInfoBar:currentTabContents_->GetInfoBarDelegateAt(i)]; + [self addInfoBar:currentTabContents_->GetInfoBarDelegateAt(i) + animate:NO]; } Source<TabContents> source(currentTabContents_); @@ -146,37 +167,42 @@ class InfoBarNotificationObserver : public NotificationObserver { [self positionInfoBarsAndRedraw]; } -- (void)addInfoBar:(InfoBarDelegate*)delegate { +- (void)addInfoBar:(InfoBarDelegate*)delegate animate:(BOOL)animate { scoped_ptr<InfoBar> infobar(delegate->CreateInfoBar()); InfoBarController* controller = infobar->controller(); [controller setContainerController:self]; + [[controller animatableView] setResizeDelegate:self]; [[self view] addSubview:[controller view]]; [infobarControllers_ addObject:[controller autorelease]]; + + if (animate) + [controller animateOpen]; + else + [controller open]; } -- (void)removeInfoBarsForDelegate:(InfoBarDelegate*)delegate { +- (void)closeInfoBarsForDelegate:(InfoBarDelegate*)delegate + animate:(BOOL)animate { for (InfoBarController* controller in [NSArray arrayWithArray:infobarControllers_.get()]) { if ([controller delegate] == delegate) { - // This code can be executed while -[InfoBarController closeInfoBar] is - // still on the stack, so we retain and autorelease the controller to - // prevent it from being dealloc'ed too early. - [[controller retain] autorelease]; - [[controller view] removeFromSuperview]; - [infobarControllers_ removeObject:controller]; + if (animate) + [controller animateClosed]; + else + [controller close]; } } } - (void)replaceInfoBarsForDelegate:(InfoBarDelegate*)old_delegate with:(InfoBarDelegate*)new_delegate { - // TODO(rohitrao): This should avoid animation when we add it. - [self removeInfoBarsForDelegate:old_delegate]; - [self addInfoBar:new_delegate]; + [self closeInfoBarsForDelegate:old_delegate animate:NO]; + [self addInfoBar:new_delegate animate:NO]; } - (void)removeAllInfoBars { for (InfoBarController* controller in infobarControllers_.get()) { + [[controller animatableView] stopAnimation]; [[controller view] removeFromSuperview]; } [infobarControllers_ removeAllObjects]; @@ -198,7 +224,6 @@ class InfoBarNotificationObserver : public NotificationObserver { frame.size.width = NSWidth(containerBounds); frame.origin.y = minY; minY += frame.size.height; - // TODO(rohitrao, jrg): Replace with an animator. [view setFrame:frame]; } diff --git a/chrome/browser/cocoa/infobar_container_controller_unittest.mm b/chrome/browser/cocoa/infobar_container_controller_unittest.mm index 274ebec..f5a45b2 100644 --- a/chrome/browser/cocoa/infobar_container_controller_unittest.mm +++ b/chrome/browser/cocoa/infobar_container_controller_unittest.mm @@ -63,23 +63,23 @@ TEST_F(InfoBarContainerControllerTest, AddAndRemoveInfoBars) { MockLinkInfoBarDelegate linkDelegate; MockConfirmInfoBarDelegate confirmDelegate; - [controller_ addInfoBar:&alertDelegate]; + [controller_ addInfoBar:&alertDelegate animate:NO]; EXPECT_EQ(1U, [[view subviews] count]); - [controller_ addInfoBar:&linkDelegate]; + [controller_ addInfoBar:&linkDelegate animate:NO]; EXPECT_EQ(2U, [[view subviews] count]); - [controller_ addInfoBar:&confirmDelegate]; + [controller_ addInfoBar:&confirmDelegate animate:NO]; EXPECT_EQ(3U, [[view subviews] count]); // Just to mix things up, remove them in a different order. - [controller_ removeInfoBarsForDelegate:&linkDelegate]; + [controller_ closeInfoBarsForDelegate:&linkDelegate animate:NO]; EXPECT_EQ(2U, [[view subviews] count]); - [controller_ removeInfoBarsForDelegate:&confirmDelegate]; + [controller_ closeInfoBarsForDelegate:&confirmDelegate animate:NO]; EXPECT_EQ(1U, [[view subviews] count]); - [controller_ removeInfoBarsForDelegate:&alertDelegate]; + [controller_ closeInfoBarsForDelegate:&alertDelegate animate:NO]; EXPECT_EQ(0U, [[view subviews] count]); } @@ -92,9 +92,9 @@ TEST_F(InfoBarContainerControllerTest, RemoveAllInfoBars) { MockLinkInfoBarDelegate linkDelegate; MockConfirmInfoBarDelegate confirmDelegate; - [controller_ addInfoBar:&alertDelegate]; - [controller_ addInfoBar:&linkDelegate]; - [controller_ addInfoBar:&confirmDelegate]; + [controller_ addInfoBar:&alertDelegate animate:NO]; + [controller_ addInfoBar:&linkDelegate animate:NO]; + [controller_ addInfoBar:&confirmDelegate animate:NO]; EXPECT_EQ(3U, [[view subviews] count]); [controller_ removeAllInfoBars]; diff --git a/chrome/browser/cocoa/infobar_controller.h b/chrome/browser/cocoa/infobar_controller.h index 8015067..8bd19ed 100644 --- a/chrome/browser/cocoa/infobar_controller.h +++ b/chrome/browser/cocoa/infobar_controller.h @@ -4,7 +4,8 @@ #import <Cocoa/Cocoa.h> -@class InfoBarContainerController; +@class AnimatableView; +@protocol InfoBarContainer; class InfoBarDelegate; // A controller for an infobar in the browser window. There is one @@ -13,10 +14,12 @@ class InfoBarDelegate; // override addAdditionalControls to customize the UI. @interface InfoBarController : NSViewController { @private - InfoBarContainerController* containerController_; // weak, owns us + id<InfoBarContainer> containerController_; // weak, owns us + BOOL infoBarClosing_; @protected InfoBarDelegate* delegate_; // weak + IBOutlet NSView* infoBarView_; IBOutlet NSImageView* image_; IBOutlet NSTextField* label_; IBOutlet NSButton* okButton_; @@ -35,12 +38,23 @@ class InfoBarDelegate; // infobar without taking any action. - (IBAction)dismiss:(id)sender; +// Returns a pointer to this controller's view, cast as an AnimatableView. +- (AnimatableView*)animatableView; + +// Open or animate open the infobar. +- (void)open; +- (void)animateOpen; + +// Close or animate close the infobar. +- (void)close; +- (void)animateClosed; + // Subclasses can override this method to add additional controls to // the infobar view. This method is called by awakeFromNib. The // default implementation does nothing. - (void)addAdditionalControls; -@property(assign, nonatomic) InfoBarContainerController* containerController; +@property(assign, nonatomic) id<InfoBarContainer> containerController; @property(readonly) InfoBarDelegate* delegate; @end diff --git a/chrome/browser/cocoa/infobar_controller.mm b/chrome/browser/cocoa/infobar_controller.mm index e8b1999..2f053b8b4 100644 --- a/chrome/browser/cocoa/infobar_controller.mm +++ b/chrome/browser/cocoa/infobar_controller.mm @@ -7,6 +7,7 @@ #include "base/logging.h" // for NOTREACHED() #include "base/mac_util.h" #include "base/sys_string_conversions.h" +#import "chrome/browser/cocoa/animatable_view.h" #include "chrome/browser/cocoa/event_utils.h" #include "chrome/browser/cocoa/infobar.h" #import "chrome/browser/cocoa/infobar_container_controller.h" @@ -16,14 +17,22 @@ #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" #include "webkit/glue/window_open_disposition.h" +namespace { +// Durations set to match the default SlideAnimation duration. +const float kAnimateOpenDuration = 0.12; +const float kAnimateCloseDuration = 0.12; +} @interface InfoBarController (PrivateMethods) -// Closes the infobar by calling RemoveDelegate on the container. -// This will remove the infobar from its associated TabContents as -// well as trigger the deletion of this InfoBarController. Once the -// delegate is removed from the container, it is no longer needed, so -// we ask it to delete itself. -- (void)closeInfoBar; +// Asks the container controller to remove the infobar for this delegate. This +// call will trigger a notification that starts the infobar animating closed. +- (void)removeInfoBar; + +// Performs final cleanup after an animation is finished or stopped, including +// notifying the InfoBarDelegate that the infobar was closed and removing the +// infobar from its container, if necessary. +- (void)cleanUpAfterAnimation:(BOOL)finished; + // Removes the ok and cancel buttons, and resizes the textfield to use the // space. - (void)removeButtons; @@ -76,7 +85,44 @@ // Called when someone clicks on the close button. - (void)dismiss:(id)sender { - [self closeInfoBar]; + [self removeInfoBar]; +} + +- (AnimatableView*)animatableView { + return static_cast<AnimatableView*>([self view]); +} + +- (void)open { + // Simply reset the frame size to its opened size, forcing a relayout. + CGFloat finalHeight = [[self view] frame].size.height; + [[self animatableView] setHeight:finalHeight]; +} + +- (void)animateOpen { + // Force the frame size to be 0 and then start an animation. + NSRect frame = [[self view] frame]; + CGFloat finalHeight = frame.size.height; + frame.size.height = 0; + [[self view] setFrame:frame]; + [[self animatableView] animateToNewHeight:finalHeight + duration:kAnimateOpenDuration]; +} + +- (void)close { + infoBarClosing_ = YES; + [self cleanUpAfterAnimation:YES]; +} + +- (void)animateClosed { + // Start animating closed. We will receive a notification when the animation + // is done, at which point we can remove our view from the hierarchy and + // notify the delegate that the infobar was closed. + [[self animatableView] animateToNewHeight:0 duration:kAnimateCloseDuration]; + + // The above call may trigger an animationDidStop: notification for any + // currently-running animations, so do not set |infoBarClosing_| until after + // starting the animation. + infoBarClosing_ = YES; } - (void)addAdditionalControls { @@ -87,14 +133,9 @@ @implementation InfoBarController (PrivateMethods) -- (void)closeInfoBar { - // Calling RemoveDelegate() triggers notifications which will remove - // the infobar view from the infobar container. At that point it is - // safe to ask the delegate to delete itself. +- (void)removeInfoBar { DCHECK(delegate_); [containerController_ removeDelegate:delegate_]; - delegate_->InfoBarClosed(); - delegate_ = NULL; } - (void)removeButtons { @@ -107,6 +148,32 @@ [label_ setFrame:labelFrame]; } +- (void)cleanUpAfterAnimation:(BOOL)finished { + // Don't need to do any cleanup if the bar was animating open. + if (!infoBarClosing_) + return; + + // Notify the delegate that the infobar was closed. The delegate may delete + // itself as a result of InfoBarClosed(), so we null out its pointer. + delegate_->InfoBarClosed(); + delegate_ = NULL; + + // If the animation ran to completion, then we need to remove ourselves from + // the container. If the animation was interrupted, then the container will + // take care of removing us. + // TODO(rohitrao): UGH! This works for now, but should be cleaner. + if (finished) + [containerController_ removeController:self]; +} + +- (void)animationDidStop:(NSAnimation*)animation { + [self cleanUpAfterAnimation:NO]; +} + +- (void)animationDidEnd:(NSAnimation*)animation { + [self cleanUpAfterAnimation:YES]; +} + @end @@ -203,7 +270,7 @@ WindowOpenDisposition disposition = event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]); if (delegate_->AsLinkInfoBarDelegate()->LinkClicked(disposition)) - [self closeInfoBar]; + [self removeInfoBar]; } @end @@ -217,13 +284,13 @@ // Called when someone clicks on the "OK" button. - (IBAction)ok:(id)sender { if (delegate_->AsConfirmInfoBarDelegate()->Accept()) - [self closeInfoBar]; + [self removeInfoBar]; } // Called when someone clicks on the "Cancel" button. - (IBAction)cancel:(id)sender { if (delegate_->AsConfirmInfoBarDelegate()->Cancel()) - [self closeInfoBar]; + [self removeInfoBar]; } // Confirm infobars can have OK and/or cancel buttons, depending on diff --git a/chrome/browser/cocoa/infobar_controller_unittest.mm b/chrome/browser/cocoa/infobar_controller_unittest.mm index c6c45c9..9a55d21 100644 --- a/chrome/browser/cocoa/infobar_controller_unittest.mm +++ b/chrome/browser/cocoa/infobar_controller_unittest.mm @@ -8,6 +8,7 @@ #include "base/string_util.h" #include "base/sys_string_conversions.h" #import "chrome/browser/cocoa/cocoa_test_helper.h" +#import "chrome/browser/cocoa/infobar_container_controller.h" #import "chrome/browser/cocoa/infobar_controller.h" #include "chrome/browser/cocoa/infobar_test_helper.h" #include "chrome/browser/tab_contents/infobar_delegate.h" @@ -24,6 +25,37 @@ } @end + +// Calls to removeDelegate: normally start an animation, which removes the +// infobar completely when finished. For unittesting purposes, we create a mock +// container which calls close: immediately, rather than kicking off an +// animation. +@interface InfoBarContainerTest : NSObject <InfoBarContainer> { + InfoBarController* controller_; +} +- (id)initWithController:(InfoBarController*)controller; +- (void)removeDelegate:(InfoBarDelegate*)delegate; +- (void)removeController:(InfoBarController*)controller; +@end + +@implementation InfoBarContainerTest +- (id)initWithController:(InfoBarController*)controller { + if ((self = [super init])) { + controller_ = controller; + } + return self; +} + +- (void)removeDelegate:(InfoBarDelegate*)delegate { + [controller_ close]; +} + +- (void)removeController:(InfoBarController*)controller { + DCHECK(controller_ == controller); + controller_ = nil; +} +@end + namespace { /////////////////////////////////////////////////////////////////////////// @@ -36,12 +68,16 @@ class AlertInfoBarControllerTest : public PlatformTest { controller_.reset( [[AlertInfoBarController alloc] initWithDelegate:&delegate_]); + container_.reset( + [[InfoBarContainerTest alloc] initWithController:controller_]); + [controller_ setContainerController:container_]; [helper_.contentView() addSubview:[controller_ view]]; } protected: CocoaTestHelper helper_; MockAlertInfoBarDelegate delegate_; + scoped_nsobject<id> container_; scoped_nsobject<AlertInfoBarController> controller_; }; @@ -52,12 +88,16 @@ class LinkInfoBarControllerTest : public PlatformTest { controller_.reset( [[LinkInfoBarController alloc] initWithDelegate:&delegate_]); + container_.reset( + [[InfoBarContainerTest alloc] initWithController:controller_]); + [controller_ setContainerController:container_]; [helper_.contentView() addSubview:[controller_ view]]; } protected: CocoaTestHelper helper_; MockLinkInfoBarDelegate delegate_; + scoped_nsobject<id> container_; scoped_nsobject<LinkInfoBarController> controller_; }; @@ -68,12 +108,16 @@ class ConfirmInfoBarControllerTest : public PlatformTest { controller_.reset( [[ConfirmInfoBarController alloc] initWithDelegate:&delegate_]); + container_.reset( + [[InfoBarContainerTest alloc] initWithController:controller_]); + [controller_ setContainerController:container_]; [helper_.contentView() addSubview:[controller_ view]]; } protected: CocoaTestHelper helper_; MockConfirmInfoBarDelegate delegate_; + scoped_nsobject<id> container_; scoped_nsobject<ConfirmInfoBarController> controller_; }; diff --git a/chrome/browser/cocoa/view_resizer.h b/chrome/browser/cocoa/view_resizer.h index 199b60f..091222d 100644 --- a/chrome/browser/cocoa/view_resizer.h +++ b/chrome/browser/cocoa/view_resizer.h @@ -14,7 +14,7 @@ // than resizing it directly, it sends a message to its parent asking the parent // to perform the resize. This allows the parent to do any re-layout that may // become necessary due to the resize. -@protocol ViewResizer +@protocol ViewResizer <NSObject> - (void)resizeView:(NSView*)view newHeight:(float)height; @end |