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

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

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

Powered by Google App Engine
This is Rietveld 408576698