OLD | NEW |
---|---|
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "chrome/browser/cocoa/preferences_window_controller.h" | 5 #import "chrome/browser/cocoa/preferences_window_controller.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include "app/l10n_util.h" | 8 #include "app/l10n_util.h" |
9 #include "base/mac_util.h" | 9 #include "base/mac_util.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 19 matching lines...) Expand all Loading... | |
30 #include "chrome/common/notification_observer.h" | 30 #include "chrome/common/notification_observer.h" |
31 #include "chrome/common/notification_type.h" | 31 #include "chrome/common/notification_type.h" |
32 #include "chrome/common/pref_names.h" | 32 #include "chrome/common/pref_names.h" |
33 #include "chrome/common/pref_service.h" | 33 #include "chrome/common/pref_service.h" |
34 #include "chrome/common/url_constants.h" | 34 #include "chrome/common/url_constants.h" |
35 #include "chrome/installer/util/google_update_settings.h" | 35 #include "chrome/installer/util/google_update_settings.h" |
36 #include "grit/chromium_strings.h" | 36 #include "grit/chromium_strings.h" |
37 #include "grit/generated_resources.h" | 37 #include "grit/generated_resources.h" |
38 #include "grit/locale_settings.h" | 38 #include "grit/locale_settings.h" |
39 #include "net/base/cookie_policy.h" | 39 #include "net/base/cookie_policy.h" |
40 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" | |
40 | 41 |
41 NSString* const kUserDoneEditingPrefsNotification = | 42 NSString* const kUserDoneEditingPrefsNotification = |
42 @"kUserDoneEditingPrefsNotification"; | 43 @"kUserDoneEditingPrefsNotification"; |
43 | 44 |
44 namespace { | 45 namespace { |
45 | 46 |
46 std::wstring GetNewTabUIURLString() { | 47 std::wstring GetNewTabUIURLString() { |
47 std::wstring temp = UTF8ToWide(chrome::kChromeUINewTabURL); | 48 std::wstring temp = UTF8ToWide(chrome::kChromeUINewTabURL); |
48 return URLFixerUpper::FixupURL(temp, std::wstring()); | 49 return URLFixerUpper::FixupURL(temp, std::wstring()); |
49 } | 50 } |
50 | 51 |
51 // Adjusts the views origin so it will be centered if in a given width parent. | 52 // Adjusts the views origin so it will be centered if in a given width parent. |
52 void CenterViewForWidth(NSView* view, CGFloat width) { | 53 void CenterViewForWidth(NSView* view, CGFloat width) { |
53 NSRect frame = [view frame]; | 54 NSRect frame = [view frame]; |
54 frame.origin.x = (width - NSWidth(frame)) / 2.0; | 55 frame.origin.x = (width - NSWidth(frame)) / 2.0; |
55 [view setFrame:frame]; | 56 [view setFrame:frame]; |
56 } | 57 } |
57 | 58 |
58 // Helper to remove all but the last view from the view heirarchy. | 59 // Helper to remove all but the last view from the view heirarchy. |
59 void RemoveAllButLastView(NSArray* views) { | 60 void RemoveAllButLastView(NSArray* views) { |
60 NSArray* toRemove = [views subarrayWithRange:NSMakeRange(0, [views count]-1)]; | 61 NSArray* toRemove = [views subarrayWithRange:NSMakeRange(0, [views count]-1)]; |
61 for (NSView* view in toRemove) { | 62 for (NSView* view in toRemove) { |
62 [view removeFromSuperviewWithoutNeedingDisplay]; | 63 [view removeFromSuperviewWithoutNeedingDisplay]; |
63 } | 64 } |
64 } | 65 } |
65 | 66 |
67 // Helper for tweaking the prefs window, if view is a: | |
68 // checkbox, radio group or label: it gets a forced wrap at current size | |
69 // editable field: left as is | |
70 // anything else: do +[GTMUILocalizerAndLayoutTweaker sizeToFitView:] | |
71 NSSize WrapOrSizeToFit(NSView* view) { | |
72 if ([view isKindOfClass:[NSTextField class]]) { | |
73 NSTextField* textField = static_cast<NSTextField*>(view); | |
74 if ([textField isEditable]) | |
75 return NSZeroSize; | |
76 CGFloat heightChange = | |
77 [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:textField]; | |
78 return NSMakeSize(0.0, heightChange); | |
79 } | |
80 if ([view isKindOfClass:[NSMatrix class]]) { | |
81 NSMatrix* radioGroup = static_cast<NSMatrix*>(view); | |
82 [GTMUILocalizerAndLayoutTweaker wrapRadioGroupForWidth:radioGroup]; | |
83 return [GTMUILocalizerAndLayoutTweaker sizeToFitView:view]; | |
84 } | |
85 if ([view isKindOfClass:[NSButton class]]) { | |
86 NSButton* button = static_cast<NSButton*>(view); | |
87 NSButtonCell* buttonCell = [button cell]; | |
88 // Decide it's a checkbox via showsStateBy and highlightsBy. | |
89 if (([buttonCell showsStateBy] == NSCellState) && | |
90 ([buttonCell highlightsBy] == NSCellState)) { | |
91 [GTMUILocalizerAndLayoutTweaker wrapButtonTitleForWidth:button]; | |
92 return [GTMUILocalizerAndLayoutTweaker sizeToFitView:view]; | |
93 } | |
94 } | |
95 return [GTMUILocalizerAndLayoutTweaker sizeToFitView:view]; | |
96 } | |
97 | |
98 // The different behaviors for the "pref group" auto sizing. | |
99 enum AutoSizeGroupBehavior { | |
100 kAutoSizeGroupBehaviorVerticalToFit, | |
101 kAutoSizeGroupBehaviorVerticalFirstToFit, | |
102 kAutoSizeGroupBehaviorHorizontalToFit, | |
103 kAutoSizeGroupBehaviorHorizontalFirstGrows | |
104 }; | |
105 | |
106 // Helper to tweak the layout of the "pref groups" and also ripple any height | |
107 // changes from one group to the next groups' origins. | |
108 // |views| is an ordered list of views with first being the label for the | |
109 // group and the rest being top down or left to right ordering of the views. | |
110 // The label is assumed to already be the same height as all the views it is | |
111 // next too. | |
112 CGFloat AutoSizeGroup(NSArray* views, AutoSizeGroupBehavior behavior, | |
113 CGFloat verticalShift) { | |
114 DCHECK_GE([views count], 2U) << "Should be at least a label and a control"; | |
115 NSTextField* label = [views objectAtIndex:0]; | |
116 | |
117 #ifndef NDEBUG | |
118 // Validate the helpers assumptions in debug builds. | |
119 DCHECK([label isKindOfClass:[NSTextField class]]) | |
120 << "First view should be the label for the group"; | |
121 NSRect initialLabelRect = [label frame]; | |
122 for (NSView* view in views) { | |
123 if (view != label) { | |
124 DCHECK_GE(NSMaxY(initialLabelRect), NSMaxY([view frame])) | |
125 << "Got a view that goes above the group label"; | |
126 DCHECK_LE(NSMinY(initialLabelRect), NSMinY([view frame])) | |
127 << "Got a view that goes below the group label"; | |
128 } | |
129 } | |
130 #endif // DEBUG | |
Mark Mentovai
2009/10/30 22:19:27
NDEBUG
| |
131 | |
132 // Auto size the label to see if we need more vertical space for its localized | |
133 // string. | |
134 CGFloat labelHeightChange = | |
135 [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:label]; | |
136 | |
137 CGFloat localVerticalShift = 0.0; | |
138 switch (behavior) { | |
139 case kAutoSizeGroupBehaviorVerticalToFit: { | |
140 // Walk bottom up doing the sizing and moves. | |
141 for (NSUInteger idx = [views count] - 1; idx > 0; --idx) { | |
142 NSView* view = [views objectAtIndex:idx]; | |
143 NSSize delta = WrapOrSizeToFit(view); | |
144 DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height"; | |
145 if (localVerticalShift) { | |
146 NSPoint origin = [view frame].origin; | |
147 origin.y += localVerticalShift; | |
148 [view setFrameOrigin:origin]; | |
149 } | |
150 localVerticalShift += delta.height; | |
151 } | |
152 break; | |
153 } | |
154 case kAutoSizeGroupBehaviorVerticalFirstToFit: { | |
155 // Just size the top one. | |
156 NSView* view = [views objectAtIndex:1]; | |
157 NSSize delta = WrapOrSizeToFit(view); | |
158 DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height"; | |
159 localVerticalShift += delta.height; | |
160 break; | |
161 } | |
162 case kAutoSizeGroupBehaviorHorizontalToFit: { | |
163 // Walk left to right doing the sizing and moves. | |
164 // NOTE: Don't worry about vertical, assume it always fits. | |
165 CGFloat horizontalShift = 0.0; | |
166 for (NSUInteger idx = 1; idx < [views count]; ++idx) { | |
167 NSView* view = [views objectAtIndex:idx]; | |
168 NSSize delta = WrapOrSizeToFit(view); | |
169 DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height"; | |
170 if (horizontalShift) { | |
171 NSPoint origin = [view frame].origin; | |
172 origin.x += horizontalShift; | |
173 [view setFrameOrigin:origin]; | |
174 } | |
175 horizontalShift += delta.width; | |
176 } | |
177 break; | |
178 } | |
179 case kAutoSizeGroupBehaviorHorizontalFirstGrows: { | |
180 // Walk right to left doing the sizing and moves, then apply the space | |
181 // collected into the first. | |
182 // NOTE: Don't worry about vertical, assume it always all fits. | |
183 CGFloat horizontalShift = 0.0; | |
184 for (NSUInteger idx = [views count] - 1; idx > 1; --idx) { | |
185 NSView* view = [views objectAtIndex:idx]; | |
186 NSSize delta = WrapOrSizeToFit(view); | |
187 DCHECK_GE(delta.height, 0.0) << "Should NOT shrink in height"; | |
188 horizontalShift -= delta.width; | |
189 NSPoint origin = [view frame].origin; | |
190 origin.x += horizontalShift; | |
191 [view setFrameOrigin:origin]; | |
192 } | |
193 if (horizontalShift) { | |
194 NSView* view = [views objectAtIndex:1]; | |
195 NSSize delta = NSMakeSize(horizontalShift, 0.0); | |
196 [GTMUILocalizerAndLayoutTweaker | |
197 resizeViewWithoutAutoResizingSubViews:view | |
198 delta:delta]; | |
199 } | |
200 break; | |
201 } | |
202 default: | |
203 NOTREACHED(); | |
204 break; | |
205 } | |
206 | |
207 // If the label grew more then the views, the other views get an extra shift. | |
208 // Otherwise, move the label to its top is aligned with the other views. | |
209 CGFloat nonLabelShift = 0.0; | |
210 if (labelHeightChange > localVerticalShift) { | |
211 // Since the lable is taller, centering the other views looks best, just | |
212 // shift the views by 1/2 of the size difference. | |
213 nonLabelShift = (labelHeightChange - localVerticalShift) / 2.0; | |
214 } else { | |
215 NSPoint origin = [label frame].origin; | |
216 origin.y += localVerticalShift - labelHeightChange; | |
217 [label setFrameOrigin:origin]; | |
218 } | |
219 | |
220 // Apply the input shift requested along with any the shift from label being | |
221 // taller then the rest of the group. | |
222 for (NSView* view in views) { | |
223 NSPoint origin = [view frame].origin; | |
224 origin.y += verticalShift; | |
225 if (view != label) { | |
226 origin.y += nonLabelShift; | |
227 } | |
228 [view setFrameOrigin:origin]; | |
229 } | |
230 | |
231 // Return how much the group grew. | |
232 return localVerticalShift + nonLabelShift; | |
233 } | |
234 | |
66 } // namespace | 235 } // namespace |
67 | 236 |
68 //------------------------------------------------------------------------- | 237 //------------------------------------------------------------------------- |
69 | 238 |
70 @interface PreferencesWindowController(Private) | 239 @interface PreferencesWindowController(Private) |
71 // Callback when preferences are changed. |prefName| is the name of the | 240 // Callback when preferences are changed. |prefName| is the name of the |
72 // pref that has changed. | 241 // pref that has changed. |
73 - (void)prefChanged:(std::wstring*)prefName; | 242 - (void)prefChanged:(std::wstring*)prefName; |
74 // Record the user performed a certain action and save the preferences. | 243 // Record the user performed a certain action and save the preferences. |
75 - (void)recordUserAction:(const wchar_t*)action; | 244 - (void)recordUserAction:(const wchar_t*)action; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
171 [animation_ setDelegate:self]; | 340 [animation_ setDelegate:self]; |
172 // The default duration is 0.5s, which actually feels slow in here, so speed | 341 // The default duration is 0.5s, which actually feels slow in here, so speed |
173 // it up a bit. | 342 // it up a bit. |
174 [animation_ setDuration:0.2]; | 343 [animation_ setDuration:0.2]; |
175 [animation_ setAnimationBlockingMode:NSAnimationNonblocking]; | 344 [animation_ setAnimationBlockingMode:NSAnimationNonblocking]; |
176 } | 345 } |
177 return self; | 346 return self; |
178 } | 347 } |
179 | 348 |
180 - (void)awakeFromNib { | 349 - (void)awakeFromNib { |
181 NSRect underTheHoodFrame = [underTheHoodView_ frame]; | 350 |
351 // Do runtime fixup of the "basics" and "personal stuff" pages for the | |
352 // strings. Work bottom up shifting views up as needed, and then resize the | |
353 // page. | |
354 CGFloat verticalShift = 0.0; | |
355 verticalShift += AutoSizeGroup(basicsGroupDefaultBrowser_, | |
356 kAutoSizeGroupBehaviorVerticalFirstToFit, | |
357 verticalShift); | |
358 verticalShift += AutoSizeGroup(basicsGroupSearchEngine_, | |
359 kAutoSizeGroupBehaviorHorizontalFirstGrows, | |
360 verticalShift); | |
361 verticalShift += AutoSizeGroup(basicsGroupToolbar_, | |
362 kAutoSizeGroupBehaviorVerticalToFit, | |
363 verticalShift); | |
364 verticalShift += AutoSizeGroup(basicsGroupHomePage_, | |
365 kAutoSizeGroupBehaviorVerticalToFit, | |
366 verticalShift); | |
367 verticalShift += AutoSizeGroup(basicsGroupStartup_, | |
368 kAutoSizeGroupBehaviorVerticalFirstToFit, | |
369 verticalShift); | |
370 [GTMUILocalizerAndLayoutTweaker | |
371 resizeViewWithoutAutoResizingSubViews:basicsView_ | |
372 delta:NSMakeSize(0.0, verticalShift)]; | |
373 verticalShift = 0.0; | |
Mark Mentovai
2009/10/30 22:19:27
nit: blank line before doing the second pane.
| |
374 verticalShift += AutoSizeGroup(personalStuffGroupThemes_, | |
375 kAutoSizeGroupBehaviorHorizontalToFit, | |
376 verticalShift); | |
377 verticalShift += AutoSizeGroup(personalStuffGroupBrowserData_, | |
378 kAutoSizeGroupBehaviorVerticalToFit, | |
379 verticalShift); | |
380 verticalShift += AutoSizeGroup(personalStuffGroupAutofill_, | |
381 kAutoSizeGroupBehaviorVerticalToFit, | |
382 verticalShift); | |
383 verticalShift += AutoSizeGroup(personalStuffGroupPasswords_, | |
384 kAutoSizeGroupBehaviorVerticalFirstToFit, | |
385 verticalShift); | |
386 [GTMUILocalizerAndLayoutTweaker | |
387 resizeViewWithoutAutoResizingSubViews:personalStuffView_ | |
388 delta:NSMakeSize(0.0, verticalShift)]; | |
182 | 389 |
183 // Make sure the window is wide enough to fit the the widest view | 390 // Make sure the window is wide enough to fit the the widest view |
391 NSRect underTheHoodFrame = [underTheHoodView_ frame]; | |
184 CGFloat widest = std::max(NSWidth([basicsView_ frame]), | 392 CGFloat widest = std::max(NSWidth([basicsView_ frame]), |
185 NSWidth([personalStuffView_ frame])); | 393 NSWidth([personalStuffView_ frame])); |
186 widest = std::max(widest, NSWidth(underTheHoodFrame)); | 394 widest = std::max(widest, NSWidth(underTheHoodFrame)); |
187 NSWindow* prefsWindow = [self window]; | 395 NSWindow* prefsWindow = [self window]; |
188 NSRect frame = [prefsWindow frame]; | 396 NSRect frame = [prefsWindow frame]; |
189 frame.size.width = widest; | 397 frame.size.width = widest; |
190 [prefsWindow setFrame:frame display:NO]; | 398 [prefsWindow setFrame:frame display:NO]; |
191 | 399 |
192 // The Under the Hood prefs is a scroller, it shouldn't get any border, so it | 400 // The Under the Hood prefs is a scroller, it shouldn't get any border, so it |
193 // gets resized to the as wide as the window ends up. | 401 // gets resized to the as wide as the window ends up. |
194 underTheHoodFrame.size.width = widest; | 402 underTheHoodFrame.size.width = widest; |
195 [underTheHoodView_ setFrame:underTheHoodFrame]; | 403 [underTheHoodView_ setFrame:underTheHoodFrame]; |
196 // Widen the Under the Hood content so things can rewrap | 404 // Widen the Under the Hood content so things can rewrap |
197 NSSize advancedContentSize = [advancedView_ frame].size; | 405 NSSize advancedContentSize = [advancedView_ frame].size; |
198 advancedContentSize.width = [advancedScroller_ contentSize].width; | 406 advancedContentSize.width = [advancedScroller_ contentSize].width; |
199 [advancedView_ setFrameSize:advancedContentSize]; | 407 [advancedView_ setFrameSize:advancedContentSize]; |
200 | 408 |
201 // Put the advanced view into the scroller and scroll it to the top. | |
202 [advancedScroller_ setDocumentView:advancedView_]; | |
203 [advancedView_ scrollPoint:NSMakePoint(0, advancedContentSize.height)]; | |
204 | |
205 // Adjust the view origins so they show up centered. | 409 // Adjust the view origins so they show up centered. |
206 CenterViewForWidth(basicsView_, widest); | 410 CenterViewForWidth(basicsView_, widest); |
207 CenterViewForWidth(personalStuffView_, widest); | 411 CenterViewForWidth(personalStuffView_, widest); |
208 CenterViewForWidth(underTheHoodView_, widest); | 412 CenterViewForWidth(underTheHoodView_, widest); |
209 | 413 |
210 // Ensure the "basics" is selected. | 414 // Put the advanced view into the scroller and scroll it to the top. |
415 [advancedScroller_ setDocumentView:advancedView_]; | |
416 [advancedView_ scrollPoint:NSMakePoint(0, advancedContentSize.height)]; | |
417 | |
418 // Ensure the "basics" page is selected. | |
211 // TODO: change this to remember what's selected in a preference and restore | 419 // TODO: change this to remember what's selected in a preference and restore |
212 // it. | 420 // it. |
213 | |
214 NSToolbarItem* firstItem = [[toolbar_ items] objectAtIndex:0]; | 421 NSToolbarItem* firstItem = [[toolbar_ items] objectAtIndex:0]; |
215 [self displayPreferenceViewForToolbarItem:firstItem animate:NO]; | 422 [self displayPreferenceViewForToolbarItem:firstItem animate:NO]; |
216 [toolbar_ setSelectedItemIdentifier:[firstItem itemIdentifier]]; | 423 [toolbar_ setSelectedItemIdentifier:[firstItem itemIdentifier]]; |
217 | 424 |
218 // TODO(pinkerton): save/restore position based on prefs. | 425 // TODO(pinkerton): save/restore position based on prefs. |
219 [[self window] center]; | 426 [[self window] center]; |
220 } | 427 } |
221 | 428 |
222 - (void)dealloc { | 429 - (void)dealloc { |
223 [customPagesSource_ removeObserver:self forKeyPath:@"customHomePages"]; | 430 [customPagesSource_ removeObserver:self forKeyPath:@"customHomePages"]; |
(...skipping 918 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1142 [[NSNotificationCenter defaultCenter] | 1349 [[NSNotificationCenter defaultCenter] |
1143 postNotificationName:kUserDoneEditingPrefsNotification | 1350 postNotificationName:kUserDoneEditingPrefsNotification |
1144 object:self]; | 1351 object:self]; |
1145 } | 1352 } |
1146 | 1353 |
1147 - (void)controlTextDidEndEditing:(NSNotification*)notification { | 1354 - (void)controlTextDidEndEditing:(NSNotification*)notification { |
1148 [customPagesSource_ validateURLs]; | 1355 [customPagesSource_ validateURLs]; |
1149 } | 1356 } |
1150 | 1357 |
1151 @end | 1358 @end |
OLD | NEW |