OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #import "ui/message_center/cocoa/settings_controller.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "base/mac/foundation_util.h" | |
10 #import "base/mac/scoped_nsobject.h" | |
11 #include "base/stl_util.h" | |
12 #include "base/strings/sys_string_conversions.h" | |
13 #include "skia/ext/skia_utils_mac.h" | |
14 #include "ui/base/l10n/l10n_util.h" | |
15 #import "ui/message_center/cocoa/opaque_views.h" | |
16 #import "ui/message_center/cocoa/settings_entry_view.h" | |
17 #import "ui/message_center/cocoa/tray_view_controller.h" | |
18 #include "ui/message_center/message_center_style.h" | |
19 #include "ui/strings/grit/ui_strings.h" | |
20 | |
21 using message_center::settings::kHorizontalMargin; | |
22 using message_center::settings::kEntryHeight; | |
23 | |
24 // Intrinsic padding pixels out of our control. | |
25 const int kIntrinsicHeaderTextTopPadding = 3; | |
26 const int kIntrinsicSubheaderTextTopPadding = 5; | |
27 const int kIntrinsicSubheaderTextBottomPadding = 3; | |
28 const int kIntrinsicDropDownVerticalPadding = 2; | |
29 const int kIntrinsicDropDownHorizontalPadding = 3; | |
30 | |
31 // Corrected padding values used in layout. | |
32 // Calculated additional blank space above the header text, including | |
33 // the intrinsic blank space above the header label. | |
34 const int kCorrectedHeaderTextTopPadding = | |
35 message_center::settings::kTopMargin - kIntrinsicHeaderTextTopPadding; | |
36 | |
37 // Calculated additional blank space above the subheader text, including | |
38 // the intrinsic blank space above the subheader label. | |
39 const int kCorrectedSubheaderTextTopPadding = | |
40 message_center::settings::kTitleToDescriptionSpace - | |
41 kIntrinsicSubheaderTextTopPadding; | |
42 | |
43 // Calcoulated additional vertical padding for the drop-down, including the | |
44 // blank space included with the drop-down control. | |
45 const int kCorrectedDropDownTopPadding = | |
46 message_center::settings::kDescriptionToSwitcherSpace - | |
47 kIntrinsicDropDownVerticalPadding - kIntrinsicSubheaderTextBottomPadding; | |
48 | |
49 // Calculated additional horizontal blank space for the drop down, including | |
50 // the blank space included with the drop-down control. | |
51 const int kCorrectedDropDownMargin = | |
52 kHorizontalMargin - kIntrinsicDropDownHorizontalPadding; | |
53 | |
54 @interface MCSettingsController (Private) | |
55 // Sets the icon on the checkbox corresponding to |notifiers_[index]|. | |
56 - (void)setIcon:(NSImage*)icon forNotifierIndex:(size_t)index; | |
57 | |
58 - (void)setIcon:(NSImage*)icon | |
59 forNotifierId:(const message_center::NotifierId&)id; | |
60 | |
61 // Returns the NSButton corresponding to the checkbox for |notifiers_[index]|. | |
62 - (MCSettingsEntryView*)entryForNotifierAtIndex:(size_t)index; | |
63 | |
64 // Update the contents view. | |
65 - (void)updateView; | |
66 | |
67 // Handler for the notifier group dropdown menu. | |
68 - (void)notifierGroupSelectionChanged:(id)sender; | |
69 | |
70 @end | |
71 | |
72 namespace message_center { | |
73 | |
74 NotifierSettingsObserverMac::~NotifierSettingsObserverMac() {} | |
75 | |
76 void NotifierSettingsObserverMac::UpdateIconImage(const NotifierId& notifier_id, | |
77 const gfx::Image& icon) { | |
78 [settings_controller_ setIcon:icon.AsNSImage() forNotifierId:notifier_id]; | |
79 } | |
80 | |
81 void NotifierSettingsObserverMac::NotifierGroupChanged() { | |
82 [settings_controller_ updateView]; | |
83 } | |
84 | |
85 void NotifierSettingsObserverMac::NotifierEnabledChanged( | |
86 const NotifierId& notifier_id, bool enabled) {} | |
87 | |
88 } // namespace message_center | |
89 | |
90 @implementation MCSettingsController | |
91 | |
92 - (id)initWithProvider:(message_center::NotifierSettingsProvider*)provider | |
93 trayViewController:(MCTrayViewController*)trayViewController { | |
94 if ((self = [super initWithNibName:nil bundle:nil])) { | |
95 observer_.reset(new message_center::NotifierSettingsObserverMac(self)); | |
96 provider_ = provider; | |
97 trayViewController_ = trayViewController; | |
98 provider_->AddObserver(observer_.get()); | |
99 } | |
100 return self; | |
101 } | |
102 | |
103 - (void)dealloc { | |
104 provider_->RemoveObserver(observer_.get()); | |
105 provider_->OnNotifierSettingsClosing(); | |
106 STLDeleteElements(¬ifiers_); | |
107 [super dealloc]; | |
108 } | |
109 | |
110 - (NSTextField*)newLabelWithFrame:(NSRect)frame { | |
111 NSColor* color = gfx::SkColorToCalibratedNSColor( | |
112 message_center::kMessageCenterBackgroundColor); | |
113 MCTextField* label = | |
114 [[MCTextField alloc] initWithFrame:frame backgroundColor:color]; | |
115 | |
116 return label; | |
117 } | |
118 | |
119 - (void)updateView { | |
120 notifiers_.clear(); | |
121 [trayViewController_ updateSettings]; | |
122 } | |
123 | |
124 - (void)loadView { | |
125 DCHECK(notifiers_.empty()); | |
126 provider_->GetNotifierList(¬ifiers_); | |
127 CGFloat maxHeight = [MCTrayViewController maxTrayClientHeight]; | |
128 | |
129 // Container view. | |
130 NSRect fullFrame = | |
131 NSMakeRect(0, 0, [MCTrayViewController trayWidth], maxHeight); | |
132 base::scoped_nsobject<NSBox> view([[NSBox alloc] initWithFrame:fullFrame]); | |
133 [view setBorderType:NSNoBorder]; | |
134 [view setBoxType:NSBoxCustom]; | |
135 [view setContentViewMargins:NSZeroSize]; | |
136 [view setFillColor:gfx::SkColorToCalibratedNSColor( | |
137 message_center::kMessageCenterBackgroundColor)]; | |
138 [view setTitlePosition:NSNoTitle]; | |
139 [self setView:view]; | |
140 | |
141 // "Settings" text. | |
142 NSRect headerFrame = NSMakeRect(kHorizontalMargin, | |
143 kHorizontalMargin, | |
144 NSWidth(fullFrame), | |
145 NSHeight(fullFrame)); | |
146 settingsText_.reset([self newLabelWithFrame:headerFrame]); | |
147 [settingsText_ setTextColor: | |
148 gfx::SkColorToCalibratedNSColor(message_center::kRegularTextColor)]; | |
149 [settingsText_ | |
150 setFont:[NSFont messageFontOfSize:message_center::kTitleFontSize]]; | |
151 | |
152 [settingsText_ setStringValue: | |
153 l10n_util::GetNSString(IDS_MESSAGE_CENTER_SETTINGS_BUTTON_LABEL)]; | |
154 [settingsText_ sizeToFit]; | |
155 headerFrame = [settingsText_ frame]; | |
156 headerFrame.origin.y = NSMaxY(fullFrame) - kCorrectedHeaderTextTopPadding - | |
157 NSHeight(headerFrame); | |
158 [[self view] addSubview:settingsText_]; | |
159 | |
160 // Subheader. | |
161 NSRect subheaderFrame = NSMakeRect(kHorizontalMargin, | |
162 kHorizontalMargin, | |
163 NSWidth(fullFrame), | |
164 NSHeight(fullFrame)); | |
165 detailsText_.reset([self newLabelWithFrame:subheaderFrame]); | |
166 [detailsText_ setTextColor: | |
167 gfx::SkColorToCalibratedNSColor(message_center::kDimTextColor)]; | |
168 [detailsText_ | |
169 setFont:[NSFont messageFontOfSize:message_center::kMessageFontSize]]; | |
170 | |
171 size_t groupCount = provider_->GetNotifierGroupCount(); | |
172 [detailsText_ setStringValue:l10n_util::GetNSString( | |
173 groupCount > 1 ? IDS_MESSAGE_CENTER_SETTINGS_DESCRIPTION_MULTIUSER | |
174 : IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION)]; | |
175 [detailsText_ sizeToFit]; | |
176 subheaderFrame = [detailsText_ frame]; | |
177 subheaderFrame.origin.y = | |
178 NSMinY(headerFrame) - kCorrectedSubheaderTextTopPadding - | |
179 NSHeight(subheaderFrame); | |
180 [[self view] addSubview:detailsText_]; | |
181 | |
182 // Profile switcher is only needed for more than one profile. | |
183 NSRect dropDownButtonFrame = subheaderFrame; | |
184 if (groupCount > 1) { | |
185 dropDownButtonFrame = NSMakeRect(kCorrectedDropDownMargin, | |
186 kHorizontalMargin, | |
187 NSWidth(fullFrame), | |
188 NSHeight(fullFrame)); | |
189 groupDropDownButton_.reset( | |
190 [[MCDropDown alloc] initWithFrame:dropDownButtonFrame pullsDown:YES]); | |
191 [groupDropDownButton_ | |
192 setBackgroundColor:gfx::SkColorToCalibratedNSColor( | |
193 message_center::kMessageCenterBackgroundColor)]; | |
194 [groupDropDownButton_ setAction:@selector(notifierGroupSelectionChanged:)]; | |
195 [groupDropDownButton_ setTarget:self]; | |
196 // Add a dummy item for pull-down. | |
197 [groupDropDownButton_ addItemWithTitle:@""]; | |
198 base::string16 title; | |
199 for (size_t i = 0; i < groupCount; ++i) { | |
200 const message_center::NotifierGroup& group = | |
201 provider_->GetNotifierGroupAt(i); | |
202 base::string16 item = | |
203 group.login_info.empty() ? group.name : group.login_info; | |
204 [groupDropDownButton_ addItemWithTitle:base::SysUTF16ToNSString(item)]; | |
205 if (provider_->IsNotifierGroupActiveAt(i)) { | |
206 title = item; | |
207 [[groupDropDownButton_ lastItem] setState:NSOnState]; | |
208 } | |
209 } | |
210 [groupDropDownButton_ setTitle:base::SysUTF16ToNSString(title)]; | |
211 [groupDropDownButton_ sizeToFit]; | |
212 dropDownButtonFrame = [groupDropDownButton_ frame]; | |
213 dropDownButtonFrame.origin.y = | |
214 NSMinY(subheaderFrame) - kCorrectedDropDownTopPadding - | |
215 NSHeight(dropDownButtonFrame); | |
216 dropDownButtonFrame.size.width = | |
217 NSWidth(fullFrame) - 2 * kCorrectedDropDownMargin; | |
218 [[self view] addSubview:groupDropDownButton_]; | |
219 } | |
220 | |
221 // Document view for the notifier settings. | |
222 CGFloat y = 0; | |
223 NSRect documentFrame = NSMakeRect(0, 0, NSWidth(fullFrame), 0); | |
224 base::scoped_nsobject<NSView> documentView( | |
225 [[NSView alloc] initWithFrame:documentFrame]); | |
226 int notifierCount = notifiers_.size(); | |
227 for (int i = notifierCount - 1; i >= 0; --i) { | |
228 message_center::Notifier* notifier = notifiers_[i]; | |
229 // TODO(thakis): Use a custom button cell. | |
230 NSRect frame = NSMakeRect(kHorizontalMargin, | |
231 y, | |
232 NSWidth(documentFrame) - kHorizontalMargin * 2, | |
233 kEntryHeight); | |
234 | |
235 base::scoped_nsobject<MCSettingsEntryView> entryView( | |
236 [[MCSettingsEntryView alloc] | |
237 initWithController:self | |
238 notifier:notifier | |
239 frame:frame | |
240 hasSeparator:(i != notifierCount - 1)]); | |
241 [documentView addSubview:entryView]; | |
242 y += NSHeight(frame); | |
243 } | |
244 | |
245 documentFrame.size.height = y - kIntrinsicDropDownVerticalPadding; | |
246 [documentView setFrame:documentFrame]; | |
247 | |
248 // Scroll view for the notifier settings. | |
249 NSRect scrollFrame = documentFrame; | |
250 scrollFrame.origin.y = 0; | |
251 CGFloat remainingHeight = NSMinY(dropDownButtonFrame) - NSMinY(scrollFrame); | |
252 | |
253 if (NSHeight(documentFrame) < remainingHeight) { | |
254 // Everything fits without scrolling. | |
255 CGFloat delta = remainingHeight - NSHeight(documentFrame); | |
256 headerFrame.origin.y -= delta; | |
257 subheaderFrame.origin.y -= delta; | |
258 dropDownButtonFrame.origin.y -= delta; | |
259 fullFrame.size.height -= delta; | |
260 } else { | |
261 scrollFrame.size.height = remainingHeight; | |
262 } | |
263 | |
264 scrollView_.reset([[NSScrollView alloc] initWithFrame:scrollFrame]); | |
265 [scrollView_ setAutohidesScrollers:YES]; | |
266 [scrollView_ setAutoresizingMask:NSViewMinYMargin]; | |
267 [scrollView_ setDocumentView:documentView]; | |
268 [scrollView_ setDrawsBackground:NO]; | |
269 [scrollView_ setHasHorizontalScroller:NO]; | |
270 [scrollView_ setHasVerticalScroller:YES]; | |
271 | |
272 // Scroll to top. | |
273 NSPoint newScrollOrigin = | |
274 NSMakePoint(0.0, | |
275 NSMaxY([[scrollView_ documentView] frame]) - | |
276 NSHeight([[scrollView_ contentView] bounds])); | |
277 [[scrollView_ documentView] scrollPoint:newScrollOrigin]; | |
278 | |
279 // Set final sizes. | |
280 [[self view] setFrame:fullFrame]; | |
281 [[self view] addSubview:scrollView_]; | |
282 [settingsText_ setFrame:headerFrame]; | |
283 [detailsText_ setFrame:subheaderFrame]; | |
284 [groupDropDownButton_ setFrame:dropDownButtonFrame]; | |
285 } | |
286 | |
287 - (void)setSettingsNotifier:(message_center::Notifier*)notifier | |
288 enabled:(BOOL)enabled { | |
289 provider_->SetNotifierEnabled(*notifier, enabled); | |
290 } | |
291 | |
292 - (void)learnMoreClicked:(message_center::Notifier*)notifier { | |
293 provider_->OnNotifierAdvancedSettingsRequested(notifier->notifier_id, NULL); | |
294 } | |
295 | |
296 // Testing API ///////////////////////////////////////////////////////////////// | |
297 | |
298 - (NSPopUpButton*)groupDropDownButton { | |
299 return groupDropDownButton_; | |
300 } | |
301 | |
302 - (NSScrollView*)scrollView { | |
303 return scrollView_; | |
304 } | |
305 | |
306 // Private API ///////////////////////////////////////////////////////////////// | |
307 | |
308 - (void)setIcon:(NSImage*)icon forNotifierIndex:(size_t)index { | |
309 MCSettingsEntryView* entry = [self entryForNotifierAtIndex:index]; | |
310 [entry setNotifierIcon:icon]; | |
311 } | |
312 | |
313 - (void)setIcon:(NSImage*)icon | |
314 forNotifierId:(const message_center::NotifierId&)id { | |
315 for (size_t i = 0; i < notifiers_.size(); ++i) { | |
316 if (notifiers_[i]->notifier_id == id) { | |
317 [self setIcon:icon forNotifierIndex:i]; | |
318 return; | |
319 } | |
320 } | |
321 } | |
322 | |
323 - (MCSettingsEntryView*)entryForNotifierAtIndex:(size_t)index { | |
324 NSArray* subviews = [[scrollView_ documentView] subviews]; | |
325 // The checkboxes are in bottom-top order, the checkbox for notifiers_[0] is | |
326 // last. | |
327 DCHECK_LT(notifiers_.size() - 1 - index, [subviews count]); | |
328 NSView* view = [subviews objectAtIndex:notifiers_.size() - 1 - index]; | |
329 return base::mac::ObjCCastStrict<MCSettingsEntryView>(view); | |
330 } | |
331 | |
332 - (void)notifierGroupSelectionChanged:(id)sender { | |
333 DCHECK_EQ(groupDropDownButton_.get(), sender); | |
334 NSPopUpButton* button = static_cast<NSPopUpButton*>(sender); | |
335 // The first item is a dummy item. | |
336 provider_->SwitchToNotifierGroup([button indexOfSelectedItem] - 1); | |
337 } | |
338 | |
339 - (BOOL)notifierHasAdvancedSettings:(const message_center::NotifierId&)id { | |
340 return provider_->NotifierHasAdvancedSettings(id); | |
341 } | |
342 | |
343 @end | |
OLD | NEW |