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

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

Issue 40483003: [rAC, OSX] Add "generated CC" info bubble. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Final fixes (arrow position etc.) Created 7 years, 1 month 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/cocoa/autofill/generated_credit_card_bubble_cocoa.h"
6
7 #include "base/mac/foundation_util.h"
8 #include "base/mac/scoped_block.h"
9 #include "base/mac/scoped_nsobject.h"
10 #include "base/strings/sys_string_conversions.h"
11 #include "chrome/browser/ui/autofill/generated_credit_card_bubble_view.h"
12 #include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
Scott Hess - ex-Googler 2013/10/31 20:23:19 order c, v.
groby-ooo-7-16 2013/10/31 22:55:47 Done. (Odd that presubmit didn't catch it, thanks
13 #import "chrome/browser/ui/cocoa/base_bubble_controller.h"
14 #import "chrome/browser/ui/cocoa/hyperlink_text_view.h"
15 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
16 #import "chrome/browser/ui/cocoa/info_bubble_window.h"
17 #include "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
18 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
19 #include "content/public/browser/web_contents_view.h"
20 #include "skia/ext/skia_utils_mac.h"
21 #include "ui/native_theme/native_theme.h"
22
23 typedef void(^CloseObserver)(GeneratedCreditCardBubbleControllerCocoa*);
24 typedef void(^ClickObserver)(int);
Scott Hess - ex-Googler 2013/10/31 20:23:19 AFAICT, neither of these actually references their
groby-ooo-7-16 2013/10/31 22:55:47 Getting rid of blocks or base::Bind, instead havin
25
26 namespace {
27
28 const CGFloat kTitlePadding = 20.0;
29 const CGFloat kInset = 20.0;
30
31 } // namespace
32
33 // The Cocoa side of the bubble controller.
34 @interface GeneratedCreditCardBubbleControllerCocoa :
35 BaseBubbleController<NSTextViewDelegate> {
36 // A block that is run when the bubble is being closed. That allows wiping
37 // out weak references. (BaseBubbleController self-destroys on close).
38 base::mac::ScopedBlock<CloseObserver> closeObserver_;
39
40 // A block that is run when the user clicks on a link.
41 base::mac::ScopedBlock<ClickObserver> clickObserver_;
42 }
43
44 // Designate initializer. Runs |closeObserver| when -windowWillClose: runs.
45 - (id)initWithParentWindow:(NSWindow*)parentWindow
46 controller:
47 (autofill::GeneratedCreditCardBubbleController*)controller
48 clickObserver:(ClickObserver)clickObserver
49 closeObserver:(CloseObserver)closeObserver;
Scott Hess - ex-Googler 2013/10/31 20:23:19 The nice thing about a weak ptr to the bridge obje
groby-ooo-7-16 2013/10/31 22:55:47 No weak ptr needed - the bridge must live on until
50
51 // Show the bubble at the given |anchor| point. Coordinates are in screen space.
52 - (void)showAtAnchor:(NSPoint)anchor;
53
54 // Return true if the bubble is in the process of hiding.
55 - (BOOL)isHiding;
56
57 // Build the window contents and lay them out.
58 - (void)performLayoutWithController:
59 (autofill::GeneratedCreditCardBubbleController*)controller;
60
61 @end
62
63
64 @implementation GeneratedCreditCardBubbleControllerCocoa
65
66 - (id)initWithParentWindow:(NSWindow*)parentWindow
67 controller:
68 (autofill::GeneratedCreditCardBubbleController*)controller
69 clickObserver:(ClickObserver)clickObserver
70 closeObserver:(CloseObserver)closeObserver {
71 base::scoped_nsobject<InfoBubbleWindow> window(
72 [[InfoBubbleWindow alloc] initWithContentRect:NSMakeRect(0, 0, 200, 100)
73 styleMask:NSBorderlessWindowMask
74 backing:NSBackingStoreBuffered
75 defer:NO]);
76 if ((self = [super initWithWindow:window
77 parentWindow:parentWindow
78 anchoredAt:NSZeroPoint])) {
79 [window setCanBecomeKeyWindow:NO];
80 closeObserver_.reset(Block_copy(closeObserver));
81 clickObserver_.reset(Block_copy(clickObserver));
82
83 ui::NativeTheme* nativeTheme = ui::NativeTheme::instance();
84 [[self bubble] setAlignment:info_bubble::kAlignArrowToAnchor];
85 [[self bubble] setArrowLocation:info_bubble::kTopRight];
86 [[self bubble] setBackgroundColor:
87 gfx::SkColorToCalibratedNSColor(nativeTheme->GetSystemColor(
88 ui::NativeTheme::kColorId_DialogBackground))];
89 [self performLayoutWithController:controller];
90 }
91 return self;
92 }
93
94 - (void)windowWillClose:(NSNotification*)notification {
95 closeObserver_.get()(self);
96 [super windowWillClose:notification];
97 }
98
99 // Called when embedded links are clicked.
100 - (BOOL)textView:(NSTextView*)textView
101 clickedOnLink:(id)link
102 atIndex:(NSUInteger)charIndex {
Scott Hess - ex-Googler 2013/10/31 20:23:19 Align the : chars.
groby-ooo-7-16 2013/10/31 22:55:47 Done.
103 int index = [base::mac::ObjCCastStrict<NSNumber>(link) intValue];
104 clickObserver_.get()(index);
105 return YES;
106 }
107
108 - (void)showAtAnchor:(NSPoint)anchorPoint {
109 [self setAnchorPoint:anchorPoint];
110 [self showWindow:nil];
111 }
112
113 - (BOOL)isHiding {
114 InfoBubbleWindow* window =
115 base::mac::ObjCCastStrict<InfoBubbleWindow>([self window]);
116 return [window isClosing];
117 }
118
119
120 - (void)performLayoutWithController:
121 (autofill::GeneratedCreditCardBubbleController*)controller {
122 CGFloat bubbleWidth = autofill::GeneratedCreditCardBubbleView::kContentsWidth;
123
124 // Build the bubble title.
125 NSFont* titleFont = [NSFont systemFontOfSize:15.0];
126 NSString* title = base::SysUTF16ToNSString(controller->TitleText());
127 base::scoped_nsobject<HyperlinkTextView> titleView(
128 [[HyperlinkTextView alloc] initWithFrame:NSZeroRect]);
129 [titleView setMessage:title
130 withFont:titleFont
131 messageColor:[NSColor blackColor]];
132
133 [titleView setFrame:NSMakeRect(
134 0, 0,
135 CGFLOAT_MAX, CGFLOAT_MAX)];
136
137 // Now use the layout manager to compute layout.
138 NSLayoutManager* layoutManager = [titleView layoutManager];
139 NSTextContainer* textContainer = [titleView textContainer];
140 [layoutManager ensureLayoutForTextContainer:textContainer];
141 NSRect titleFrame = [layoutManager usedRectForTextContainer:textContainer];
142 [titleView setFrame:titleFrame];
Scott Hess - ex-Googler 2013/10/31 20:23:19 This section of code seems to be copy/paste inheri
groby-ooo-7-16 2013/10/31 22:55:47 I can skip this since it's always going to be sing
143
144 bubbleWidth = std::max(bubbleWidth, NSWidth([titleView frame]) + 2 * kInset);
Scott Hess - ex-Googler 2013/10/31 20:23:19 Is it certain that the title won't cause windows t
groby-ooo-7-16 2013/10/31 22:55:47 That depends - if the browser is almost completely
Scott Hess - ex-Googler 2013/10/31 23:33:38 I agree that it would be a conundrum, but just bec
145
146 // Build the contents view.
147 base::scoped_nsobject<HyperlinkTextView> contentsView(
148 [[HyperlinkTextView alloc] initWithFrame:NSZeroRect]);
149
150 [contentsView setEditable:NO];
151 [contentsView setDelegate:self];
152
153 NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
154 NSFont* boldFont = [NSFont boldSystemFontOfSize:[NSFont systemFontSize]];
Scott Hess - ex-Googler 2013/10/31 20:23:19 Could as easily store the @{} in an NSDictionary*
groby-ooo-7-16 2013/10/31 22:55:47 You mean the font? Yes, but HyperlinkTextView does
Scott Hess - ex-Googler 2013/10/31 23:33:38 |boldFont| is being applied to non-link sections t
155 [contentsView setMessage:base::SysUTF16ToNSString(controller->ContentsText())
156 withFont:font
157 messageColor:[NSColor blackColor]];
158
159 const std::vector<autofill::TextRange>& text_ranges =
160 controller->ContentsTextRanges();
161 for (size_t i = 0; i < text_ranges.size(); ++i) {
162 NSRange range = text_ranges[i].range.ToNSRange();
163 if (text_ranges[i].is_link) {
164 [contentsView addLinkRange:range
165 withName:@(i)
166 linkColor:[NSColor blueColor]];
167 } else {
168 [[contentsView textStorage]
169 addAttributes:@{ NSFontAttributeName : boldFont }
170 range:range];
171 }
172 }
173
174 // There's no direct API to compute desired sizes - use layouting instead.
175 // Layout in a rect with fixed width and "infinite" height.
176 [contentsView setFrame:NSMakeRect(
177 0, 0,
178 bubbleWidth - 2 * kInset, CGFLOAT_MAX)];
179
180 // Use the layout manager to compute size.
181 layoutManager = [contentsView layoutManager];
182 textContainer = [contentsView textContainer];
183 [layoutManager ensureLayoutForTextContainer:textContainer];
184 NSRect newFrame = [layoutManager usedRectForTextContainer:textContainer];
185 [contentsView setFrame:newFrame];
Scott Hess - ex-Googler 2013/10/31 20:23:19 Likewise here, seems like having contentsView expo
groby-ooo-7-16 2013/10/31 22:55:47 Technically, it belongs on NSTextView, but I'm rel
Scott Hess - ex-Googler 2013/10/31 23:33:38 I find two existing cases where we're doing this b
186
187 // Sizes are computed, now lay out the individual parts.
188 CGFloat bubbleHeight = NSHeight([titleView frame]) +
189 kTitlePadding +
190 2 * kInset +
191 NSHeight([contentsView frame]);
192 [titleView setFrameOrigin:
193 NSMakePoint(kInset, bubbleHeight - kInset - NSHeight([titleView frame]))];
Scott Hess - ex-Googler 2013/10/31 20:23:19 Rather than constructing bubbleHeight and then bac
groby-ooo-7-16 2013/10/31 22:55:47 Done.
194 [contentsView setFrameOrigin:NSMakePoint(kInset, kInset)];
Scott Hess - ex-Googler 2013/10/31 20:23:19 Though another option would be to construct additi
groby-ooo-7-16 2013/10/31 22:55:47 Done.
195 [[[self window] contentView] setSubviews:@[ contentsView, titleView ]];
196
197 // Update window frame.
198 NSRect windowFrame = [[self window] frame];
199 windowFrame.size = NSMakeSize(bubbleWidth, bubbleHeight);
200 [[self window] setFrame:windowFrame display:YES];
201 }
202
203 @end
204
205
206 namespace autofill {
207
208 // static
209 base::WeakPtr<GeneratedCreditCardBubbleView>
210 GeneratedCreditCardBubbleView::Create(
211 const base::WeakPtr<GeneratedCreditCardBubbleController>& controller) {
212 return (new GeneratedCreditCardBubbleCocoa(controller))->weak_ptr_factory_.
213 GetWeakPtr();
214 }
215
216 GeneratedCreditCardBubbleCocoa::GeneratedCreditCardBubbleCocoa(
217 const base::WeakPtr<GeneratedCreditCardBubbleController>& controller)
218 : bubbleController_(NULL),
219 controller_(controller),
220 weak_ptr_factory_(this) {
221 }
222
223 GeneratedCreditCardBubbleCocoa::~GeneratedCreditCardBubbleCocoa() {}
224
225 void GeneratedCreditCardBubbleCocoa::Show() {
226 NSView* browser_view =
227 controller_->web_contents()->GetView()->GetNativeView();
Scott Hess - ex-Googler 2013/10/31 20:23:19 AFAICT, your code never checks whether the weak po
groby-ooo-7-16 2013/10/31 22:55:47 It does check in the observer blocks. Show is inde
228 NSWindow* parent_window = [browser_view window];
229 LocationBarViewMac* location_bar =
230 [[parent_window windowController] locationBarBridge];
231
232 // |location_bar| can be NULL during initialization stages.
233 if (!location_bar)
234 return;
235
236 if (!bubbleController_) {
237 CloseObserver observer = ^(GeneratedCreditCardBubbleControllerCocoa*) {
238 bubbleController_ = nil;
239 };
240 ClickObserver clickObserver = ^(int index) {
241 if (controller_)
242 controller_->OnLinkClicked();
243 };
244 bubbleController_ = [[GeneratedCreditCardBubbleControllerCocoa alloc]
245 initWithParentWindow:parent_window
246 controller:controller_.get()
247 clickObserver:clickObserver
248 closeObserver:observer];
249 }
250
251 NSRect frame = NSZeroRect;
252 frame.origin = location_bar->GetGeneratedCreditCardBubblePoint();
Scott Hess - ex-Googler 2013/10/31 20:23:19 Excess space.
groby-ooo-7-16 2013/10/31 22:55:47 Done.
253 NSPoint anchor = [parent_window convertRectToScreen:frame].origin;
254 [bubbleController_ showAtAnchor:anchor];
255 }
256
Scott Hess - ex-Googler 2013/10/31 20:23:19 extra line.
groby-ooo-7-16 2013/10/31 22:55:47 Done.
257
258 void GeneratedCreditCardBubbleCocoa::Hide() {
259 [bubbleController_ close];
260 }
261
262 bool GeneratedCreditCardBubbleCocoa::IsHiding() const {
263 return [bubbleController_ isHiding];
264 }
265
Scott Hess - ex-Googler 2013/10/31 20:23:19 extra line
groby-ooo-7-16 2013/10/31 22:55:47 Done.
266
267 } // autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698