diff options
author | mnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-22 10:42:27 +0000 |
---|---|---|
committer | mnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-22 10:42:27 +0000 |
commit | b5a7c90f4fe3c7ce6b0416459065e4319eff1c18 (patch) | |
tree | 0ec0d3516b63bd7bc848527ad673e71beb789939 | |
parent | 95ab14addfa350acfaf78f94c8436ce7564ad6ef (diff) | |
download | chromium_src-b5a7c90f4fe3c7ce6b0416459065e4319eff1c18.zip chromium_src-b5a7c90f4fe3c7ce6b0416459065e4319eff1c18.tar.gz chromium_src-b5a7c90f4fe3c7ce6b0416459065e4319eff1c18.tar.bz2 |
Managed preferences warning banner for Mac preferences dialog
Add a new view to the preferences dialog in Preferences.xib that holds the
alert image and the warning message label. Update the visibility of the warning
banner when switching preference views in PreferencesWindowController.
BUG=43423
TEST=none
Review URL: http://codereview.chromium.org/2831004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50444 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/app/nibs/Preferences.xib | 158 | ||||
-rw-r--r-- | chrome/browser/cocoa/infobar_gradient_view.h | 11 | ||||
-rw-r--r-- | chrome/browser/cocoa/infobar_gradient_view.mm | 30 | ||||
-rw-r--r-- | chrome/browser/cocoa/preferences_window_controller.h | 8 | ||||
-rw-r--r-- | chrome/browser/cocoa/preferences_window_controller.mm | 243 | ||||
-rw-r--r-- | chrome/browser/cocoa/vertical_gradient_view.h | 35 | ||||
-rw-r--r-- | chrome/browser/cocoa/vertical_gradient_view.mm | 39 | ||||
-rw-r--r-- | chrome/browser/cocoa/vertical_gradient_view_unittest.mm | 27 | ||||
-rwxr-xr-x | chrome/chrome_browser.gypi | 2 | ||||
-rwxr-xr-x | chrome/chrome_tests.gypi | 1 |
10 files changed, 466 insertions, 88 deletions
diff --git a/chrome/app/nibs/Preferences.xib b/chrome/app/nibs/Preferences.xib index 9a54bca..3b3d7ca 100644 --- a/chrome/app/nibs/Preferences.xib +++ b/chrome/app/nibs/Preferences.xib @@ -3,11 +3,12 @@ <data> <int key="IBDocument.SystemTarget">1050</int> <string key="IBDocument.SystemVersion">9L31a</string> - <string key="IBDocument.InterfaceBuilderVersion">677</string> + <string key="IBDocument.InterfaceBuilderVersion">680</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="692"/> <integer value="481"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> @@ -2386,6 +2387,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> <string key="NSFrame">{{1, 1}, {525, 402}}</string> <reference key="NSSuperview" ref="14278481"/> + <reference key="NSNextKeyView" ref="772886817"/> <reference key="NSDocView" ref="772886817"/> <object class="NSColor" key="NSBGColor"> <int key="NSColorSpace">3</int> @@ -2416,6 +2418,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> <string key="NSFrame">{{-1, 60}, {542, 404}}</string> <reference key="NSSuperview" ref="933437956"/> + <reference key="NSNextKeyView" ref="277407604"/> <int key="NSsFlags">18</int> <reference key="NSVScroller" ref="331420378"/> <reference key="NSHScroller" ref="470087648"/> @@ -2455,12 +2458,69 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string key="NSFrameSize">{540, 463}</string> <string key="NSClassName">NSView</string> </object> + <object class="NSCustomView" id="380531918"> + <reference key="NSNextResponder"/> + <int key="NSvFlags">268</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSImageView" id="846805293"> + <reference key="NSNextResponder" ref="380531918"/> + <int key="NSvFlags">256</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="NSFrameSize">{27, 27}</string> + <reference key="NSSuperview" ref="380531918"/> + <bool key="NSEnabled">YES</bool> + <object class="NSImageCell" key="NSCell" id="252500928"> + <int key="NSCellFlags">130560</int> + <int key="NSCellFlags2">33554432</int> + <int key="NSAlign">0</int> + <int key="NSScale">0</int> + <int key="NSStyle">0</int> + <bool key="NSAnimates">NO</bool> + </object> + <bool key="NSEditable">YES</bool> + </object> + <object class="NSTextField" id="555840669"> + <reference key="NSNextResponder" ref="380531918"/> + <int key="NSvFlags">258</int> + <string key="NSFrame">{{32, 5}, {511, 17}}</string> + <reference key="NSSuperview" ref="380531918"/> + <bool key="NSEnabled">YES</bool> + <object class="NSTextFieldCell" key="NSCell" id="839405772"> + <int key="NSCellFlags">68288064</int> + <int key="NSCellFlags2">272630784</int> + <string key="NSContents">^IDS_OPTIONS_MANAGED_PREFS</string> + <reference key="NSSupport" ref="445696277"/> + <reference key="NSControlView" ref="555840669"/> + <reference key="NSBackgroundColor" ref="592613688"/> + <reference key="NSTextColor" ref="748094473"/> + </object> + </object> + </object> + <string key="NSFrameSize">{540, 27}</string> + <reference key="NSSuperview"/> + <string key="NSClassName">VerticalGradientView</string> + </object> <object class="NSCustomObject" id="385419425"> <string key="NSClassName">ChromeUILocalizer</string> </object> <object class="NSCustomObject" id="305848829"> <string key="NSClassName">ChromeUILocalizer</string> </object> + <object class="NSCustomObject" id="78746495"> + <string key="NSClassName">ChromeUILocalizer</string> + </object> <object class="NSCustomObject" id="145618054"> <string key="NSClassName">GTMIBArray</string> </object> @@ -3878,6 +3938,30 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> <int key="connectionID">691</int> </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">managedPrefsBannerView_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="380531918"/> + </object> + <int key="connectionID">697</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">managedPrefsBannerWarningImage_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="846805293"/> + </object> + <int key="connectionID">698</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">owner_</string> + <reference key="source" ref="78746495"/> + <reference key="destination" ref="380531918"/> + </object> + <int key="connectionID">701</int> + </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> @@ -5133,6 +5217,50 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <reference key="object" ref="201482610"/> <reference key="parent" ref="596669929"/> </object> + <object class="IBObjectRecord"> + <int key="objectID">692</int> + <reference key="object" ref="380531918"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="846805293"/> + <reference ref="555840669"/> + </object> + <reference key="parent" ref="476301154"/> + <string key="objectName">Managed Prefs Banner</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">693</int> + <reference key="object" ref="846805293"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="252500928"/> + </object> + <reference key="parent" ref="380531918"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">694</int> + <reference key="object" ref="252500928"/> + <reference key="parent" ref="846805293"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">695</int> + <reference key="object" ref="555840669"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="839405772"/> + </object> + <reference key="parent" ref="380531918"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">696</int> + <reference key="object" ref="839405772"/> + <reference key="parent" ref="555840669"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">699</int> + <reference key="object" ref="78746495"/> + <reference key="parent" ref="476301154"/> + </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> @@ -5311,6 +5439,13 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>662.IBPluginDependency</string> <string>67.IBPluginDependency</string> <string>69.IBPluginDependency</string> + <string>692.IBEditorWindowLastContentRect</string> + <string>692.IBPluginDependency</string> + <string>693.IBPluginDependency</string> + <string>694.IBPluginDependency</string> + <string>695.IBPluginDependency</string> + <string>696.IBPluginDependency</string> + <string>699.IBPluginDependency</string> <string>70.IBPluginDependency</string> <string>71.IBPluginDependency</string> <string>74.IBEditorWindowLastContentRect</string> @@ -5508,6 +5643,13 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{277, 847}, {540, 27}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{{375, 102}, {443, 754}}</string> @@ -5550,7 +5692,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> </object> </object> <nil key="sourceID"/> - <int key="maxID">691</int> + <int key="maxID">701</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> @@ -5790,6 +5932,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>downloadLocationButton_</string> <string>downloadLocationControl_</string> <string>enableLoggingCheckbox_</string> + <string>managedPrefsBannerView_</string> + <string>managedPrefsBannerWarningImage_</string> <string>personalStuffGroupAutofill_</string> <string>personalStuffGroupBrowserData_</string> <string>personalStuffGroupPasswords_</string> @@ -5821,6 +5965,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string>NSButton</string> <string>NSPathControl</string> <string>NSButton</string> + <string>VerticalGradientView</string> + <string>NSImageView</string> <string>NSArray</string> <string>NSArray</string> <string>NSArray</string> @@ -5843,6 +5989,14 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes> <string key="minorKey">browser/cocoa/preferences_window_controller.h</string> </object> </object> + <object class="IBPartialClassDescription"> + <string key="className">VerticalGradientView</string> + <string key="superclassName">NSView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/vertical_gradient_view.h</string> + </object> + </object> </object> </object> <int key="IBDocument.localizationMode">0</int> diff --git a/chrome/browser/cocoa/infobar_gradient_view.h b/chrome/browser/cocoa/infobar_gradient_view.h index f80650d..27c303d 100644 --- a/chrome/browser/cocoa/infobar_gradient_view.h +++ b/chrome/browser/cocoa/infobar_gradient_view.h @@ -5,19 +5,14 @@ #ifndef CHROME_BROWSER_COCOA_INFOBAR_GRADIENT_VIEW_H_ #define CHROME_BROWSER_COCOA_INFOBAR_GRADIENT_VIEW_H_ +#import "chrome/browser/cocoa/vertical_gradient_view.h" + #import <Cocoa/Cocoa.h> // A custom view that draws the background gradient for an infobar. -// The default is a yellow gradient, but a custom gradient can also be set. -@interface InfoBarGradientView : NSView { - @private - // The gradient to draw. - NSGradient* gradient_; +@interface InfoBarGradientView : VerticalGradientView { } -// Set a custom gradient for the view. -- (void)setGradient:(NSGradient*)gradient; - @end #endif // CHROME_BROWSER_COCOA_INFOBAR_GRADIENT_VIEW_H_ diff --git a/chrome/browser/cocoa/infobar_gradient_view.mm b/chrome/browser/cocoa/infobar_gradient_view.mm index 6af8fbb..1dc0b7c 100644 --- a/chrome/browser/cocoa/infobar_gradient_view.mm +++ b/chrome/browser/cocoa/infobar_gradient_view.mm @@ -4,13 +4,17 @@ #include "chrome/browser/cocoa/infobar_gradient_view.h" +#include "base/scoped_nsobject.h" #import "chrome/browser/browser_theme_provider.h" #import "chrome/browser/cocoa/themed_window.h" +namespace { + const double kBackgroundColorTop[3] = {255.0 / 255.0, 242.0 / 255.0, 183.0 / 255.0}; const double kBackgroundColorBottom[3] = {250.0 / 255.0, 230.0 / 255.0, 145.0 / 255.0}; +} @implementation InfoBarGradientView @@ -26,24 +30,14 @@ const double kBackgroundColorBottom[3] = green:kBackgroundColorBottom[1] blue:kBackgroundColorBottom[2] alpha:1.0]; - gradient_ = + scoped_nsobject<NSGradient> gradient( [[NSGradient alloc] initWithStartingColor:startingColor - endingColor:endingColor]; + endingColor:endingColor]); + [self setGradient:gradient]; } return self; } -- (void)dealloc { - [gradient_ release]; - [super dealloc]; -} - -- (void)setGradient:(NSGradient*)gradient { - [gradient retain]; - [gradient_ release]; - gradient_ = gradient; -} - - (NSColor*)strokeColor { ThemeProvider* themeProvider = [[self window] themeProvider]; if (!themeProvider) @@ -56,16 +50,6 @@ const double kBackgroundColorBottom[3] = true); } -- (void)drawRect:(NSRect)rect { - [gradient_ drawInRect:[self bounds] angle:270]; - - // Draw bottom stroke - [[self strokeColor] set]; - NSRect borderRect, contentRect; - NSDivideRect([self bounds], &borderRect, &contentRect, 1, NSMinYEdge); - NSRectFillUsingOperation(borderRect, NSCompositeSourceOver); -} - - (BOOL)mouseDownCanMoveWindow { return NO; } diff --git a/chrome/browser/cocoa/preferences_window_controller.h b/chrome/browser/cocoa/preferences_window_controller.h index d77545b..d1a515b 100644 --- a/chrome/browser/cocoa/preferences_window_controller.h +++ b/chrome/browser/cocoa/preferences_window_controller.h @@ -11,6 +11,7 @@ namespace PreferencesWindowControllerInternal { class PrefObserverBridge; +class ManagedPrefsBannerState; } @class CustomHomePagesModel; @@ -19,6 +20,7 @@ class PrefService; class Profile; class ProfileSyncService; @class SearchEngineListModel; +@class VerticalGradientView; @class WindowSizeAutosaver; // A window controller that handles the preferences window. The bulk of the @@ -43,8 +45,14 @@ class ProfileSyncService; scoped_ptr<PreferencesWindowControllerInternal::PrefObserverBridge> observer_; // Watches for pref changes. scoped_nsobject<WindowSizeAutosaver> sizeSaver_; + NSView* currentPrefsView_; // weak ref - current prefs page view. + scoped_ptr<PreferencesWindowControllerInternal::ManagedPrefsBannerState> + bannerState_; + BOOL managedPrefsBannerVisible_; IBOutlet NSToolbar* toolbar_; + IBOutlet VerticalGradientView* managedPrefsBannerView_; + IBOutlet NSImageView* managedPrefsBannerWarningImage_; // The views we'll rotate through IBOutlet NSView* basicsView_; diff --git a/chrome/browser/cocoa/preferences_window_controller.mm b/chrome/browser/cocoa/preferences_window_controller.mm index 6099b0b..b432a5b 100644 --- a/chrome/browser/cocoa/preferences_window_controller.mm +++ b/chrome/browser/cocoa/preferences_window_controller.mm @@ -8,6 +8,7 @@ #include "app/l10n_util.h" #include "app/l10n_util_mac.h" +#include "app/resource_bundle.h" #include "base/logging.h" #include "base/mac_util.h" #include "base/string16.h" @@ -28,9 +29,11 @@ #import "chrome/browser/cocoa/l10n_util.h" #import "chrome/browser/cocoa/search_engine_list_model.h" #import "chrome/browser/cocoa/sync_customize_controller_cppsafe.h" +#import "chrome/browser/cocoa/vertical_gradient_view.h" #import "chrome/browser/cocoa/window_size_autosaver.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/managed_prefs_banner_base.h" #include "chrome/browser/metrics/metrics_service.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/net/dns_global.h" @@ -54,24 +57,30 @@ #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" +#include "grit/theme_resources.h" #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h" namespace { +// Colors for the managed preferences warning banner. +static const double kBannerGradientColorTop[3] = + {255.0 / 255.0, 242.0 / 255.0, 183.0 / 255.0}; +static const double kBannerGradientColorBottom[3] = + {250.0 / 255.0, 230.0 / 255.0, 145.0 / 255.0}; +static const double kBannerStrokeColor = 135.0 / 255.0; + +// Preferences relevant to the general page potentially constrained by policy. +static const wchar_t* kGeneralPolicyConstrainedPrefs[] = { + prefs::kHomePage, + prefs::kHomePageIsNewTabPage +}; + std::string GetNewTabUIURLString() { return URLFixerUpper::FixupURL(chrome::kChromeUINewTabURL, std::string()).possibly_invalid_spec(); } -// Helper to remove all but the last view from the view hierarchy. -void RemoveAllButLastView(NSArray* views) { - NSArray* toRemove = [views subarrayWithRange:NSMakeRange(0, [views count]-1)]; - for (NSView* view in toRemove) { - [view removeFromSuperviewWithoutNeedingDisplay]; - } -} - // Helper that sizes two buttons to fit in a row keeping their spacing, returns // the total horizontal size change. CGFloat SizeToFitButtonPair(NSButton* leftButton, NSButton* rightButton) { @@ -349,6 +358,8 @@ CGFloat AutoSizeUnderTheHoodContent(NSView* view, - (void)setTabsToLinks:(BOOL)value; - (void)displayPreferenceViewForPage:(OptionsPage)page animate:(BOOL)animate; +- (void)resetSubViews; +- (void)initBannerStateForPage:(OptionsPage)page; // KVC getter methods. - (BOOL)fileHandlerUIEnabled; @@ -383,6 +394,58 @@ class PrefObserverBridge : public NotificationObserver, PreferencesWindowController* controller_; // weak, owns us }; +// Tracks state for a managed prefs banner and triggers UI updates through the +// PreferencesWindowController as appropriate. +class ManagedPrefsBannerState : public ManagedPrefsBannerBase { + public: + virtual ~ManagedPrefsBannerState() { } + + BOOL IsVisible() { + return DetermineVisibility() ? YES : NO; + } + + // Create a banner state tracker object suitable for use with a given |page|. + static ManagedPrefsBannerState* CreateForPage( + PreferencesWindowController* controller, + OptionsPage page, + PrefService* prefs) { + switch (page) { + case OPTIONS_PAGE_GENERAL: + return new ManagedPrefsBannerState(controller, page, prefs, + kGeneralPolicyConstrainedPrefs, + arraysize(kGeneralPolicyConstrainedPrefs)); + case OPTIONS_PAGE_CONTENT: + break; + case OPTIONS_PAGE_ADVANCED: + break; + case OPTIONS_PAGE_DEFAULT: + case OPTIONS_PAGE_COUNT: + LOG(DFATAL) << "Invalid page value " << page; + break; + } + return new ManagedPrefsBannerState(controller, page, prefs, NULL, 0); + } + + protected: + // Overridden from ManagedPrefsBannerBase. + virtual void OnUpdateVisibility() { + [controller_ switchToPage:page_ animate:YES]; + } + + private: + explicit ManagedPrefsBannerState(PreferencesWindowController* controller, + OptionsPage page, + PrefService* prefs, + const wchar_t** relevant_prefs, + size_t count) + : ManagedPrefsBannerBase(prefs, relevant_prefs, count), + controller_(controller), + page_(page) { } + + PreferencesWindowController* controller_; // weak, owns us + OptionsPage page_; // current options page +}; + } // namespace PreferencesWindowControllerInternal @implementation PreferencesWindowController @@ -651,6 +714,12 @@ class PrefObserverBridge : public NotificationObserver, [underTheHoodContentView_ scrollPoint: NSMakePoint(0, underTheHoodContentSize.height)]; + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + NSImage* alertIcon = rb.GetNSImageNamed(IDR_WARNING); + DCHECK(alertIcon); + [managedPrefsBannerWarningImage_ setImage:alertIcon]; + + [self initBannerStateForPage:initialPage_]; [self switchToPage:initialPage_ animate:NO]; // Save/restore position based on prefs. @@ -661,6 +730,27 @@ class PrefObserverBridge : public NotificationObserver, path:prefs::kPreferencesWindowPlacement state:kSaveWindowRect]); } + + // Initialize the banner gradient and stroke color. + NSColor* bannerStartingColor = + [NSColor colorWithCalibratedRed:kBannerGradientColorTop[0] + green:kBannerGradientColorTop[1] + blue:kBannerGradientColorTop[2] + alpha:1.0]; + NSColor* bannerEndingColor = + [NSColor colorWithCalibratedRed:kBannerGradientColorBottom[0] + green:kBannerGradientColorBottom[1] + blue:kBannerGradientColorBottom[2] + alpha:1.0]; + scoped_nsobject<NSGradient> bannerGradient( + [[NSGradient alloc] initWithStartingColor:bannerStartingColor + endingColor:bannerEndingColor]); + [managedPrefsBannerView_ setGradient:bannerGradient]; + + NSColor* bannerStrokeColor = + [NSColor colorWithCalibratedWhite:kBannerStrokeColor + alpha:1.0]; + [managedPrefsBannerView_ setStrokeColor:bannerStrokeColor]; } - (void)dealloc { @@ -1752,17 +1842,9 @@ const int kDisabledIndex = 1; NSView* prefsView = [self getPrefsViewForPage:page]; NSView* contentView = [prefsWindow contentView]; - // Normally there is only one view, but if the user clicks really quickly, the - // animation could still been running, and the last view is the one that was - // animating in. - NSArray* subviews = [contentView subviews]; - NSView* currentPrefsView = nil; - if ([subviews count]) { - currentPrefsView = [subviews lastObject]; - } - // Make sure we aren't being told to display the same thing again. - if (currentPrefsView == prefsView) { + if (currentPrefsView_ == prefsView && + managedPrefsBannerVisible_ == bannerState_->IsVisible()) { return; } @@ -1770,15 +1852,29 @@ const int kDisabledIndex = 1; if (page != OPTIONS_PAGE_DEFAULT) lastSelectedPage_.SetValue(page); - // Stop any running animation, and remove any past views that were on the way - // out. + // Stop any running animation, and reset the subviews to the new state. We + // re-add any views we need for animation later. [animation_ stopAnimation]; - if ([subviews count]) { - RemoveAllButLastView(subviews); - } + NSView* oldPrefsView = currentPrefsView_; + currentPrefsView_ = prefsView; + [self resetSubViews]; + // Update the banner state. + [self initBannerStateForPage:page]; + BOOL showBanner = bannerState_->IsVisible(); + + // Update the window title. + NSToolbarItem* toolbarItem = [self getToolbarItemForPage:page]; + [prefsWindow setTitle:[toolbarItem label]]; + + // Calculate new frames for the subviews. NSRect prefsViewFrame = [prefsView frame]; NSRect contentViewFrame = [contentView frame]; + NSRect bannerViewFrame = [managedPrefsBannerView_ frame]; + + // Determine what height the managed prefs banner will use. + CGFloat bannerViewHeight = showBanner ? NSHeight(bannerViewFrame) : 0.0; + if (animate) { // NSViewAnimation doesn't seem to honor subview resizing as it animates the // Window's frame. So instead of trying to get the top in the right place, @@ -1789,26 +1885,20 @@ const int kDisabledIndex = 1; // The prefView is anchored to the top of its parent, so set its origin so // that the top is where it should be. When the window's frame is set, the // origin will be adjusted to keep it in the right spot. - prefsViewFrame.origin.y = - NSHeight(contentViewFrame) - NSHeight(prefsViewFrame); + prefsViewFrame.origin.y = NSHeight(contentViewFrame) - + NSHeight(prefsViewFrame) - bannerViewHeight; } + bannerViewFrame.origin.y = NSHeight(prefsViewFrame); + bannerViewFrame.size.width = NSWidth(contentViewFrame); [prefsView setFrame:prefsViewFrame]; - // Add the view. - [contentView addSubview:prefsView]; - [prefsWindow setInitialFirstResponder:prefsView]; - - // Update the window title. - NSToolbarItem* toolbarItem = [self getToolbarItemForPage:page]; - [prefsWindow setTitle:[toolbarItem label]]; - // Figure out the size of the window. NSRect windowFrame = [contentView convertRect:[prefsWindow frame] fromView:nil]; CGFloat titleToolbarHeight = NSHeight(windowFrame) - NSHeight(contentViewFrame); windowFrame.size.height = - NSHeight(prefsViewFrame) + titleToolbarHeight; + NSHeight(prefsViewFrame) + titleToolbarHeight + bannerViewHeight; DCHECK_GE(NSWidth(windowFrame), NSWidth(prefsViewFrame)) << "Initial width set wasn't wide enough."; windowFrame = [contentView convertRect:windowFrame toView:nil]; @@ -1816,42 +1906,85 @@ const int kDisabledIndex = 1; // Now change the size. if (animate) { - NSDictionary* oldViewOut = - [NSDictionary dictionaryWithObjectsAndKeys: - currentPrefsView, NSViewAnimationTargetKey, - NSViewAnimationFadeOutEffect, NSViewAnimationEffectKey, - nil]; - NSDictionary* newViewIn = - [NSDictionary dictionaryWithObjectsAndKeys: - prefsView, NSViewAnimationTargetKey, - NSViewAnimationFadeInEffect, NSViewAnimationEffectKey, - nil]; - NSDictionary* windowResize = + NSMutableArray* animations = [NSMutableArray arrayWithCapacity:4]; + if (oldPrefsView != prefsView) { + // Fade between prefs views if they change. + [contentView addSubview:oldPrefsView + positioned:NSWindowBelow + relativeTo:nil]; + [animations addObject: + [NSDictionary dictionaryWithObjectsAndKeys: + oldPrefsView, NSViewAnimationTargetKey, + NSViewAnimationFadeOutEffect, NSViewAnimationEffectKey, + nil]]; + [animations addObject: + [NSDictionary dictionaryWithObjectsAndKeys: + prefsView, NSViewAnimationTargetKey, + NSViewAnimationFadeInEffect, NSViewAnimationEffectKey, + nil]]; + } else { + // Make sure the prefs pane ends up in the right position in case we + // manipulate the banner. + [animations addObject: + [NSDictionary dictionaryWithObjectsAndKeys: + prefsView, NSViewAnimationTargetKey, + [NSValue valueWithRect:prefsViewFrame], + NSViewAnimationEndFrameKey, + nil]]; + } + if (showBanner != managedPrefsBannerVisible_) { + // Slide the warning banner in or out of view. + [animations addObject: + [NSDictionary dictionaryWithObjectsAndKeys: + managedPrefsBannerView_, NSViewAnimationTargetKey, + [NSValue valueWithRect:bannerViewFrame], + NSViewAnimationEndFrameKey, + nil]]; + } + // Window resize animation. + [animations addObject: [NSDictionary dictionaryWithObjectsAndKeys: - prefsWindow, NSViewAnimationTargetKey, - [NSValue valueWithRect:windowFrame], NSViewAnimationEndFrameKey, - nil]; - [animation_ setViewAnimations: - [NSArray arrayWithObjects:oldViewOut, newViewIn, windowResize, nil]]; + prefsWindow, NSViewAnimationTargetKey, + [NSValue valueWithRect:windowFrame], NSViewAnimationEndFrameKey, + nil]]; + [animation_ setViewAnimations:animations]; // The default duration is 0.5s, which actually feels slow in here, so speed // it up a bit. [animation_ gtm_setDuration:0.2 eventMask:NSLeftMouseUpMask]; [animation_ startAnimation]; } else { - [currentPrefsView removeFromSuperviewWithoutNeedingDisplay]; // If not animating, odds are we don't want to display either (because it // is initial window setup). [prefsWindow setFrame:windowFrame display:NO]; + [managedPrefsBannerView_ setFrame:bannerViewFrame]; } + + managedPrefsBannerVisible_ = showBanner; +} + +- (void)resetSubViews { + // Reset subviews to current prefs view and banner, remove any views that + // might have been left over from previous state or animation. + NSArray* subviews = [NSArray arrayWithObjects: + currentPrefsView_, managedPrefsBannerView_, nil]; + [[[self window] contentView] setSubviews:subviews]; + [[self window] setInitialFirstResponder:currentPrefsView_]; } - (void)animationDidEnd:(NSAnimation*)animation { DCHECK_EQ(animation_.get(), animation); - // Animation finished, remove everything but the view we just added (it will - // be last in the list). - NSArray* subviews = [[[self window] contentView] subviews]; - RemoveAllButLastView(subviews); + // Animation finished, reset subviews to current prefs view and the banner. + [self resetSubViews]; +} + +// Reinitializes the banner state tracker object to watch for managed bits of +// preferences relevant to the given options |page|. +- (void)initBannerStateForPage:(OptionsPage)page { + page = [self normalizePage:page]; + bannerState_.reset( + PreferencesWindowControllerInternal::ManagedPrefsBannerState:: + CreateForPage(self, page, prefs_)); } - (void)switchToPage:(OptionsPage)page animate:(BOOL)animate { diff --git a/chrome/browser/cocoa/vertical_gradient_view.h b/chrome/browser/cocoa/vertical_gradient_view.h new file mode 100644 index 0000000..d6364c2 --- /dev/null +++ b/chrome/browser/cocoa/vertical_gradient_view.h @@ -0,0 +1,35 @@ +// Copyright (c) 2010 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_VERTICAL_GRADIENT_VIEW_H_ +#define CHROME_BROWSER_COCOA_VERTICAL_GRADIENT_VIEW_H_ + +#include "base/scoped_nsobject.h" + +#import <Cocoa/Cocoa.h> + +// Draws a vertical background gradient with a bottom stroke. The gradient and +// stroke colors can be defined by calling |setGradient| and |setStrokeColor|, +// respectively. Alternatively, you may override the |gradient| and +// |strokeColor| accessors in order to provide colors dynamically. If the +// gradient or color is |nil|, the respective element will not be drawn. +@interface VerticalGradientView : NSView { + @private + // The gradient to draw. + scoped_nsobject<NSGradient> gradient_; + // Color for bottom stroke. + scoped_nsobject<NSColor> strokeColor_; +} + +// Gets and sets the gradient to paint as background. +- (NSGradient*)gradient; +- (void)setGradient:(NSGradient*)gradient; + +// Gets and sets the color of the stroke drawn at the bottom of the view. +- (NSColor*)strokeColor; +- (void)setStrokeColor:(NSColor*)gradient; + +@end + +#endif // CHROME_BROWSER_COCOA_VERTICAL_GRADIENT_VIEW_H_ diff --git a/chrome/browser/cocoa/vertical_gradient_view.mm b/chrome/browser/cocoa/vertical_gradient_view.mm new file mode 100644 index 0000000..701053d --- /dev/null +++ b/chrome/browser/cocoa/vertical_gradient_view.mm @@ -0,0 +1,39 @@ +// Copyright (c) 2010 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. + +#include "chrome/browser/cocoa/vertical_gradient_view.h" + +@implementation VerticalGradientView + +- (NSGradient*)gradient { + return gradient_; +} + +- (void)setGradient:(NSGradient*)gradient { + gradient_.reset([gradient retain]); +} + +- (NSColor*)strokeColor { + return strokeColor_; +} + +- (void)setStrokeColor:(NSColor*)strokeColor { + strokeColor_.reset([strokeColor retain]); +} + +- (void)drawRect:(NSRect)rect { + // Draw gradient. + [[self gradient] drawInRect:[self bounds] angle:270]; + + // Draw bottom stroke. + NSColor* strokeColor = [self strokeColor]; + if (strokeColor) { + [[self strokeColor] set]; + NSRect borderRect, contentRect; + NSDivideRect([self bounds], &borderRect, &contentRect, 1, NSMinYEdge); + NSRectFillUsingOperation(borderRect, NSCompositeSourceOver); + } +} + +@end diff --git a/chrome/browser/cocoa/vertical_gradient_view_unittest.mm b/chrome/browser/cocoa/vertical_gradient_view_unittest.mm new file mode 100644 index 0000000..2e4e0a7 --- /dev/null +++ b/chrome/browser/cocoa/vertical_gradient_view_unittest.mm @@ -0,0 +1,27 @@ +// Copyright (c) 2010 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. + +#include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#import "chrome/browser/cocoa/vertical_gradient_view.h" + +namespace { + +class VerticalGradientViewTest : public CocoaTest { + public: + VerticalGradientViewTest() { + NSRect frame = NSMakeRect(0, 0, 50, 27); + scoped_nsobject<VerticalGradientView> view( + [[VerticalGradientView alloc] initWithFrame:frame]); + view_ = view.get(); + [[test_window() contentView] addSubview:view_]; + } + + VerticalGradientView* view_; +}; + +TEST_VIEW(VerticalGradientViewTest, view_); + +} // namespace + diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 4e8f2b0..3714b39 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -902,6 +902,8 @@ 'browser/cocoa/ui_localizer.mm', 'browser/cocoa/url_drop_target.h', 'browser/cocoa/url_drop_target.mm', + 'browser/cocoa/vertical_gradient_view.h', + 'browser/cocoa/vertical_gradient_view.mm', 'browser/cocoa/view_resizer.h', 'browser/cocoa/web_contents_drag_source.h', 'browser/cocoa/web_contents_drag_source.mm', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index f87178c..d98e4d5 100755 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -753,6 +753,7 @@ 'browser/cocoa/toolbar_controller_unittest.mm', 'browser/cocoa/toolbar_view_unittest.mm', 'browser/cocoa/translate_infobar_unittest.mm', + 'browser/cocoa/vertical_gradient_view_unittest.mm', 'browser/cocoa/view_resizer_pong.h', 'browser/cocoa/view_resizer_pong.mm', 'browser/cocoa/web_drop_target_unittest.mm', |