diff options
Diffstat (limited to 'chrome/browser/cocoa/preferences_window_controller.mm')
-rw-r--r-- | chrome/browser/cocoa/preferences_window_controller.mm | 140 |
1 files changed, 118 insertions, 22 deletions
diff --git a/chrome/browser/cocoa/preferences_window_controller.mm b/chrome/browser/cocoa/preferences_window_controller.mm index bdb4dd6..1a4967a 100644 --- a/chrome/browser/cocoa/preferences_window_controller.mm +++ b/chrome/browser/cocoa/preferences_window_controller.mm @@ -6,7 +6,9 @@ #include <algorithm> #include "app/l10n_util.h" +#include "app/l10n_util_mac.h" #include "base/mac_util.h" +#include "base/string16.h" #include "base/string_util.h" #include "base/sys_string_conversions.h" #include "chrome/browser/browser.h" @@ -26,6 +28,8 @@ #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/session_startup_pref.h" #include "chrome/browser/shell_integration.h" +#include "chrome/browser/sync/profile_sync_service.h" +#include "chrome/browser/sync/sync_status_ui_helper.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/notification_details.h" #include "chrome/common/notification_observer.h" @@ -249,7 +253,6 @@ NSInteger CompareFrameY(id view1, id view2, void* context) { return NSOrderedSame; } -#if !defined(GOOGLE_CHROME_BUILD) // Helper to remove a view and move everything above it down to take over the // space. void RemoveViewFromView(NSView* view, NSView* toRemove) { @@ -261,32 +264,48 @@ void RemoveViewFromView(NSView* view, NSView* toRemove) { NSUInteger index = [views indexOfObject:toRemove]; DCHECK_NE(index, NSNotFound); NSUInteger count = [views count]; - if (index == (count - 1)) - return; // It was the top item, nothing to do (shouldn't happen). - - // The amount to shift is the bottom of |toRemove| to the bottom of the view - // above it. - CGFloat shiftDown = - NSMinY([[views objectAtIndex:index + 1] frame]) - - NSMinY([toRemove frame]); - - // Now cycle over the views above it moving them down. - for (++index; index < count; ++index) { - NSView* view = [views objectAtIndex:index]; - NSPoint origin = [view frame].origin; - origin.y -= shiftDown; - [view setFrameOrigin:origin]; + CGFloat shrinkHeight = 0; + if (index < (count - 1)) { + // If we're not the topmost control, the amount to shift is the bottom of + // |toRemove| to the bottom of the view above it. + CGFloat shiftDown = + NSMinY([[views objectAtIndex:index + 1] frame]) - + NSMinY([toRemove frame]); + + // Now cycle over the views above it moving them down. + for (++index; index < count; ++index) { + NSView* view = [views objectAtIndex:index]; + NSPoint origin = [view frame].origin; + origin.y -= shiftDown; + [view setFrameOrigin:origin]; + } + + shrinkHeight = shiftDown; + } else if (index > 0) { + // If we're the topmost control, there's nothing to shift but we want to + // shrink until the top edge of the second-topmost control, unless it is + // actually higher than the topmost control (since we're sorting by the + // bottom edge). + shrinkHeight = std::max(0.f, + NSMaxY([toRemove frame]) - + NSMaxY([[views objectAtIndex:index - 1] frame])); } + // If we only have one control, don't do any resizing (for now). // Remove |toRemove|. [toRemove removeFromSuperview]; - // Resize the view. [GTMUILocalizerAndLayoutTweaker resizeViewWithoutAutoResizingSubViews:view - delta:NSMakeSize(0, -shiftDown)]; + delta:NSMakeSize(0, -shrinkHeight)]; +} + +// Simply removes all the views in |toRemove|. +void RemoveGroupFromView(NSView* view, NSArray* toRemove) { + for (NSView* viewToRemove in toRemove) { + RemoveViewFromView(view, viewToRemove); + } } -#endif // !defined(GOOGLE_CHROME_BUILD) // Helper to tweak the layout of the "Under the Hood" content by autosizing all // the views and moving things up vertically. Special case the two controls for @@ -332,6 +351,9 @@ CGFloat AutoSizeUnderTheHoodContent(NSView* view, // Callback when preferences are changed. |prefName| is the name of the // pref that has changed. - (void)prefChanged:(std::wstring*)prefName; +// Callback when sync state has changed. syncService_ needs to be +// queried to find out what happened. +- (void)syncStateChanged; // Record the user performed a certain action and save the preferences. - (void)recordUserAction:(const wchar_t*)action; - (void)registerPrefObservers; @@ -361,10 +383,14 @@ CGFloat AutoSizeUnderTheHoodContent(NSView* view, // A C++ class registered for changes in preferences. Bridges the // notification back to the PWC. -class PrefObserverBridge : public NotificationObserver { +class PrefObserverBridge : public NotificationObserver, + public ProfileSyncServiceObserver { public: PrefObserverBridge(PreferencesWindowController* controller) - : controller_(controller) { } + : controller_(controller) {} + + virtual ~PrefObserverBridge() {} + // Overridden from NotificationObserver: virtual void Observe(NotificationType type, const NotificationSource& source, @@ -372,6 +398,12 @@ class PrefObserverBridge : public NotificationObserver { if (type == NotificationType::PREF_CHANGED) [controller_ prefChanged:Details<std::wstring>(details).ptr()]; } + + // Overridden from ProfileSyncServiceObserver. + virtual void OnStateChanged() { + [controller_ syncStateChanged]; + } + private: PreferencesWindowController* controller_; // weak, owns us }; @@ -434,6 +466,11 @@ class PrefObserverBridge : public NotificationObserver { // it up a bit. [animation_ gtm_setDuration:0.2]; [animation_ setAnimationBlockingMode:NSAnimationNonblocking]; + + // TODO(akalin): handle incognito profiles? The windows version of this + // (in chrome/browser/views/options/content_page_view.cc) just does what + // we do below. + syncService_ = profile_->GetProfileSyncService(); } return self; } @@ -464,7 +501,7 @@ class PrefObserverBridge : public NotificationObserver { #endif // !defined(GOOGLE_CHROME_BUILD) // There are three problem children within the groups: - // Bascis - Default Browser + // Basics - Default Browser // Personal Stuff - Themes // Personal Stuff - Browser Data // These three have buttons that with some localizations are wider then the @@ -559,10 +596,24 @@ class PrefObserverBridge : public NotificationObserver { verticalShift += AutoSizeGroup(personalStuffGroupPasswords_, kAutoSizeGroupBehaviorVerticalToFit, verticalShift); + // We want to autosize the sync button but not the text field, so we use + // VerticalFirstToFit. + verticalShift += AutoSizeGroup(personalStuffGroupSync_, + kAutoSizeGroupBehaviorVerticalFirstToFit, + verticalShift); [GTMUILocalizerAndLayoutTweaker resizeViewWithoutAutoResizingSubViews:personalStuffView_ delta:NSMakeSize(0.0, verticalShift)]; + if (syncService_) { + syncService_->AddObserver(observer_.get()); + // Update the controls according to the initial state. + [self syncStateChanged]; + } else { + // If sync is disabled we don't want to show the sync controls at all. + RemoveGroupFromView(personalStuffView_, personalStuffGroupSync_); + } + // Make the window as wide as the views. NSWindow* prefsWindow = [self window]; NSRect frame = [prefsWindow frame]; @@ -613,6 +664,9 @@ class PrefObserverBridge : public NotificationObserver { } - (void)dealloc { + if (syncService_) { + syncService_->RemoveObserver(observer_.get()); + } [customPagesSource_ removeObserver:self forKeyPath:@"customHomePages"]; [[NSNotificationCenter defaultCenter] removeObserver:self]; [self unregisterPrefObservers]; @@ -1133,6 +1187,18 @@ const int kDisabledIndex = 1; } } +- (IBAction)doSyncAction:(id)sender { + DCHECK(syncService_); + if (syncService_->HasSyncSetupCompleted()) { + syncService_->DisableForUser(); + ProfileSyncService::SyncEvent(ProfileSyncService::STOP_FROM_OPTIONS); + // TODO(akalin): Pop up a confirmation dialog before disabling syncing. + } else { + syncService_->EnableForUser(); + ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_OPTIONS); + } +} + - (void)setPasswordManagerEnabledIndex:(NSInteger)value { if (value == kEnabledIndex) [self recordUserAction:L"Options_PasswordManager_Enable"]; @@ -1526,6 +1592,36 @@ const int kDisabledIndex = 1; [self underHoodPrefChanged:prefName]; } +// Callback when sync service state has changed. +// +// TODO(akalin): Decomp this out since a lot of it is copied from the +// Windows version. +// TODO(akalin): Actually have a control for the link. +// TODO(akalin): Change the background of the status label/link on error. +// TODO(akalin): Make sure selecting the "Sync my bookmarks..." menu item +// pops up this preference pane if syncing has already been set up. +- (void)syncStateChanged { + DCHECK(syncService_); + + [syncButton_ setEnabled:!syncService_->WizardIsVisible()]; + NSString* buttonLabel; + if (syncService_->HasSyncSetupCompleted()) { + buttonLabel = l10n_util::GetNSStringWithFixup( + IDS_SYNC_STOP_SYNCING_BUTTON_LABEL); + } else if (syncService_->SetupInProgress()) { + buttonLabel = l10n_util::GetNSStringWithFixup( + IDS_SYNC_NTP_SETUP_IN_PROGRESS); + } else { + buttonLabel = l10n_util::GetNSStringWithFixup( + IDS_SYNC_START_SYNC_BUTTON_LABEL); + } + [syncButton_ setTitle:buttonLabel]; + + string16 statusLabel, linkLabel; + SyncStatusUIHelper::GetLabels(syncService_, &statusLabel, &linkLabel); + [syncStatus_ setStringValue:base::SysUTF16ToNSString(statusLabel)]; +} + // Show the preferences window. - (IBAction)showPreferences:(id)sender { [self showWindow:sender]; |