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

Unified 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, 2 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/cocoa/autofill/generated_credit_card_bubble_cocoa.mm
diff --git a/chrome/browser/ui/cocoa/autofill/generated_credit_card_bubble_cocoa.mm b/chrome/browser/ui/cocoa/autofill/generated_credit_card_bubble_cocoa.mm
new file mode 100644
index 0000000000000000000000000000000000000000..a55981059926aa99d9be475c8986070867a05a0c
--- /dev/null
+++ b/chrome/browser/ui/cocoa/autofill/generated_credit_card_bubble_cocoa.mm
@@ -0,0 +1,267 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/cocoa/autofill/generated_credit_card_bubble_cocoa.h"
+
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_block.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/strings/sys_string_conversions.h"
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_view.h"
+#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
+#import "chrome/browser/ui/cocoa/base_bubble_controller.h"
+#import "chrome/browser/ui/cocoa/hyperlink_text_view.h"
+#import "chrome/browser/ui/cocoa/info_bubble_view.h"
+#import "chrome/browser/ui/cocoa/info_bubble_window.h"
+#include "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
+#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
+#include "content/public/browser/web_contents_view.h"
+#include "skia/ext/skia_utils_mac.h"
+#include "ui/native_theme/native_theme.h"
+
+typedef void(^CloseObserver)(GeneratedCreditCardBubbleControllerCocoa*);
+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
+
+namespace {
+
+const CGFloat kTitlePadding = 20.0;
+const CGFloat kInset = 20.0;
+
+} // namespace
+
+// The Cocoa side of the bubble controller.
+@interface GeneratedCreditCardBubbleControllerCocoa :
+ BaseBubbleController<NSTextViewDelegate> {
+ // A block that is run when the bubble is being closed. That allows wiping
+ // out weak references. (BaseBubbleController self-destroys on close).
+ base::mac::ScopedBlock<CloseObserver> closeObserver_;
+
+ // A block that is run when the user clicks on a link.
+ base::mac::ScopedBlock<ClickObserver> clickObserver_;
+}
+
+// Designate initializer. Runs |closeObserver| when -windowWillClose: runs.
+- (id)initWithParentWindow:(NSWindow*)parentWindow
+ controller:
+ (autofill::GeneratedCreditCardBubbleController*)controller
+ clickObserver:(ClickObserver)clickObserver
+ 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
+
+// Show the bubble at the given |anchor| point. Coordinates are in screen space.
+- (void)showAtAnchor:(NSPoint)anchor;
+
+// Return true if the bubble is in the process of hiding.
+- (BOOL)isHiding;
+
+// Build the window contents and lay them out.
+- (void)performLayoutWithController:
+ (autofill::GeneratedCreditCardBubbleController*)controller;
+
+@end
+
+
+@implementation GeneratedCreditCardBubbleControllerCocoa
+
+- (id)initWithParentWindow:(NSWindow*)parentWindow
+ controller:
+ (autofill::GeneratedCreditCardBubbleController*)controller
+ clickObserver:(ClickObserver)clickObserver
+ closeObserver:(CloseObserver)closeObserver {
+ base::scoped_nsobject<InfoBubbleWindow> window(
+ [[InfoBubbleWindow alloc] initWithContentRect:NSMakeRect(0, 0, 200, 100)
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:NO]);
+ if ((self = [super initWithWindow:window
+ parentWindow:parentWindow
+ anchoredAt:NSZeroPoint])) {
+ [window setCanBecomeKeyWindow:NO];
+ closeObserver_.reset(Block_copy(closeObserver));
+ clickObserver_.reset(Block_copy(clickObserver));
+
+ ui::NativeTheme* nativeTheme = ui::NativeTheme::instance();
+ [[self bubble] setAlignment:info_bubble::kAlignArrowToAnchor];
+ [[self bubble] setArrowLocation:info_bubble::kTopRight];
+ [[self bubble] setBackgroundColor:
+ gfx::SkColorToCalibratedNSColor(nativeTheme->GetSystemColor(
+ ui::NativeTheme::kColorId_DialogBackground))];
+ [self performLayoutWithController:controller];
+ }
+ return self;
+}
+
+- (void)windowWillClose:(NSNotification*)notification {
+ closeObserver_.get()(self);
+ [super windowWillClose:notification];
+}
+
+// Called when embedded links are clicked.
+- (BOOL)textView:(NSTextView*)textView
+ clickedOnLink:(id)link
+ 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.
+ int index = [base::mac::ObjCCastStrict<NSNumber>(link) intValue];
+ clickObserver_.get()(index);
+ return YES;
+}
+
+- (void)showAtAnchor:(NSPoint)anchorPoint {
+ [self setAnchorPoint:anchorPoint];
+ [self showWindow:nil];
+}
+
+- (BOOL)isHiding {
+ InfoBubbleWindow* window =
+ base::mac::ObjCCastStrict<InfoBubbleWindow>([self window]);
+ return [window isClosing];
+}
+
+
+- (void)performLayoutWithController:
+ (autofill::GeneratedCreditCardBubbleController*)controller {
+ CGFloat bubbleWidth = autofill::GeneratedCreditCardBubbleView::kContentsWidth;
+
+ // Build the bubble title.
+ NSFont* titleFont = [NSFont systemFontOfSize:15.0];
+ NSString* title = base::SysUTF16ToNSString(controller->TitleText());
+ base::scoped_nsobject<HyperlinkTextView> titleView(
+ [[HyperlinkTextView alloc] initWithFrame:NSZeroRect]);
+ [titleView setMessage:title
+ withFont:titleFont
+ messageColor:[NSColor blackColor]];
+
+ [titleView setFrame:NSMakeRect(
+ 0, 0,
+ CGFLOAT_MAX, CGFLOAT_MAX)];
+
+ // Now use the layout manager to compute layout.
+ NSLayoutManager* layoutManager = [titleView layoutManager];
+ NSTextContainer* textContainer = [titleView textContainer];
+ [layoutManager ensureLayoutForTextContainer:textContainer];
+ NSRect titleFrame = [layoutManager usedRectForTextContainer:textContainer];
+ [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
+
+ 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
+
+ // Build the contents view.
+ base::scoped_nsobject<HyperlinkTextView> contentsView(
+ [[HyperlinkTextView alloc] initWithFrame:NSZeroRect]);
+
+ [contentsView setEditable:NO];
+ [contentsView setDelegate:self];
+
+ NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
+ 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
+ [contentsView setMessage:base::SysUTF16ToNSString(controller->ContentsText())
+ withFont:font
+ messageColor:[NSColor blackColor]];
+
+ const std::vector<autofill::TextRange>& text_ranges =
+ controller->ContentsTextRanges();
+ for (size_t i = 0; i < text_ranges.size(); ++i) {
+ NSRange range = text_ranges[i].range.ToNSRange();
+ if (text_ranges[i].is_link) {
+ [contentsView addLinkRange:range
+ withName:@(i)
+ linkColor:[NSColor blueColor]];
+ } else {
+ [[contentsView textStorage]
+ addAttributes:@{ NSFontAttributeName : boldFont }
+ range:range];
+ }
+ }
+
+ // There's no direct API to compute desired sizes - use layouting instead.
+ // Layout in a rect with fixed width and "infinite" height.
+ [contentsView setFrame:NSMakeRect(
+ 0, 0,
+ bubbleWidth - 2 * kInset, CGFLOAT_MAX)];
+
+ // Use the layout manager to compute size.
+ layoutManager = [contentsView layoutManager];
+ textContainer = [contentsView textContainer];
+ [layoutManager ensureLayoutForTextContainer:textContainer];
+ NSRect newFrame = [layoutManager usedRectForTextContainer:textContainer];
+ [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
+
+ // Sizes are computed, now lay out the individual parts.
+ CGFloat bubbleHeight = NSHeight([titleView frame]) +
+ kTitlePadding +
+ 2 * kInset +
+ NSHeight([contentsView frame]);
+ [titleView setFrameOrigin:
+ 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.
+ [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.
+ [[[self window] contentView] setSubviews:@[ contentsView, titleView ]];
+
+ // Update window frame.
+ NSRect windowFrame = [[self window] frame];
+ windowFrame.size = NSMakeSize(bubbleWidth, bubbleHeight);
+ [[self window] setFrame:windowFrame display:YES];
+}
+
+@end
+
+
+namespace autofill {
+
+// static
+base::WeakPtr<GeneratedCreditCardBubbleView>
+ GeneratedCreditCardBubbleView::Create(
+ const base::WeakPtr<GeneratedCreditCardBubbleController>& controller) {
+ return (new GeneratedCreditCardBubbleCocoa(controller))->weak_ptr_factory_.
+ GetWeakPtr();
+}
+
+GeneratedCreditCardBubbleCocoa::GeneratedCreditCardBubbleCocoa(
+ const base::WeakPtr<GeneratedCreditCardBubbleController>& controller)
+ : bubbleController_(NULL),
+ controller_(controller),
+ weak_ptr_factory_(this) {
+}
+
+GeneratedCreditCardBubbleCocoa::~GeneratedCreditCardBubbleCocoa() {}
+
+void GeneratedCreditCardBubbleCocoa::Show() {
+ NSView* browser_view =
+ 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
+ NSWindow* parent_window = [browser_view window];
+ LocationBarViewMac* location_bar =
+ [[parent_window windowController] locationBarBridge];
+
+ // |location_bar| can be NULL during initialization stages.
+ if (!location_bar)
+ return;
+
+ if (!bubbleController_) {
+ CloseObserver observer = ^(GeneratedCreditCardBubbleControllerCocoa*) {
+ bubbleController_ = nil;
+ };
+ ClickObserver clickObserver = ^(int index) {
+ if (controller_)
+ controller_->OnLinkClicked();
+ };
+ bubbleController_ = [[GeneratedCreditCardBubbleControllerCocoa alloc]
+ initWithParentWindow:parent_window
+ controller:controller_.get()
+ clickObserver:clickObserver
+ closeObserver:observer];
+ }
+
+ NSRect frame = NSZeroRect;
+ 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.
+ NSPoint anchor = [parent_window convertRectToScreen:frame].origin;
+ [bubbleController_ showAtAnchor:anchor];
+}
+
Scott Hess - ex-Googler 2013/10/31 20:23:19 extra line.
groby-ooo-7-16 2013/10/31 22:55:47 Done.
+
+void GeneratedCreditCardBubbleCocoa::Hide() {
+ [bubbleController_ close];
+}
+
+bool GeneratedCreditCardBubbleCocoa::IsHiding() const {
+ return [bubbleController_ isHiding];
+}
+
Scott Hess - ex-Googler 2013/10/31 20:23:19 extra line
groby-ooo-7-16 2013/10/31 22:55:47 Done.
+
+} // autofill

Powered by Google App Engine
This is Rietveld 408576698