Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: chrome/browser/ui/cocoa/autofill/save_card_bubble_view_bridge.mm

Issue 1783833002: Add explanation text and legal message footer to upload bubble. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2661
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698