| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/ui/cocoa/autofill/save_card_bubble_view_bridge.h" | 5 #import "chrome/browser/ui/cocoa/autofill/save_card_bubble_view_bridge.h" |
| 6 | 6 |
| 7 #include "base/strings/sys_string_conversions.h" | 7 #include "base/strings/sys_string_conversions.h" |
| 8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
| 9 #include "chrome/browser/ui/autofill/save_card_bubble_controller.h" | 9 #include "chrome/browser/ui/autofill/save_card_bubble_controller.h" |
| 10 #include "chrome/browser/ui/chrome_style.h" | 10 #include "chrome/browser/ui/chrome_style.h" |
| 11 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | 11 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
| 12 #import "chrome/browser/ui/cocoa/info_bubble_view.h" |
| 12 #import "chrome/browser/ui/cocoa/info_bubble_window.h" | 13 #import "chrome/browser/ui/cocoa/info_bubble_window.h" |
| 13 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h" | 14 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h" |
| 14 #include "grit/components_strings.h" | 15 #include "grit/components_strings.h" |
| 15 #include "skia/ext/skia_utils_mac.h" | 16 #include "skia/ext/skia_utils_mac.h" |
| 16 #import "ui/base/cocoa/controls/hyperlink_text_view.h" | 17 #import "ui/base/cocoa/controls/hyperlink_text_view.h" |
| 17 #import "ui/base/cocoa/window_size_constants.h" | 18 #import "ui/base/cocoa/window_size_constants.h" |
| 18 #include "ui/base/l10n/l10n_util.h" | 19 #include "ui/base/l10n/l10n_util.h" |
| 19 #include "ui/base/resource/resource_bundle.h" | 20 #include "ui/base/resource/resource_bundle.h" |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 22 | 23 |
| 23 const CGFloat kDesiredBubbleWidth = 370; | 24 const CGFloat kDesiredBubbleWidth = 370; |
| 25 const CGFloat kDividerHeight = 1; |
| 24 const CGFloat kFramePadding = 16; | 26 const CGFloat kFramePadding = 16; |
| 25 const CGFloat kRelatedControlHorizontalPadding = 2; | 27 const CGFloat kRelatedControlHorizontalPadding = 2; |
| 28 const CGFloat kRelatedControlVerticalPadding = 5; |
| 26 const CGFloat kUnrelatedControlVerticalPadding = 15; | 29 const CGFloat kUnrelatedControlVerticalPadding = 15; |
| 27 | 30 |
| 28 const SkColor kIconBorderColor = 0x10000000; // SkColorSetARGB(10, 0, 0, 0); | 31 const SkColor kDividerColor = 0xFFE9E9E9; // SkColorSetRGB(0xE9, 0xE9, 0xE9); |
| 32 const SkColor kFooterColor = 0xFFF5F5F5; // SkColorSetRGB(0xF5, 0xF5, 0xF5); |
| 33 const SkColor kIconBorderColor = 0x10000000; // SkColorSetARGB(0x10, 0, 0, 0); |
| 34 |
| 29 } | 35 } |
| 30 | 36 |
| 31 namespace autofill { | 37 namespace autofill { |
| 32 | 38 |
| 33 #pragma mark SaveCardBubbleViewBridge | 39 #pragma mark SaveCardBubbleViewBridge |
| 34 | 40 |
| 35 SaveCardBubbleViewBridge::SaveCardBubbleViewBridge( | 41 SaveCardBubbleViewBridge::SaveCardBubbleViewBridge( |
| 36 SaveCardBubbleController* controller, | 42 SaveCardBubbleController* controller, |
| 37 BrowserWindowController* browser_window_controller) | 43 BrowserWindowController* browser_window_controller) |
| 38 : controller_(controller) { | 44 : controller_(controller) { |
| 39 view_controller_ = [[SaveCardBubbleViewCocoa alloc] | 45 view_controller_ = [[SaveCardBubbleViewCocoa alloc] |
| 40 initWithBrowserWindowController:browser_window_controller | 46 initWithBrowserWindowController:browser_window_controller |
| 41 bridge:this]; | 47 bridge:this]; |
| 42 DCHECK(view_controller_); | 48 DCHECK(view_controller_); |
| 43 [view_controller_ showWindow:nil]; | 49 [view_controller_ showWindow:nil]; |
| 44 } | 50 } |
| 45 | 51 |
| 46 SaveCardBubbleViewBridge::~SaveCardBubbleViewBridge() {} | 52 SaveCardBubbleViewBridge::~SaveCardBubbleViewBridge() {} |
| 47 | 53 |
| 48 base::string16 SaveCardBubbleViewBridge::GetWindowTitle() const { | 54 base::string16 SaveCardBubbleViewBridge::GetWindowTitle() const { |
| 49 return controller_ ? controller_->GetWindowTitle() : base::string16(); | 55 return controller_ ? controller_->GetWindowTitle() : base::string16(); |
| 50 } | 56 } |
| 51 | 57 |
| 58 base::string16 SaveCardBubbleViewBridge::GetExplanatoryMessage() const { |
| 59 return controller_ ? controller_->GetExplanatoryMessage() : base::string16(); |
| 60 } |
| 61 |
| 52 CreditCard SaveCardBubbleViewBridge::GetCard() const { | 62 CreditCard SaveCardBubbleViewBridge::GetCard() const { |
| 53 return controller_ ? controller_->GetCard() : CreditCard(); | 63 return controller_ ? controller_->GetCard() : CreditCard(); |
| 54 } | 64 } |
| 55 | 65 |
| 66 const LegalMessageLines SaveCardBubbleViewBridge::GetLegalMessageLines() const { |
| 67 return controller_ ? controller_->GetLegalMessageLines() |
| 68 : LegalMessageLines(); |
| 69 } |
| 70 |
| 56 void SaveCardBubbleViewBridge::OnSaveButton() { | 71 void SaveCardBubbleViewBridge::OnSaveButton() { |
| 57 if (controller_) | 72 if (controller_) |
| 58 controller_->OnSaveButton(); | 73 controller_->OnSaveButton(); |
| 59 Hide(); | 74 Hide(); |
| 60 } | 75 } |
| 61 | 76 |
| 62 void SaveCardBubbleViewBridge::OnCancelButton() { | 77 void SaveCardBubbleViewBridge::OnCancelButton() { |
| 63 if (controller_) | 78 if (controller_) |
| 64 controller_->OnCancelButton(); | 79 controller_->OnCancelButton(); |
| 65 Hide(); | 80 Hide(); |
| 66 } | 81 } |
| 67 | 82 |
| 68 void SaveCardBubbleViewBridge::OnLearnMoreClicked() { | 83 void SaveCardBubbleViewBridge::OnLearnMoreClicked() { |
| 69 if (controller_) | 84 if (controller_) |
| 70 controller_->OnLearnMoreClicked(); | 85 controller_->OnLearnMoreClicked(); |
| 71 } | 86 } |
| 72 | 87 |
| 88 void SaveCardBubbleViewBridge::OnLegalMessageLinkClicked(const GURL& url) { |
| 89 if (controller_) |
| 90 controller_->OnLegalMessageLinkClicked(url); |
| 91 } |
| 92 |
| 73 void SaveCardBubbleViewBridge::OnBubbleClosed() { | 93 void SaveCardBubbleViewBridge::OnBubbleClosed() { |
| 74 if (controller_) | 94 if (controller_) |
| 75 controller_->OnBubbleClosed(); | 95 controller_->OnBubbleClosed(); |
| 76 | 96 |
| 77 delete this; | 97 delete this; |
| 78 } | 98 } |
| 79 | 99 |
| 80 void SaveCardBubbleViewBridge::Hide() { | 100 void SaveCardBubbleViewBridge::Hide() { |
| 81 // SaveCardBubbleViewBridge::OnBubbleClosed won't be able to call | 101 // SaveCardBubbleViewBridge::OnBubbleClosed won't be able to call |
| 82 // OnBubbleClosed on the bubble controller since we null the reference to it | 102 // OnBubbleClosed on the bubble controller since we null the reference to it |
| 83 // below. So we need to call it here. | 103 // below. So we need to call it here. |
| 84 controller_->OnBubbleClosed(); | 104 controller_->OnBubbleClosed(); |
| 85 controller_ = nullptr; | 105 controller_ = nullptr; |
| 86 [view_controller_ close]; | 106 [view_controller_ close]; |
| 87 } | 107 } |
| 88 | 108 |
| 89 } // autofill | 109 } // autofill |
| 90 | 110 |
| 91 #pragma mark SaveCardBubbleViewCocoa | 111 #pragma mark SaveCardBubbleViewCocoa |
| 92 | 112 |
| 93 @interface SaveCardBubbleViewCocoa () | 113 @interface SaveCardBubbleViewCocoa () |
| 94 + (base::scoped_nsobject<NSTextField>)makeTextField; | 114 + (base::scoped_nsobject<NSTextField>)makeLabel:(NSString*)text; |
| 95 + (base::scoped_nsobject<NSButton>)makeButton; | 115 + (base::scoped_nsobject<NSTextView>)makeWrappingLabel:(NSString*)text |
| 116 withFontSize:(CGFloat)fontSize; |
| 117 + (base::scoped_nsobject<HyperlinkTextView>)makeHyperlinkText:(NSString*)text; |
| 118 + (base::scoped_nsobject<NSButton>)makeButton:(NSString*)text; |
| 96 @end | 119 @end |
| 97 | 120 |
| 98 @implementation SaveCardBubbleViewCocoa { | 121 @implementation SaveCardBubbleViewCocoa { |
| 99 autofill::SaveCardBubbleViewBridge* bridge_; // Weak. | 122 autofill::SaveCardBubbleViewBridge* bridge_; // Weak. |
| 100 } | 123 } |
| 101 | 124 |
| 102 + (base::scoped_nsobject<NSTextField>)makeTextField { | 125 + (base::scoped_nsobject<NSTextField>)makeLabel:(NSString*)text { |
| 103 base::scoped_nsobject<NSTextField> textField( | 126 base::scoped_nsobject<NSTextField> textField( |
| 104 [[NSTextField alloc] initWithFrame:NSZeroRect]); | 127 [[NSTextField alloc] initWithFrame:NSZeroRect]); |
| 105 [textField setEditable:NO]; | 128 [textField setEditable:NO]; |
| 106 [textField setSelectable:NO]; | 129 [textField setSelectable:NO]; |
| 107 [textField setDrawsBackground:NO]; | 130 [textField setDrawsBackground:NO]; |
| 108 [textField setBezeled:NO]; | 131 [textField setBezeled:NO]; |
| 132 [textField setStringValue:text]; |
| 133 [textField sizeToFit]; |
| 109 | 134 |
| 110 return textField; | 135 return textField; |
| 111 } | 136 } |
| 112 | 137 |
| 113 + (base::scoped_nsobject<NSButton>)makeButton { | 138 + (base::scoped_nsobject<NSTextView>)makeWrappingLabel:(NSString*)text |
| 139 withFontSize:(CGFloat)fontSize { |
| 140 base::scoped_nsobject<NSTextView> textView( |
| 141 [[NSTextView alloc] initWithFrame:NSZeroRect]); |
| 142 NSDictionary* attributes = |
| 143 @{NSFontAttributeName : [NSFont systemFontOfSize:fontSize]}; |
| 144 base::scoped_nsobject<NSAttributedString> attributedMessage( |
| 145 [[NSAttributedString alloc] initWithString:text attributes:attributes]); |
| 146 [[textView textStorage] setAttributedString:attributedMessage]; |
| 147 [[textView textContainer] setLineFragmentPadding:0.0f]; |
| 148 [textView setEditable:NO]; |
| 149 [textView setSelectable:NO]; |
| 150 [textView setDrawsBackground:NO]; |
| 151 [textView setVerticallyResizable:YES]; |
| 152 [textView setFrameSize:NSMakeSize(kDesiredBubbleWidth - (2 * kFramePadding), |
| 153 MAXFLOAT)]; |
| 154 [textView sizeToFit]; |
| 155 |
| 156 return textView; |
| 157 } |
| 158 |
| 159 + (base::scoped_nsobject<HyperlinkTextView>)makeHyperlinkText:(NSString*)text { |
| 160 base::scoped_nsobject<HyperlinkTextView> lineView( |
| 161 [[HyperlinkTextView alloc] initWithFrame:NSZeroRect]); |
| 162 [lineView setMessage:text |
| 163 withFont:[NSFont systemFontOfSize:[NSFont systemFontSize]] |
| 164 messageColor:[NSColor blackColor]]; |
| 165 |
| 166 [[lineView textContainer] setLineFragmentPadding:0.0f]; |
| 167 [lineView setVerticallyResizable:YES]; |
| 168 [lineView setFrameSize:NSMakeSize(kDesiredBubbleWidth - 2 * kFramePadding, |
| 169 MAXFLOAT)]; |
| 170 [lineView sizeToFit]; |
| 171 |
| 172 return lineView; |
| 173 } |
| 174 |
| 175 + (base::scoped_nsobject<NSButton>)makeButton:(NSString*)text { |
| 114 base::scoped_nsobject<NSButton> button( | 176 base::scoped_nsobject<NSButton> button( |
| 115 [[NSButton alloc] initWithFrame:NSZeroRect]); | 177 [[NSButton alloc] initWithFrame:NSZeroRect]); |
| 116 [button setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; | 178 [button setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; |
| 117 [button setBezelStyle:NSRoundedBezelStyle]; | 179 [button setBezelStyle:NSRoundedBezelStyle]; |
| 118 [[button cell] setControlSize:NSSmallControlSize]; | 180 [[button cell] setControlSize:NSSmallControlSize]; |
| 181 [button setTitle:text]; |
| 182 [button sizeToFit]; |
| 119 | 183 |
| 120 return button; | 184 return button; |
| 121 } | 185 } |
| 122 | 186 |
| 123 - (id)initWithBrowserWindowController: | 187 - (id)initWithBrowserWindowController: |
| 124 (BrowserWindowController*)browserWindowController | 188 (BrowserWindowController*)browserWindowController |
| 125 bridge: | 189 bridge: |
| 126 (autofill::SaveCardBubbleViewBridge*)bridge { | 190 (autofill::SaveCardBubbleViewBridge*)bridge { |
| 127 DCHECK(bridge); | 191 DCHECK(bridge); |
| 128 | 192 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 153 | 217 |
| 154 - (void)close { | 218 - (void)close { |
| 155 if (bridge_) { | 219 if (bridge_) { |
| 156 bridge_->OnBubbleClosed(); | 220 bridge_->OnBubbleClosed(); |
| 157 bridge_ = nullptr; | 221 bridge_ = nullptr; |
| 158 } | 222 } |
| 159 [super close]; | 223 [super close]; |
| 160 } | 224 } |
| 161 | 225 |
| 162 - (void)loadView { | 226 - (void)loadView { |
| 163 // Title is an NSTextView instead of an NSTextField to allow it to wrap. | 227 // Title. |
| 228 NSString* title = SysUTF16ToNSString(bridge_->GetWindowTitle()); |
| 164 base::scoped_nsobject<NSTextView> titleLabel( | 229 base::scoped_nsobject<NSTextView> titleLabel( |
| 165 [[NSTextView alloc] initWithFrame:NSZeroRect]); | 230 [SaveCardBubbleViewCocoa makeWrappingLabel:title withFontSize:15.0]); |
| 166 NSDictionary* attributes = | |
| 167 @{NSFontAttributeName : [NSFont systemFontOfSize:15.0]}; | |
| 168 base::scoped_nsobject<NSAttributedString> attributedMessage( | |
| 169 [[NSAttributedString alloc] | |
| 170 initWithString:base::SysUTF16ToNSString(bridge_->GetWindowTitle()) | |
| 171 attributes:attributes]); | |
| 172 [[titleLabel textStorage] setAttributedString:attributedMessage]; | |
| 173 [[titleLabel textContainer] setLineFragmentPadding:0.0f]; | |
| 174 [titleLabel setEditable:NO]; | |
| 175 [titleLabel setSelectable:NO]; | |
| 176 [titleLabel setDrawsBackground:NO]; | |
| 177 [titleLabel setVerticallyResizable:YES]; | |
| 178 [titleLabel setFrameSize:NSMakeSize(kDesiredBubbleWidth - (2 * kFramePadding), | |
| 179 MAXFLOAT)]; | |
| 180 [titleLabel sizeToFit]; | |
| 181 | 231 |
| 182 // Credit card info. | 232 // Credit card info. |
| 183 autofill::CreditCard card = bridge_->GetCard(); | 233 autofill::CreditCard card = bridge_->GetCard(); |
| 184 base::scoped_nsobject<NSImageView> cardIcon( | 234 base::scoped_nsobject<NSImageView> cardIcon( |
| 185 [[NSImageView alloc] initWithFrame:NSZeroRect]); | 235 [[NSImageView alloc] initWithFrame:NSZeroRect]); |
| 186 [cardIcon setToolTip:base::SysUTF16ToNSString(card.TypeForDisplay())]; | 236 [cardIcon setToolTip:base::SysUTF16ToNSString(card.TypeForDisplay())]; |
| 187 [cardIcon setWantsLayer:YES]; | 237 [cardIcon setWantsLayer:YES]; |
| 188 [[cardIcon layer] setBorderWidth:1.0]; | 238 [[cardIcon layer] setBorderWidth:1.0]; |
| 189 [[cardIcon layer] setCornerRadius:2.0]; | 239 [[cardIcon layer] setCornerRadius:2.0]; |
| 190 [[cardIcon layer] setMasksToBounds:YES]; | 240 [[cardIcon layer] setMasksToBounds:YES]; |
| 191 [[cardIcon layer] | 241 [[cardIcon layer] |
| 192 setBorderColor:skia::CGColorCreateFromSkColor(kIconBorderColor)]; | 242 setBorderColor:skia::CGColorCreateFromSkColor(kIconBorderColor)]; |
| 193 [cardIcon setImage:ResourceBundle::GetSharedInstance() | 243 [cardIcon setImage:ResourceBundle::GetSharedInstance() |
| 194 .GetNativeImageNamed( | 244 .GetNativeImageNamed( |
| 195 autofill::CreditCard::IconResourceId(card.type())) | 245 autofill::CreditCard::IconResourceId(card.type())) |
| 196 .AsNSImage()]; | 246 .AsNSImage()]; |
| 197 [cardIcon setFrameSize:[[cardIcon image] size]]; | 247 [cardIcon setFrameSize:[[cardIcon image] size]]; |
| 198 | 248 |
| 199 base::scoped_nsobject<NSTextField> lastFourLabel( | |
| 200 [SaveCardBubbleViewCocoa makeTextField]); | |
| 201 // Midline horizontal ellipsis follwed by last four digits. | 249 // Midline horizontal ellipsis follwed by last four digits. |
| 202 [lastFourLabel setStringValue:base::SysUTF16ToNSString( | 250 base::scoped_nsobject<NSTextField> lastFourLabel([SaveCardBubbleViewCocoa |
| 203 base::UTF8ToUTF16("\xE2\x8B\xAF") + | 251 makeLabel:SysUTF16ToNSString(base::UTF8ToUTF16("\xE2\x8B\xAF") + |
| 204 card.LastFourDigits())]; | 252 card.LastFourDigits())]); |
| 205 [lastFourLabel sizeToFit]; | |
| 206 | 253 |
| 207 base::scoped_nsobject<NSTextField> expirationDateLabel( | 254 base::scoped_nsobject<NSTextField> expirationDateLabel( |
| 208 [SaveCardBubbleViewCocoa makeTextField]); | 255 [SaveCardBubbleViewCocoa |
| 209 [expirationDateLabel | 256 makeLabel:base::SysUTF16ToNSString( |
| 210 setStringValue:base::SysUTF16ToNSString( | 257 card.AbbreviatedExpirationDateForDisplay())]); |
| 211 card.AbbreviatedExpirationDateForDisplay())]; | 258 |
| 212 [expirationDateLabel sizeToFit]; | 259 // Explanatory text (only shown for upload). |
| 260 base::scoped_nsobject<NSTextView> explanationLabel( |
| 261 [[NSTextView alloc] initWithFrame:NSZeroRect]); |
| 262 base::string16 explanation = bridge_->GetExplanatoryMessage(); |
| 263 if (!explanation.empty()) { |
| 264 explanationLabel.reset([SaveCardBubbleViewCocoa |
| 265 makeWrappingLabel:SysUTF16ToNSString(explanation) |
| 266 withFontSize:[NSFont systemFontSize]] |
| 267 .release()); |
| 268 } |
| 213 | 269 |
| 214 // "Learn more" link. | 270 // "Learn more" link. |
| 271 NSString* learnMoreString = l10n_util::GetNSString(IDS_LEARN_MORE); |
| 215 base::scoped_nsobject<HyperlinkTextView> learnMoreLink( | 272 base::scoped_nsobject<HyperlinkTextView> learnMoreLink( |
| 216 [[HyperlinkTextView alloc] initWithFrame:NSZeroRect]); | 273 [SaveCardBubbleViewCocoa makeHyperlinkText:learnMoreString]); |
| 217 NSString* learnMoreString = l10n_util::GetNSString(IDS_LEARN_MORE); | |
| 218 [learnMoreLink | |
| 219 setMessage:learnMoreString | |
| 220 withFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]] | |
| 221 messageColor:[NSColor blackColor]]; | |
| 222 [learnMoreLink setDelegate:self]; | 274 [learnMoreLink setDelegate:self]; |
| 275 |
| 223 NSColor* linkColor = | 276 NSColor* linkColor = |
| 224 skia::SkColorToCalibratedNSColor(chrome_style::GetLinkColor()); | 277 skia::SkColorToCalibratedNSColor(chrome_style::GetLinkColor()); |
| 225 [learnMoreLink addLinkRange:NSMakeRange(0, [learnMoreString length]) | 278 NSRange range = NSMakeRange(0, [learnMoreString length]); |
| 226 withURL:nil | 279 [learnMoreLink addLinkRange:range withURL:nil linkColor:linkColor]; |
| 227 linkColor:linkColor]; | 280 [[learnMoreLink textStorage] addAttribute:NSUnderlineStyleAttributeName |
| 228 NSTextStorage* text = [learnMoreLink textStorage]; | 281 value:@(NSUnderlineStyleNone) |
| 229 [text addAttribute:NSUnderlineStyleAttributeName | 282 range:range]; |
| 230 value:[NSNumber numberWithInt:NSUnderlineStyleNone] | |
| 231 range:NSMakeRange(0, [learnMoreString length])]; | |
| 232 [[learnMoreLink textContainer] setLineFragmentPadding:0.0f]; | |
| 233 [learnMoreLink setVerticallyResizable:YES]; | |
| 234 [learnMoreLink | |
| 235 setFrameSize:NSMakeSize(kDesiredBubbleWidth - 2 * kFramePadding, | |
| 236 MAXFLOAT)]; | |
| 237 [learnMoreLink sizeToFit]; | |
| 238 | 283 |
| 239 // Cancel button. | 284 // Cancel button. |
| 240 base::scoped_nsobject<NSButton> cancelButton( | 285 base::scoped_nsobject<NSButton> cancelButton([SaveCardBubbleViewCocoa |
| 241 [SaveCardBubbleViewCocoa makeButton]); | 286 makeButton:l10n_util::GetNSString(IDS_AUTOFILL_SAVE_CARD_PROMPT_DENY)]); |
| 242 [cancelButton | |
| 243 setTitle:l10n_util::GetNSString(IDS_AUTOFILL_SAVE_CARD_PROMPT_DENY)]; | |
| 244 [cancelButton sizeToFit]; | |
| 245 [cancelButton setTarget:self]; | 287 [cancelButton setTarget:self]; |
| 246 [cancelButton setAction:@selector(onCancelButton:)]; | 288 [cancelButton setAction:@selector(onCancelButton:)]; |
| 247 [cancelButton setKeyEquivalent:@"\e"]; | 289 [cancelButton setKeyEquivalent:@"\e"]; |
| 248 | 290 |
| 249 // Save button. | 291 // Save button. |
| 250 base::scoped_nsobject<NSButton> saveButton( | 292 base::scoped_nsobject<NSButton> saveButton([SaveCardBubbleViewCocoa |
| 251 [SaveCardBubbleViewCocoa makeButton]); | 293 makeButton:l10n_util::GetNSString(IDS_AUTOFILL_SAVE_CARD_PROMPT_ACCEPT)]); |
| 252 [saveButton | |
| 253 setTitle:l10n_util::GetNSString(IDS_AUTOFILL_SAVE_CARD_PROMPT_ACCEPT)]; | |
| 254 [saveButton sizeToFit]; | |
| 255 [saveButton setTarget:self]; | 294 [saveButton setTarget:self]; |
| 256 [saveButton setAction:@selector(onSaveButton:)]; | 295 [saveButton setAction:@selector(onSaveButton:)]; |
| 257 [saveButton setKeyEquivalent:@"\r"]; | 296 [saveButton setKeyEquivalent:@"\r"]; |
| 258 | 297 |
| 298 // Footer with legal text (only shown for upload). |
| 299 base::scoped_nsobject<NSBox> divider( |
| 300 [[NSBox alloc] initWithFrame:NSZeroRect]); |
| 301 base::scoped_nsobject<NSView> footerView( |
| 302 [[NSView alloc] initWithFrame:NSZeroRect]); |
| 303 const autofill::LegalMessageLines& lines = bridge_->GetLegalMessageLines(); |
| 304 if (!lines.empty()) { |
| 305 [divider setBoxType:NSBoxCustom]; |
| 306 [divider setBorderType:NSLineBorder]; |
| 307 [divider setBorderColor:skia::SkColorToCalibratedNSColor(kDividerColor)]; |
| 308 [divider setFrameSize:NSMakeSize(kDesiredBubbleWidth, kDividerHeight)]; |
| 309 |
| 310 [footerView setWantsLayer:YES]; |
| 311 [[footerView layer] |
| 312 setBackgroundColor:skia::CGColorCreateFromSkColor(kFooterColor)]; |
| 313 |
| 314 CGFloat linesHeight = kFramePadding; |
| 315 for (auto lineIter = lines.rbegin(); lineIter != lines.rend(); ++lineIter) { |
| 316 // Create the legal message line view. |
| 317 base::scoped_nsobject<HyperlinkTextView> lineView([SaveCardBubbleViewCocoa |
| 318 makeHyperlinkText:SysUTF16ToNSString(lineIter->text())]); |
| 319 [lineView setDelegate:self]; |
| 320 |
| 321 // Add the links. |
| 322 for (const autofill::LegalMessageLine::Link& link : lineIter->links()) { |
| 323 NSRange range = NSMakeRange(link.range.start(), link.range.length()); |
| 324 [lineView addLinkRange:range withURL:nil linkColor:linkColor]; |
| 325 [[lineView textStorage] addAttribute:NSUnderlineStyleAttributeName |
| 326 value:@(NSUnderlineStyleNone) |
| 327 range:range]; |
| 328 } |
| 329 |
| 330 // Add the line to the footer view. |
| 331 [footerView addSubview:lineView]; |
| 332 [lineView setFrameOrigin:NSMakePoint(kFramePadding, linesHeight)]; |
| 333 linesHeight += |
| 334 [lineView frame].size.height + kRelatedControlVerticalPadding; |
| 335 } |
| 336 [footerView setFrameSize:NSMakeSize(kDesiredBubbleWidth, |
| 337 linesHeight + kFramePadding)]; |
| 338 } |
| 339 |
| 259 // Layout. | 340 // Layout. |
| 341 [footerView setFrameOrigin:NSZeroPoint]; |
| 342 |
| 343 [divider setFrameOrigin:NSMakePoint(0, NSMaxY([footerView frame]))]; |
| 344 |
| 260 [saveButton setFrameOrigin: | 345 [saveButton setFrameOrigin: |
| 261 NSMakePoint(kDesiredBubbleWidth - kFramePadding - | 346 NSMakePoint(kDesiredBubbleWidth - kFramePadding - |
| 262 NSWidth([saveButton frame]), | 347 NSWidth([saveButton frame]), |
| 263 kFramePadding)]; | 348 NSMaxY([divider frame]) + kFramePadding)]; |
| 264 [cancelButton setFrameOrigin: | 349 [cancelButton setFrameOrigin: |
| 265 NSMakePoint(NSMinX([saveButton frame]) - | 350 NSMakePoint(NSMinX([saveButton frame]) - |
| 266 kRelatedControlHorizontalPadding - | 351 kRelatedControlHorizontalPadding - |
| 267 NSWidth([cancelButton frame]), | 352 NSWidth([cancelButton frame]), |
| 268 kFramePadding)]; | 353 NSMaxY([divider frame]) + kFramePadding)]; |
| 269 [learnMoreLink setFrameOrigin: | 354 [learnMoreLink setFrameOrigin: |
| 270 NSMakePoint(kFramePadding, | 355 NSMakePoint(kFramePadding, |
| 271 NSMidY([saveButton frame]) - | 356 NSMidY([saveButton frame]) - |
| 272 (NSHeight([learnMoreLink frame]) / 2.0))]; | 357 (NSHeight([learnMoreLink frame]) / 2.0))]; |
| 273 | 358 |
| 359 [explanationLabel setFrameOrigin: |
| 360 NSMakePoint(kFramePadding, |
| 361 NSMaxY([saveButton frame]) + |
| 362 kUnrelatedControlVerticalPadding)]; |
| 363 |
| 364 NSView* viewBelowIcon = |
| 365 ([explanationLabel frame].size.height > 0) ? explanationLabel.get() |
| 366 : saveButton.get(); |
| 274 [cardIcon setFrameOrigin: | 367 [cardIcon setFrameOrigin: |
| 275 NSMakePoint(kFramePadding, | 368 NSMakePoint(kFramePadding, |
| 276 NSMaxY([saveButton frame]) + | 369 NSMaxY([viewBelowIcon frame]) + |
| 277 kUnrelatedControlVerticalPadding)]; | 370 kUnrelatedControlVerticalPadding)]; |
| 278 [lastFourLabel setFrameOrigin: | 371 [lastFourLabel setFrameOrigin: |
| 279 NSMakePoint(NSMaxX([cardIcon frame]) + kRelatedControlHorizontalPadding, | 372 NSMakePoint(NSMaxX([cardIcon frame]) + kRelatedControlHorizontalPadding, |
| 280 NSMidY([cardIcon frame]) - | 373 NSMidY([cardIcon frame]) - |
| 281 (NSHeight([lastFourLabel frame]) / 2.0))]; | 374 (NSHeight([lastFourLabel frame]) / 2.0))]; |
| 282 [expirationDateLabel setFrameOrigin: | 375 [expirationDateLabel setFrameOrigin: |
| 283 NSMakePoint(NSMaxX([lastFourLabel frame]) + | 376 NSMakePoint(NSMaxX([lastFourLabel frame]) + |
| 284 kRelatedControlHorizontalPadding, | 377 kRelatedControlHorizontalPadding, |
| 285 NSMidY([cardIcon frame]) - | 378 NSMidY([cardIcon frame]) - |
| 286 (NSHeight([expirationDateLabel frame]) / 2.0))]; | 379 (NSHeight([expirationDateLabel frame]) / 2.0))]; |
| 287 | 380 |
| 288 [titleLabel setFrameOrigin: | 381 [titleLabel setFrameOrigin: |
| 289 NSMakePoint(kFramePadding, | 382 NSMakePoint(kFramePadding, |
| 290 NSMaxY([cardIcon frame]) + kUnrelatedControlVerticalPadding)]; | 383 NSMaxY([cardIcon frame]) + kUnrelatedControlVerticalPadding)]; |
| 291 | 384 |
| 292 [[[self window] contentView] setSubviews:@[ | 385 [[[self window] contentView] setSubviews:@[ |
| 293 titleLabel, cardIcon, lastFourLabel, expirationDateLabel, learnMoreLink, | 386 titleLabel, cardIcon, lastFourLabel, expirationDateLabel, explanationLabel, |
| 294 cancelButton, saveButton | 387 learnMoreLink, cancelButton, saveButton, divider, footerView |
| 295 ]]; | 388 ]]; |
| 296 | 389 |
| 297 // Update window frame. | 390 // Update window frame. |
| 298 NSRect windowFrame = [[self window] frame]; | 391 NSRect windowFrame = [[self window] frame]; |
| 299 windowFrame.size.height = NSMaxY([titleLabel frame]) + kFramePadding; | 392 windowFrame.size.height = NSMaxY([titleLabel frame]) + kFramePadding + |
| 393 info_bubble::kBubbleArrowHeight; |
| 300 windowFrame.size.width = kDesiredBubbleWidth; | 394 windowFrame.size.width = kDesiredBubbleWidth; |
| 301 [[self window] setFrame:windowFrame display:NO]; | 395 [[self window] setFrame:windowFrame display:NO]; |
| 302 } | 396 } |
| 303 | 397 |
| 304 - (void)onSaveButton:(id)sender { | 398 - (void)onSaveButton:(id)sender { |
| 305 DCHECK(bridge_); | 399 DCHECK(bridge_); |
| 306 bridge_->OnSaveButton(); | 400 bridge_->OnSaveButton(); |
| 307 } | 401 } |
| 308 | 402 |
| 309 - (void)onCancelButton:(id)sender { | 403 - (void)onCancelButton:(id)sender { |
| 310 DCHECK(bridge_); | 404 DCHECK(bridge_); |
| 311 bridge_->OnCancelButton(); | 405 bridge_->OnCancelButton(); |
| 312 } | 406 } |
| 313 | 407 |
| 314 - (BOOL)textView:(NSTextView*)textView | 408 - (BOOL)textView:(NSTextView*)textView |
| 315 clickedOnLink:(id)link | 409 clickedOnLink:(id)link |
| 316 atIndex:(NSUInteger)charIndex { | 410 atIndex:(NSUInteger)charIndex { |
| 317 DCHECK(bridge_); | 411 DCHECK(bridge_); |
| 412 |
| 413 // Check each of the links in each of the legal message lines ot see if they |
| 414 // are the source of the click. |
| 415 const autofill::LegalMessageLines& lines = bridge_->GetLegalMessageLines(); |
| 416 for (const autofill::LegalMessageLine& line : lines) { |
| 417 if (line.text() == |
| 418 base::SysNSStringToUTF16([[textView textStorage] string])) { |
| 419 for (const autofill::LegalMessageLine::Link& link : line.links()) { |
| 420 if (link.range.start() <= charIndex && charIndex < link.range.end()) { |
| 421 bridge_->OnLegalMessageLinkClicked(link.url); |
| 422 return YES; |
| 423 } |
| 424 } |
| 425 } |
| 426 } |
| 427 |
| 428 // If none of the legal message links are the source of the click, the source |
| 429 // must be the learn more link. |
| 318 bridge_->OnLearnMoreClicked(); | 430 bridge_->OnLearnMoreClicked(); |
| 319 return YES; | 431 return YES; |
| 320 } | 432 } |
| 321 | 433 |
| 322 @end | 434 @end |
| OLD | NEW |