Index: chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm |
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm b/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm |
index 082272193c6c7d77aaf24a58495957bd80fced71..794e53d817e26e5ece5221438b11dbc224860004 100644 |
--- a/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm |
+++ b/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm |
@@ -5,40 +5,13 @@ |
#include "chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.h" |
#include "base/bind.h" |
-#include "base/mac/bundle_locations.h" |
-#include "base/mac/foundation_util.h" |
#include "base/mac/scoped_nsobject.h" |
#include "base/message_loop/message_loop.h" |
#include "base/strings/sys_string_conversions.h" |
#include "chrome/browser/ui/autofill/autofill_dialog_view_delegate.h" |
-#include "chrome/browser/ui/chrome_style.h" |
-#import "chrome/browser/ui/cocoa/autofill/autofill_account_chooser.h" |
#import "chrome/browser/ui/cocoa/autofill/autofill_details_container.h" |
-#include "chrome/browser/ui/cocoa/autofill/autofill_dialog_constants.h" |
-#import "chrome/browser/ui/cocoa/autofill/autofill_input_field.h" |
-#import "chrome/browser/ui/cocoa/autofill/autofill_main_container.h" |
-#import "chrome/browser/ui/cocoa/autofill/autofill_overlay_controller.h" |
-#import "chrome/browser/ui/cocoa/autofill/autofill_section_container.h" |
-#import "chrome/browser/ui/cocoa/autofill/autofill_sign_in_container.h" |
-#import "chrome/browser/ui/cocoa/autofill/autofill_textfield.h" |
+#import "chrome/browser/ui/cocoa/autofill/autofill_dialog_window_controller.h" |
#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h" |
-#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.h" |
-#include "content/public/browser/web_contents.h" |
-#include "content/public/browser/web_contents_view.h" |
-#include "grit/generated_resources.h" |
-#import "ui/base/cocoa/flipped_view.h" |
-#include "ui/base/cocoa/window_size_constants.h" |
-#include "ui/base/l10n/l10n_util.h" |
-#include "ui/gfx/platform_font.h" |
- |
-const CGFloat kAccountChooserHeight = 20.0; |
-const CGFloat kMinimumContentsHeight = 101; |
- |
-// Height of all decorations & paddings on main dialog together. |
-const CGFloat kDecorationHeight = kAccountChooserHeight + |
- autofill::kDetailVerticalPadding + |
- chrome_style::kClientBottomPadding + |
- chrome_style::kTitleTopPadding; |
namespace autofill { |
@@ -232,447 +205,3 @@ void AutofillDialogCocoa::OnConstrainedWindowClosed( |
} |
} // autofill |
- |
-#pragma mark "Loading" Shield |
- |
-@interface AutofillOpaqueView : NSView |
-@end |
- |
-@implementation AutofillOpaqueView |
- |
-- (BOOL)isOpaque { |
- return YES; |
-} |
- |
-- (void)drawRect:(NSRect)dirtyRect { |
- [[[self window] backgroundColor] setFill]; |
- [NSBezierPath fillRect:[self bounds]]; |
-} |
- |
-@end |
- |
- |
-#pragma mark Field Editor |
- |
-@interface AutofillDialogFieldEditor : NSTextView |
-@end |
- |
- |
-@implementation AutofillDialogFieldEditor |
- |
-- (void)mouseDown:(NSEvent*)event { |
- // Delegate _must_ be notified before mouseDown is complete, since it needs |
- // to distinguish between mouseDown for already focused fields, and fields |
- // that will receive focus as part of the mouseDown. |
- AutofillTextField* textfield = |
- base::mac::ObjCCastStrict<AutofillTextField>([self delegate]); |
- [textfield onEditorMouseDown:self]; |
- [super mouseDown:event]; |
-} |
- |
-@end |
- |
- |
-#pragma mark Window Controller |
- |
-@interface AutofillDialogWindowController () |
- |
-// Compute maximum allowed height for the dialog. |
-- (CGFloat)maxHeight; |
- |
-// Update size constraints on sign-in container. |
-- (void)updateSignInSizeConstraints; |
- |
-// Notification that the WebContent's view frame has changed. |
-- (void)onContentViewFrameDidChange:(NSNotification*)notification; |
- |
-@end |
- |
- |
-@implementation AutofillDialogWindowController (NSWindowDelegate) |
- |
-- (id)windowWillReturnFieldEditor:(NSWindow*)window toObject:(id)client { |
- AutofillTextField* textfield = base::mac::ObjCCast<AutofillTextField>(client); |
- if (!textfield) |
- return nil; |
- |
- if (!fieldEditor_) { |
- fieldEditor_.reset([[AutofillDialogFieldEditor alloc] init]); |
- [fieldEditor_ setFieldEditor:YES]; |
- } |
- return fieldEditor_.get(); |
-} |
- |
-@end |
- |
- |
-@implementation AutofillDialogWindowController |
- |
-- (id)initWithWebContents:(content::WebContents*)webContents |
- autofillDialog:(autofill::AutofillDialogCocoa*)autofillDialog { |
- DCHECK(webContents); |
- |
- base::scoped_nsobject<ConstrainedWindowCustomWindow> window( |
- [[ConstrainedWindowCustomWindow alloc] |
- initWithContentRect:ui::kWindowSizeDeterminedLater]); |
- |
- if ((self = [super initWithWindow:window])) { |
- [window setDelegate:self]; |
- webContents_ = webContents; |
- autofillDialog_ = autofillDialog; |
- |
- mainContainer_.reset([[AutofillMainContainer alloc] |
- initWithDelegate:autofillDialog->delegate()]); |
- [mainContainer_ setTarget:self]; |
- |
- signInContainer_.reset( |
- [[AutofillSignInContainer alloc] initWithDialog:autofillDialog]); |
- [[signInContainer_ view] setHidden:YES]; |
- |
- NSRect clientRect = [[mainContainer_ view] frame]; |
- clientRect.origin = NSMakePoint(chrome_style::kClientBottomPadding, |
- chrome_style::kHorizontalPadding); |
- [[mainContainer_ view] setFrame:clientRect]; |
- [[signInContainer_ view] setFrame:clientRect]; |
- |
- // Set dialog title. |
- titleTextField_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]); |
- [titleTextField_ setEditable:NO]; |
- [titleTextField_ setBordered:NO]; |
- [titleTextField_ setDrawsBackground:NO]; |
- [titleTextField_ setFont:[NSFont systemFontOfSize:15.0]]; |
- [titleTextField_ setStringValue: |
- base::SysUTF16ToNSString(autofillDialog->delegate()->DialogTitle())]; |
- [titleTextField_ sizeToFit]; |
- |
- NSRect headerRect = clientRect; |
- headerRect.size.height = kAccountChooserHeight; |
- headerRect.origin.y = NSMaxY(clientRect); |
- accountChooser_.reset([[AutofillAccountChooser alloc] |
- initWithFrame:headerRect |
- delegate:autofillDialog->delegate()]); |
- |
- loadingShieldTextField_.reset( |
- [[NSTextField alloc] initWithFrame:NSZeroRect]); |
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
- NSFont* loadingFont = rb.GetFont( |
- ui::ResourceBundle::BaseFont).DeriveFont(15).GetNativeFont(); |
- [loadingShieldTextField_ setFont:loadingFont]; |
- [loadingShieldTextField_ setEditable:NO]; |
- [loadingShieldTextField_ setBordered:NO]; |
- [loadingShieldTextField_ setDrawsBackground:NO]; |
- |
- base::scoped_nsobject<AutofillOpaqueView> loadingShieldView( |
- [[AutofillOpaqueView alloc] initWithFrame:NSZeroRect]); |
- [loadingShieldView setHidden:YES]; |
- [loadingShieldView addSubview:loadingShieldTextField_]; |
- |
- overlayController_.reset( |
- [[AutofillOverlayController alloc] initWithDelegate: |
- autofillDialog->delegate()]); |
- [[overlayController_ view] setHidden:YES]; |
- |
- // This needs a flipped content view because otherwise the size |
- // animation looks odd. However, replacing the contentView for constrained |
- // windows does not work - it does custom rendering. |
- base::scoped_nsobject<NSView> flippedContentView( |
- [[FlippedView alloc] initWithFrame: |
- [[[self window] contentView] frame]]); |
- [flippedContentView setSubviews: |
- @[accountChooser_, |
- titleTextField_, |
- [mainContainer_ view], |
- [signInContainer_ view], |
- loadingShieldView, |
- [overlayController_ view]]]; |
- [flippedContentView setAutoresizingMask: |
- (NSViewWidthSizable | NSViewHeightSizable)]; |
- [[[self window] contentView] addSubview:flippedContentView]; |
- [mainContainer_ setAnchorView:[[accountChooser_ subviews] objectAtIndex:1]]; |
- } |
- return self; |
-} |
- |
-- (void)dealloc { |
- [[NSNotificationCenter defaultCenter] removeObserver:self]; |
- [super dealloc]; |
-} |
- |
-- (CGFloat)maxHeight { |
- NSRect dialogFrameRect = [[self window] frame]; |
- NSRect browserFrameRect = |
- [webContents_->GetView()->GetTopLevelNativeWindow() frame]; |
- dialogFrameRect.size.height = |
- NSMaxY(dialogFrameRect) - NSMinY(browserFrameRect); |
- dialogFrameRect = [[self window] contentRectForFrameRect:dialogFrameRect]; |
- return NSHeight(dialogFrameRect); |
-} |
- |
-- (void)updateSignInSizeConstraints { |
- // Adjust for the size of all decorations and paddings outside main content. |
- CGFloat minHeight = kMinimumContentsHeight - kDecorationHeight; |
- CGFloat maxHeight = std::max([self maxHeight] - kDecorationHeight, minHeight); |
- CGFloat width = NSWidth([[[self window] contentView] frame]); |
- |
- [signInContainer_ constrainSizeToMinimum:NSMakeSize(width, minHeight) |
- maximum:NSMakeSize(width, maxHeight)]; |
-} |
- |
-- (void)onContentViewFrameDidChange:(NSNotification*)notification { |
- [self updateSignInSizeConstraints]; |
- if ([[signInContainer_ view] isHidden]) |
- [self requestRelayout]; |
-} |
- |
-- (void)cancelRelayout { |
- [NSObject cancelPreviousPerformRequestsWithTarget:self |
- selector:@selector(performLayout) |
- object:nil]; |
-} |
- |
-- (void)requestRelayout { |
- [self cancelRelayout]; |
- [self performSelector:@selector(performLayout) withObject:nil afterDelay:0.0]; |
-} |
- |
-- (NSSize)preferredSize { |
- NSSize size; |
- |
- // Overall size is determined by either main container or sign in view. |
- if ([[signInContainer_ view] isHidden]) |
- size = [mainContainer_ preferredSize]; |
- else |
- size = [signInContainer_ preferredSize]; |
- |
- // Always make room for the header. |
- size.height += kDecorationHeight; |
- |
- if (![[overlayController_ view] isHidden]) { |
- CGFloat height = [overlayController_ heightForWidth:size.width]; |
- if (height != 0.0) |
- size.height = height; |
- } |
- |
- // Show as much of the main view as is possible without going past the |
- // bottom of the browser window. |
- size.height = std::min(size.height, [self maxHeight]); |
- |
- return size; |
-} |
- |
-- (void)performLayout { |
- NSRect contentRect = NSZeroRect; |
- contentRect.size = [self preferredSize]; |
- NSRect clientRect = contentRect; |
- clientRect.origin.y = chrome_style::kClientBottomPadding; |
- clientRect.size.height -= chrome_style::kTitleTopPadding + |
- chrome_style::kClientBottomPadding; |
- |
- [titleTextField_ setStringValue: |
- base::SysUTF16ToNSString(autofillDialog_->delegate()->DialogTitle())]; |
- [titleTextField_ sizeToFit]; |
- |
- NSRect headerRect, mainRect, titleRect, dummyRect; |
- NSDivideRect(clientRect, &headerRect, &mainRect, |
- kAccountChooserHeight, NSMinYEdge); |
- NSDivideRect(mainRect, &dummyRect, &mainRect, |
- autofill::kDetailVerticalPadding, NSMinYEdge); |
- headerRect = NSInsetRect(headerRect, chrome_style::kHorizontalPadding, 0); |
- NSDivideRect(headerRect, &titleRect, &headerRect, |
- NSWidth([titleTextField_ frame]), NSMinXEdge); |
- |
- // Align baseline of title with bottom of accountChooser. |
- base::scoped_nsobject<NSLayoutManager> layout_manager( |
- [[NSLayoutManager alloc] init]); |
- NSFont* titleFont = [titleTextField_ font]; |
- titleRect.origin.y += NSHeight(titleRect) - |
- [layout_manager defaultBaselineOffsetForFont:titleFont]; |
- [titleTextField_ setFrame:titleRect]; |
- |
- [accountChooser_ setFrame:headerRect]; |
- [accountChooser_ performLayout]; |
- if ([[signInContainer_ view] isHidden]) { |
- [[mainContainer_ view] setFrame:mainRect]; |
- [mainContainer_ performLayout]; |
- } else { |
- [[signInContainer_ view] setFrame:mainRect]; |
- } |
- |
- // Loading shield has text centered in the content rect. |
- NSRect textFrame = [loadingShieldTextField_ frame]; |
- textFrame.origin.x = |
- std::ceil((NSWidth(contentRect) - NSWidth(textFrame)) / 2.0); |
- textFrame.origin.y = |
- std::ceil((NSHeight(contentRect) - NSHeight(textFrame)) / 2.0); |
- [loadingShieldTextField_ setFrame:textFrame]; |
- [[loadingShieldTextField_ superview] setFrame:contentRect]; |
- |
- [[overlayController_ view] setFrame:contentRect]; |
- [overlayController_ performLayout]; |
- |
- NSRect frameRect = [[self window] frameRectForContentRect:contentRect]; |
- [[self window] setFrame:frameRect display:YES]; |
- [[self window] recalculateKeyViewLoop]; |
-} |
- |
-- (IBAction)accept:(id)sender { |
- if ([mainContainer_ validate]) |
- autofillDialog_->delegate()->OnAccept(); |
- else |
- [mainContainer_ makeFirstInvalidInputFirstResponder]; |
-} |
- |
-- (IBAction)cancel:(id)sender { |
- autofillDialog_->delegate()->OnCancel(); |
- autofillDialog_->PerformClose(); |
-} |
- |
-- (void)show { |
- // Resizing the browser causes the ConstrainedWindow to move. |
- // Observe that to allow resizes based on browser size. |
- // NOTE: This MUST come last after all initial setup is done, because there |
- // is an immediate notification post registration. |
- DCHECK([self window]); |
- [[NSNotificationCenter defaultCenter] |
- addObserver:self |
- selector:@selector(onContentViewFrameDidChange:) |
- name:NSWindowDidMoveNotification |
- object:[self window]]; |
- |
- [self updateAccountChooser]; |
- [self updateNotificationArea]; |
- [self requestRelayout]; |
-} |
- |
-- (void)hide { |
- autofillDialog_->delegate()->OnCancel(); |
- autofillDialog_->PerformClose(); |
-} |
- |
-- (void)updateNotificationArea { |
- [mainContainer_ updateNotificationArea]; |
-} |
- |
-- (void)updateAccountChooser { |
- [accountChooser_ update]; |
- [mainContainer_ updateLegalDocuments]; |
- |
- NSString* newLoadingMessage = @""; |
- if (autofillDialog_->delegate()->ShouldShowSpinner()) |
- newLoadingMessage = l10n_util::GetNSStringWithFixup(IDS_TAB_LOADING_TITLE); |
- if (![newLoadingMessage isEqualToString: |
- [loadingShieldTextField_ stringValue]]) { |
- NSView* loadingShieldView = [loadingShieldTextField_ superview]; |
- [loadingShieldTextField_ setStringValue:newLoadingMessage]; |
- [loadingShieldTextField_ sizeToFit]; |
- |
- BOOL showShield = ([newLoadingMessage length] != 0); |
- |
- // For the duration of the loading shield, hide the main contents. |
- // This prevents the currently focused text field "shining through". |
- // No need to remember previous state, because the loading shield |
- // always flows through to the main container. |
- [[mainContainer_ view] setHidden:showShield]; |
- [loadingShieldView setHidden:!showShield]; |
- [self requestRelayout]; |
- } |
-} |
- |
-- (void)updateButtonStrip { |
- [overlayController_ updateState]; |
-} |
- |
-- (void)updateSection:(autofill::DialogSection)section { |
- [[mainContainer_ sectionForId:section] update]; |
- [mainContainer_ updateSaveInChrome]; |
-} |
- |
-- (void)fillSection:(autofill::DialogSection)section |
- forInput:(const autofill::DetailInput&)input { |
- [[mainContainer_ sectionForId:section] fillForInput:input]; |
- [mainContainer_ updateSaveInChrome]; |
-} |
- |
-- (content::NavigationController*)showSignIn { |
- [self updateSignInSizeConstraints]; |
- [signInContainer_ loadSignInPage]; |
- [[mainContainer_ view] setHidden:YES]; |
- [[signInContainer_ view] setHidden:NO]; |
- [self requestRelayout]; |
- |
- return [signInContainer_ navigationController]; |
-} |
- |
-- (void)getInputs:(autofill::DetailOutputMap*)output |
- forSection:(autofill::DialogSection)section { |
- [[mainContainer_ sectionForId:section] getInputs:output]; |
-} |
- |
-- (NSString*)getCvc { |
- autofill::DialogSection section = autofill::SECTION_CC; |
- NSString* value = [[mainContainer_ sectionForId:section] suggestionText]; |
- if (!value) { |
- section = autofill::SECTION_CC_BILLING; |
- value = [[mainContainer_ sectionForId:section] suggestionText]; |
- } |
- return value; |
-} |
- |
-- (BOOL)saveDetailsLocally { |
- return [mainContainer_ saveDetailsLocally]; |
-} |
- |
-- (void)hideSignIn { |
- [[signInContainer_ view] setHidden:YES]; |
- [[mainContainer_ view] setHidden:NO]; |
- [self requestRelayout]; |
-} |
- |
-- (void)modelChanged { |
- [mainContainer_ modelChanged]; |
-} |
- |
-- (void)updateErrorBubble { |
- [mainContainer_ updateErrorBubble]; |
-} |
- |
-- (void)onSignInResize:(NSSize)size { |
- [signInContainer_ setPreferredSize:size]; |
- [self requestRelayout]; |
-} |
- |
-@end |
- |
- |
-@implementation AutofillDialogWindowController (TestableAutofillDialogView) |
- |
-- (void)setTextContents:(NSString*)text |
- forInput:(const autofill::DetailInput&)input { |
- for (size_t i = autofill::SECTION_MIN; i <= autofill::SECTION_MAX; ++i) { |
- autofill::DialogSection section = static_cast<autofill::DialogSection>(i); |
- // TODO(groby): Need to find the section for an input directly - wasteful. |
- [[mainContainer_ sectionForId:section] setFieldValue:text forInput:input]; |
- } |
-} |
- |
-- (void)setTextContents:(NSString*)text |
- ofSuggestionForSection:(autofill::DialogSection)section { |
- [[mainContainer_ sectionForId:section] setSuggestionFieldValue:text]; |
-} |
- |
-- (void)activateFieldForInput:(const autofill::DetailInput&)input { |
- for (size_t i = autofill::SECTION_MIN; i <= autofill::SECTION_MAX; ++i) { |
- autofill::DialogSection section = static_cast<autofill::DialogSection>(i); |
- [[mainContainer_ sectionForId:section] activateFieldForInput:input]; |
- } |
-} |
- |
-- (content::WebContents*)getSignInWebContents { |
- return [signInContainer_ webContents]; |
-} |
- |
-- (BOOL)IsShowingOverlay { |
- return ![[overlayController_ view] isHidden]; |
-} |
- |
-@end |