Cleanup: Update the path to insets and point headers.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / one_click_signin_view_controller.mm
blob26c7c4eb5e68e5ff7c6c18b0e42f4dad80f31022
1 // Copyright (c) 2012 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.
5 #import "chrome/browser/ui/cocoa/one_click_signin_view_controller.h"
7 #include "base/callback_helpers.h"
8 #include "base/logging.h"
9 #include "base/mac/bundle_locations.h"
10 #import "chrome/browser/ui/chrome_style.h"
11 #include "chrome/browser/ui/sync/one_click_signin_helper.h"
12 #include "chrome/common/url_constants.h"
13 #include "chrome/grit/chromium_strings.h"
14 #include "chrome/grit/generated_resources.h"
15 #include "components/signin/core/browser/signin_metrics.h"
16 #include "content/public/browser/web_contents.h"
17 #include "grit/components_strings.h"
18 #include "skia/ext/skia_utils_mac.h"
19 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h"
20 #import "ui/base/cocoa/controls/hyperlink_text_view.h"
21 #include "ui/base/l10n/l10n_util_mac.h"
23 namespace {
25 // The margin between the top edge of the border and the error message text in
26 // the sign-in bubble, in the case of an error.
27 const CGFloat kTopErrorMessageMargin = 12;
29 // Shift the origin of |view|'s frame by the given amount in the
30 // positive y direction (up).
31 void ShiftOriginY(NSView* view, CGFloat amount) {
32   NSPoint origin = [view frame].origin;
33   origin.y += amount;
34   [view setFrameOrigin:origin];
37 }  // namespace
39 @interface OneClickSigninViewController ()
40 - (CGFloat)initializeInformativeTextView;
41 - (void)close;
42 @end
44 @implementation OneClickSigninViewController
47 - (id)initWithNibName:(NSString*)nibName
48           webContents:(content::WebContents*)webContents
49          syncCallback:(const BrowserWindow::StartSyncCallback&)syncCallback
50         closeCallback:(const base::Closure&)closeCallback
51          isSyncDialog:(BOOL)isSyncDialog
52                 email:(const base::string16&)email
53          errorMessage:(NSString*)errorMessage {
54   if ((self = [super initWithNibName:nibName
55                               bundle:base::mac::FrameworkBundle()])) {
56     webContents_ = webContents;
57     startSyncCallback_ = syncCallback;
58     closeCallback_ = closeCallback;
59     isSyncDialog_ = isSyncDialog;
60     clickedLearnMore_ = NO;
61     email_ = email;
62     errorMessage_.reset([errorMessage retain]);
63     if (isSyncDialog_)
64       DCHECK(!startSyncCallback_.is_null());
65   }
66   return self;
69 - (void)viewWillClose {
70   // This is usually called after a click handler has initiated sync
71   // and has reset the callback. However, in the case that we are closing
72   // the window and nothing else has initiated the sync, we must do so here
73   if (isSyncDialog_ && !startSyncCallback_.is_null()) {
74     base::ResetAndReturn(&startSyncCallback_).Run(
75         OneClickSigninSyncStarter::UNDO_SYNC);
76   }
79 - (IBAction)ok:(id)sender {
80   if (isSyncDialog_) {
81     OneClickSigninHelper::LogConfirmHistogramValue(
82         clickedLearnMore_ ?
83             signin_metrics::HISTOGRAM_CONFIRM_LEARN_MORE_OK :
84             signin_metrics::HISTOGRAM_CONFIRM_OK);
86     base::ResetAndReturn(&startSyncCallback_).Run(
87       OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS);
88   }
89   [self close];
92 - (IBAction)onClickUndo:(id)sender {
93   if (isSyncDialog_) {
94     OneClickSigninHelper::LogConfirmHistogramValue(
95         clickedLearnMore_ ?
96             signin_metrics::HISTOGRAM_CONFIRM_LEARN_MORE_UNDO :
97             signin_metrics::HISTOGRAM_CONFIRM_UNDO);
99     base::ResetAndReturn(&startSyncCallback_).Run(
100       OneClickSigninSyncStarter::UNDO_SYNC);
101   }
102   [self close];
105 - (IBAction)onClickAdvancedLink:(id)sender {
106   if (isSyncDialog_) {
107     OneClickSigninHelper::LogConfirmHistogramValue(
108         clickedLearnMore_ ?
109             signin_metrics::HISTOGRAM_CONFIRM_LEARN_MORE_ADVANCED :
110             signin_metrics::HISTOGRAM_CONFIRM_ADVANCED);
112     base::ResetAndReturn(&startSyncCallback_).Run(
113         OneClickSigninSyncStarter::CONFIGURE_SYNC_FIRST);
114   }
115   else {
116     content::OpenURLParams params(GURL(chrome::kChromeUISettingsURL),
117                                   content::Referrer(), CURRENT_TAB,
118                                   ui::PAGE_TRANSITION_LINK, false);
119     webContents_->OpenURL(params);
120   }
121   [self close];
124 - (IBAction)onClickClose:(id)sender {
125   if (isSyncDialog_) {
126     OneClickSigninHelper::LogConfirmHistogramValue(
127         clickedLearnMore_ ?
128             signin_metrics::HISTOGRAM_CONFIRM_LEARN_MORE_CLOSE :
129             signin_metrics::HISTOGRAM_CONFIRM_CLOSE);
131     base::ResetAndReturn(&startSyncCallback_).Run(
132         OneClickSigninSyncStarter::UNDO_SYNC);
133   }
134   [self close];
137 - (void)awakeFromNib {
138   // Lay out the text controls from the bottom up.
139   CGFloat totalYOffset = 0.0;
141   if ([errorMessage_ length] == 0) {
142     totalYOffset +=
143         [GTMUILocalizerAndLayoutTweaker sizeToFitView:advancedLink_].height;
144     [[advancedLink_ cell] setTextColor:
145         gfx::SkColorToCalibratedNSColor(chrome_style::GetLinkColor())];
146   } else {
147     // Don't display the advanced link for the error bubble.
148     // To align the Learn More link with the OK button, we need to offset by
149     // the height of the Advanced link, plus the padding between it and the
150     // Learn More link above.
151     float advancedLinkHeightPlusPadding =
152         [informativePlaceholderTextField_ frame].origin.y -
153         [advancedLink_ frame].origin.y;
155     totalYOffset -= advancedLinkHeightPlusPadding;
156     [advancedLink_ removeFromSuperview];
157   }
159   if (informativePlaceholderTextField_) {
160     if (!isSyncDialog_ && ([errorMessage_ length] != 0)) {
161       // Move up the "Learn more" origin in error case to account for the
162       // smaller bubble.
163       NSRect frame = [informativePlaceholderTextField_ frame];
164       frame = NSOffsetRect(frame, 0, NSHeight([titleTextField_ frame]));
165       [informativePlaceholderTextField_ setFrame:frame];
166     }
168     ShiftOriginY(informativePlaceholderTextField_, totalYOffset);
169     totalYOffset += [self initializeInformativeTextView];
170   }
172   ShiftOriginY(messageTextField_, totalYOffset);
173   totalYOffset +=
174       [GTMUILocalizerAndLayoutTweaker
175           sizeToFitFixedWidthTextField:messageTextField_];
177   ShiftOriginY(titleTextField_, totalYOffset);
178   totalYOffset +=
179       [GTMUILocalizerAndLayoutTweaker
180           sizeToFitFixedWidthTextField:titleTextField_];
182   NSSize delta = NSMakeSize(0.0, totalYOffset);
184   if (isSyncDialog_) {
185     [messageTextField_ setStringValue:l10n_util::GetNSStringWithFixup(
186         IDS_ONE_CLICK_SIGNIN_DIALOG_TITLE_NEW)];
187   } else if ([errorMessage_ length] != 0) {
188     [titleTextField_ setHidden:YES];
189     [messageTextField_ setStringValue:errorMessage_];
191     // Make the bubble less tall, as the title text will be hidden.
192     NSSize size = [[self view] frame].size;
193     size.height = size.height - NSHeight([titleTextField_ frame]);
194     [[self view] setFrameSize:size];
196     // Shift the message text up to where the title text used to be.
197     NSPoint origin = [titleTextField_ frame].origin;
198     [messageTextField_ setFrameOrigin:origin];
199     ShiftOriginY(messageTextField_, -kTopErrorMessageMargin);
201     // Use "OK" instead of "OK, got it" in the error case, and size the button
202     // accordingly.
203     [closeButton_ setTitle:l10n_util::GetNSStringWithFixup(
204         IDS_OK)];
205     [GTMUILocalizerAndLayoutTweaker sizeToFitView:[closeButton_ superview]];
206   }
208   // Resize bubble and window to hold the controls.
209   [GTMUILocalizerAndLayoutTweaker
210       resizeViewWithoutAutoResizingSubViews:[self view]
211                                       delta:delta];
213   if (isSyncDialog_) {
214     OneClickSigninHelper::LogConfirmHistogramValue(
215         signin_metrics::HISTOGRAM_CONFIRM_SHOWN);
216   }
219 - (CGFloat)initializeInformativeTextView {
220   NSRect oldFrame = [informativePlaceholderTextField_ frame];
222   // Replace the placeholder NSTextField with the real label NSTextView. The
223   // former doesn't show links in a nice way, but the latter can't be added in
224   // a xib without a containing scroll view, so create the NSTextView
225   // programmatically.
226   informativeTextView_.reset(
227       [[HyperlinkTextView alloc] initWithFrame:oldFrame]);
228   [informativeTextView_.get() setAutoresizingMask:
229       [informativePlaceholderTextField_ autoresizingMask]];
230   [informativeTextView_.get() setDelegate:self];
232   // Set the text.
233   NSString* learnMoreText = l10n_util::GetNSStringWithFixup(IDS_LEARN_MORE);
234   NSString* messageText;
236   ui::ResourceBundle::FontStyle fontStyle = isSyncDialog_ ?
237       chrome_style::kTextFontStyle : ui::ResourceBundle::SmallFont;
238   NSFont* font = ui::ResourceBundle::GetSharedInstance().GetFont(
239       fontStyle).GetNativeFont();
241   // The non-modal bubble already has a text content and only needs the
242   // Learn More link (in a smaller font).
243   if (isSyncDialog_) {
244     messageText = l10n_util::GetNSStringFWithFixup(
245         IDS_ONE_CLICK_SIGNIN_DIALOG_MESSAGE_NEW, email_);
246     messageText = [messageText stringByAppendingString:@" "];
247   } else {
248     messageText = @"";
249   }
251   NSColor* linkColor =
252       gfx::SkColorToCalibratedNSColor(chrome_style::GetLinkColor());
253   [informativeTextView_ setMessageAndLink:messageText
254                                  withLink:learnMoreText
255                                  atOffset:[messageText length]
256                                      font:font
257                              messageColor:[NSColor blackColor]
258                                 linkColor:linkColor];
261   // Make the "Advanced" link font as large as the "Learn More" link.
262   [[advancedLink_ cell] setFont:font];
263   [advancedLink_ sizeToFit];
265   // Size to fit.
266   [[informativePlaceholderTextField_ cell] setAttributedStringValue:
267       [informativeTextView_ attributedString]];
268   [GTMUILocalizerAndLayoutTweaker
269         sizeToFitFixedWidthTextField:informativePlaceholderTextField_];
270   NSRect newFrame = [informativePlaceholderTextField_ frame];
271   [informativeTextView_ setFrame:newFrame];
273   // Swap placeholder.
274   [[informativePlaceholderTextField_ superview]
275      replaceSubview:informativePlaceholderTextField_
276                with:informativeTextView_.get()];
277   informativePlaceholderTextField_ = nil;  // Now released.
279   return NSHeight(newFrame) - NSHeight(oldFrame);
282 - (BOOL)textView:(NSTextView*)textView
283    clickedOnLink:(id)link
284          atIndex:(NSUInteger)charIndex {
285   if (isSyncDialog_ && !clickedLearnMore_) {
286     clickedLearnMore_ = YES;
288     OneClickSigninHelper::LogConfirmHistogramValue(
289         signin_metrics::HISTOGRAM_CONFIRM_LEARN_MORE);
290   }
291   WindowOpenDisposition location = isSyncDialog_ ?
292                                    NEW_WINDOW : NEW_FOREGROUND_TAB;
293   content::OpenURLParams params(GURL(chrome::kChromeSyncLearnMoreURL),
294                                 content::Referrer(), location,
295                                 ui::PAGE_TRANSITION_LINK, false);
296   webContents_->OpenURL(params);
297   return YES;
300 - (void)close {
301   base::ResetAndReturn(&closeCallback_).Run();
304 @end