NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / autofill / new_credit_card_bubble_cocoa.mm
blob2ac24ae88beab91ea628168e8de6e80d8c68847a
1 // Copyright 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.
5 #include "chrome/browser/ui/cocoa/autofill/new_credit_card_bubble_cocoa.h"
7 #include "base/i18n/rtl.h"
8 #include "base/mac/foundation_util.h"
9 #include "base/strings/sys_string_conversions.h"
10 #include "chrome/browser/ui/autofill/new_credit_card_bubble_controller.h"
11 #include "chrome/browser/ui/browser_finder.h"
12 #include "chrome/browser/ui/browser_window.h"
13 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
14 #import "chrome/browser/ui/cocoa/base_bubble_controller.h"
15 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
16 #import "chrome/browser/ui/cocoa/info_bubble_window.h"
17 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
18 #include "content/public/browser/web_contents.h"
19 #include "content/public/browser/web_contents_view.h"
20 #include "skia/ext/skia_utils_mac.h"
21 #import "ui/base/cocoa/controls/hyperlink_button_cell.h"
22 #include "ui/base/cocoa/window_size_constants.h"
23 #include "ui/native_theme/native_theme.h"
25 namespace {
27 const CGFloat kWrenchBubblePointOffsetY = 6;
28 const CGFloat kVerticalSpacing = 8;
29 const CGFloat kHorizontalSpacing = 4;
30 const CGFloat kInset = 20.0;
31 const CGFloat kTitleSpacing = 15;
32 const CGFloat kAnchorlessEndPadding = 20;
33 const CGFloat kAnchorlessTopPadding = 10;
35 }  // namespace
37 @interface NewCreditCardBubbleControllerCocoa : BaseBubbleController {
38  @private
39   // Controller that drives this bubble. Never NULL; outlives this class.
40   autofill::NewCreditCardBubbleController* controller_;
42   // Objective-C/C++ bridge. Owned by this class.
43   scoped_ptr<autofill::NewCreditCardBubbleCocoa> bridge_;
46 // Designated initializer.
47 - (id)initWithParentWindow:(NSWindow*)parentWindow
48                 controller:
49                     (autofill::NewCreditCardBubbleController*)controller
50                     bridge:(autofill::NewCreditCardBubbleCocoa*)bridge;
52 // Displays the bubble anchored at the specified |anchorPoint|.
53 - (void)showAtAnchor:(NSPoint)anchorPoint;
55 // Helper function to create an uneditable text field.
56 - (base::scoped_nsobject<NSTextField>)makeTextField;
58 // Helper function to set the appropriately styled details string.
59 - (void)setDetailsStringForField:(NSTextField*)details;
61 // Create and lay out all control elements inside the bubble.
62 - (void)performLayout;
64 // Delegate interface for clicks on "Learn more".
65 - (void)onLinkClicked:(id)sender;
67 @end
70 @implementation NewCreditCardBubbleControllerCocoa
72 - (id)initWithParentWindow:(NSWindow*)parentWindow
73                 controller:
74                     (autofill::NewCreditCardBubbleController*)controller
75                     bridge:(autofill::NewCreditCardBubbleCocoa*)bridge {
76   base::scoped_nsobject<InfoBubbleWindow> window(
77       [[InfoBubbleWindow alloc]
78           initWithContentRect:ui::kWindowSizeDeterminedLater
79                     styleMask:NSBorderlessWindowMask
80                       backing:NSBackingStoreBuffered
81                         defer:NO]);
82   bridge_.reset(bridge);
83   if ((self = [super initWithWindow:window
84                        parentWindow:parentWindow
85                          anchoredAt:NSZeroPoint])) {
86     controller_ = controller;
87     [window setCanBecomeKeyWindow:NO];
89     ui::NativeTheme* nativeTheme = ui::NativeTheme::instance();
90     [[self bubble] setBackgroundColor:
91         gfx::SkColorToCalibratedNSColor(nativeTheme->GetSystemColor(
92             ui::NativeTheme::kColorId_DialogBackground))];
93     [self performLayout];
94   }
95   return self;
98 - (void)showAtAnchor:(NSPoint)anchorPoint {
99   [self setAnchorPoint:anchorPoint];
100   [[self bubble] setNeedsDisplay:YES];
101   [self showWindow:nil];
104 - (base::scoped_nsobject<NSTextField>)makeTextField {
105   base::scoped_nsobject<NSTextField> textField(
106       [[NSTextField alloc] initWithFrame:NSZeroRect]);
107   [textField setEditable:NO];
108   [textField setSelectable:NO];
109   [textField setDrawsBackground:NO];
110   [textField setBezeled:NO];
112   return textField;
115 - (void)setDetailsStringForField:(NSTextField*)details {
116   // Set linespacing for |details| to match line spacing used in the dialog.
117   base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
118       [[NSMutableParagraphStyle alloc] init]);
119   [paragraphStyle setLineSpacing:0.5 * [[details font] pointSize]];
121   NSString* description =
122       base::SysUTF16ToNSString(controller_->CardDescription().description);
123   base::scoped_nsobject<NSAttributedString> detailsString(
124       [[NSAttributedString alloc]
125            initWithString:description
126                attributes:@{ NSParagraphStyleAttributeName : paragraphStyle }]);
128   [details setAttributedStringValue:detailsString];
131 - (void)performLayout {
132   base::scoped_nsobject<NSTextField> title([self makeTextField]);
133   base::scoped_nsobject<NSImageView> icon([[NSImageView alloc]
134       initWithFrame:NSZeroRect]);
135   base::scoped_nsobject<NSTextField> name([self makeTextField]);
136   base::scoped_nsobject<NSTextField> details([self makeTextField]);
137   base::scoped_nsobject<NSButton> link([[HyperlinkButtonCell buttonWithString:
138           base::SysUTF16ToNSString(controller_->LinkText())] retain]);
140   [link setTarget:self];
141   [link setAction:@selector(onLinkClicked:)];
143   // Use uniform font across all controls (except title).
144   [details setFont:[link font]];
145   [name setFont:[link font]];
146   [title setFont:[NSFont systemFontOfSize:15.0]];
148   // Populate fields.
149   const autofill::CreditCardDescription& card_desc =
150       controller_->CardDescription();
151   [title setStringValue:base::SysUTF16ToNSString(controller_->TitleText())];
152   [icon setImage:card_desc.icon.AsNSImage()];
153   [name setStringValue:base::SysUTF16ToNSString(card_desc.name)];
154   [self setDetailsStringForField:details];
156   // Size fields.
157   CGFloat bubbleWidth = autofill::NewCreditCardBubbleView::kContentsWidth;
158   [title sizeToFit];
159   bubbleWidth = std::max(bubbleWidth, NSWidth([title frame]) + 2 * kInset);
160   [icon setFrameSize:[[icon image] size]];
161   [name sizeToFit];
162   [details setFrameSize:[[details cell] cellSizeForBounds:
163       NSMakeRect(0, 0, bubbleWidth - 2 * kInset, CGFLOAT_MAX)]];
164   [link sizeToFit];
166   // Layout fields.
167   [link setFrameOrigin:NSMakePoint(kInset, kInset)];
168   [details setFrameOrigin:NSMakePoint(
169       kInset, NSMaxY([link frame]) + kVerticalSpacing)];
170   [icon setFrameOrigin:NSMakePoint(
171       kInset, NSMaxY([details frame]) + kVerticalSpacing)];
172   [name setFrameOrigin:NSMakePoint(
173       NSMaxX([icon frame]) + kHorizontalSpacing,
174       NSMidY([icon frame]) - (NSHeight([name frame]) / 2.0))];
175   [title setFrameOrigin:
176       NSMakePoint(kInset, NSMaxY([icon frame]) + kTitleSpacing)];
178   [[[self window] contentView] setSubviews:
179       @[ title, icon, name, details, link ]];
181   // Update window frame.
182   NSRect windowFrame = [[self window] frame];
183   windowFrame.size.height = NSMaxY([title frame]) + kInset;
184   windowFrame.size.width = bubbleWidth;
185   [[self window] setFrame:windowFrame display:NO];
188 - (void)onLinkClicked:(id)sender {
189   controller_->OnLinkClicked();
192 @end
195 namespace autofill {
197 NewCreditCardBubbleCocoa::~NewCreditCardBubbleCocoa() {
198   controller_->OnBubbleDestroyed();
201 void NewCreditCardBubbleCocoa::Show() {
202   NSView* browser_view =
203       controller_->web_contents()->GetView()->GetNativeView();
204   NSWindow* parent_window = [browser_view window];
205   BrowserWindowController* bwc = [BrowserWindowController
206       browserWindowControllerForWindow:parent_window];
208   if (!bubbleController_)
209     CreateCocoaController(parent_window);
211   NSPoint anchor_point;
212   NSView* anchor_view;
213   if ([bwc isTabbedWindow]) {
214     anchor_view = [[bwc toolbarController] wrenchButton];
215     anchor_point = NSMakePoint(
216         NSMidX([anchor_view bounds]),
217         NSMinY([anchor_view bounds]) + kWrenchBubblePointOffsetY);
218     [[bubbleController_ bubble] setArrowLocation:info_bubble::kTopRight];
219     [[bubbleController_ bubble] setAlignment:info_bubble::kAlignArrowToAnchor];
220   } else {
221     anchor_view = browser_view;
222     anchor_point = NSMakePoint(
223         NSMaxX([browser_view bounds]) - kAnchorlessEndPadding,
224         NSMaxY([browser_view bounds]) - kAnchorlessTopPadding);
225     [[bubbleController_ bubble] setArrowLocation:info_bubble::kNoArrow];
226     if (base::i18n::IsRTL()) {
227       anchor_point.x = NSMaxX([anchor_view bounds]) - anchor_point.x;
228       [[bubbleController_ bubble] setAlignment:
229           info_bubble::kAlignLeftEdgeToAnchorEdge];
230     } else {
231       [[bubbleController_ bubble] setAlignment:
232           info_bubble::kAlignRightEdgeToAnchorEdge];
233     }
234   }
235   if ([anchor_view isFlipped])
236     anchor_point.y = NSMaxY([anchor_view bounds]) - anchor_point.y;
237   anchor_point = [anchor_view convertPoint:anchor_point toView:nil];
239   NSRect frame = NSZeroRect;
240   frame.origin = anchor_point;
241   anchor_point = [parent_window convertBaseToScreen:anchor_point];
242   [bubbleController_ showAtAnchor:anchor_point];
245 void NewCreditCardBubbleCocoa::Hide() {
246   [bubbleController_ close];
249 // static
250 base::WeakPtr<NewCreditCardBubbleView> NewCreditCardBubbleView::Create(
251     NewCreditCardBubbleController* controller) {
252   NewCreditCardBubbleCocoa* bubble = new NewCreditCardBubbleCocoa(controller);
253   return bubble->weak_ptr_factory_.GetWeakPtr();
256 NewCreditCardBubbleCocoa::NewCreditCardBubbleCocoa(
257     NewCreditCardBubbleController* controller)
258     : bubbleController_(NULL),
259       controller_(controller),
260       weak_ptr_factory_(this) {
263 void NewCreditCardBubbleCocoa::CreateCocoaController(NSWindow* parent) {
264   DCHECK(!bubbleController_);
265   bubbleController_ = [[NewCreditCardBubbleControllerCocoa alloc]
266       initWithParentWindow:parent
267                 controller:controller_
268                     bridge:this];
271 InfoBubbleWindow* NewCreditCardBubbleCocoa::GetInfoBubbleWindow() {
272   return base::mac::ObjCCastStrict<InfoBubbleWindow>(
273       [bubbleController_ window]);
276 }  // namespace autofill