NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / autofill / generated_credit_card_bubble_cocoa.mm
blob4ce551405e91ef2c7ab8f1376814c38713ca3999
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/generated_credit_card_bubble_cocoa.h"
7 #include "base/mac/foundation_util.h"
8 #include "base/mac/scoped_nsobject.h"
9 #include "base/strings/sys_string_conversions.h"
10 #include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
11 #include "chrome/browser/ui/autofill/generated_credit_card_bubble_view.h"
12 #import "chrome/browser/ui/cocoa/base_bubble_controller.h"
13 #import "chrome/browser/ui/cocoa/hyperlink_text_view.h"
14 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
15 #import "chrome/browser/ui/cocoa/info_bubble_window.h"
16 #include "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
17 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
18 #include "content/public/browser/web_contents_view.h"
19 #include "skia/ext/skia_utils_mac.h"
20 #include "ui/base/cocoa/window_size_constants.h"
21 #include "ui/native_theme/native_theme.h"
23 using autofill::GeneratedCreditCardBubbleCocoa;
25 namespace {
27 const CGFloat kTitlePadding = 20.0;
28 const CGFloat kInset = 20.0;
30 }  // namespace
32 // The Cocoa side of the bubble controller.
33 @interface GeneratedCreditCardBubbleControllerCocoa :
34     BaseBubbleController<NSTextViewDelegate> {
36   // Bridge to C++ side.
37   scoped_ptr<GeneratedCreditCardBubbleCocoa> bridge_;
40 - (id)initWithParentWindow:(NSWindow*)parentWindow
41                     bridge:(GeneratedCreditCardBubbleCocoa*)bridge;
43 // Show the bubble at the given |anchor| point. Coordinates are in screen space.
44 - (void)showAtAnchor:(NSPoint)anchor;
46 // Return true if the bubble is in the process of hiding.
47 - (BOOL)isHiding;
49 // Build the window contents and lay them out.
50 - (void)performLayoutWithController:
51       (autofill::GeneratedCreditCardBubbleController*)controller;
53 @end
56 @implementation GeneratedCreditCardBubbleControllerCocoa
58 - (id)initWithParentWindow:(NSWindow*)parentWindow
59                     bridge:(GeneratedCreditCardBubbleCocoa*)bridge {
60   DCHECK(bridge);
61   base::scoped_nsobject<InfoBubbleWindow> window(
62       [[InfoBubbleWindow alloc]
63           initWithContentRect:ui::kWindowSizeDeterminedLater
64                     styleMask:NSBorderlessWindowMask
65                       backing:NSBackingStoreBuffered
66                         defer:NO]);
67   if ((self = [super initWithWindow:window
68                        parentWindow:parentWindow
69                          anchoredAt:NSZeroPoint])) {
70     [window setCanBecomeKeyWindow:NO];
71     bridge_.reset(bridge);
73     ui::NativeTheme* nativeTheme = ui::NativeTheme::instance();
74     [[self bubble] setAlignment:info_bubble::kAlignArrowToAnchor];
75     [[self bubble] setArrowLocation:info_bubble::kTopRight];
76     [[self bubble] setBackgroundColor:
77         gfx::SkColorToCalibratedNSColor(nativeTheme->GetSystemColor(
78             ui::NativeTheme::kColorId_DialogBackground))];
79     [self performLayoutWithController:bridge->controller().get()];
80   }
81   return self;
84 - (void)windowWillClose:(NSNotification*)notification {
85   bridge_->OnBubbleClosing();
86   [super windowWillClose:notification];
89 // Called when embedded links are clicked.
90 - (BOOL)textView:(NSTextView*)textView
91    clickedOnLink:(id)link
92          atIndex:(NSUInteger)charIndex {
93   bridge_->OnLinkClicked();
94   return YES;
97 - (void)showAtAnchor:(NSPoint)anchorPoint {
98   [self setAnchorPoint:anchorPoint];
99   [self showWindow:nil];
102 - (BOOL)isHiding {
103   InfoBubbleWindow* window =
104       base::mac::ObjCCastStrict<InfoBubbleWindow>([self window]);
105   return [window isClosing];
109 - (void)performLayoutWithController:
110     (autofill::GeneratedCreditCardBubbleController*)controller {
111   CGFloat bubbleWidth = autofill::GeneratedCreditCardBubbleView::kContentsWidth;
113   // Build the bubble title.
114   NSFont* titleFont = [NSFont systemFontOfSize:15.0];
115   NSString* title = base::SysUTF16ToNSString(controller->TitleText());
116   base::scoped_nsobject<NSTextField> titleView(
117     [[NSTextField alloc] initWithFrame:NSZeroRect]);
118   [titleView setDrawsBackground:NO];
119   [titleView setBezeled:NO];
120   [titleView setEditable:NO];
121   [titleView setSelectable:NO];
122   [titleView setStringValue:title];
123   [titleView setFont:titleFont];
124   [titleView sizeToFit];
126   bubbleWidth = std::max(bubbleWidth, NSWidth([titleView frame]) + 2 * kInset);
128   // Build the contents view.
129   base::scoped_nsobject<HyperlinkTextView> contentsView(
130       [[HyperlinkTextView alloc] initWithFrame:NSZeroRect]);
132   [contentsView setEditable:NO];
133   [contentsView setDelegate:self];
135   NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
136   NSFont* boldFont = [NSFont boldSystemFontOfSize:[NSFont systemFontSize]];
137   [contentsView setMessage:base::SysUTF16ToNSString(controller->ContentsText())
138                   withFont:font
139               messageColor:[NSColor blackColor]];
141   const std::vector<autofill::TextRange>& text_ranges =
142       controller->ContentsTextRanges();
143   for (size_t i = 0; i < text_ranges.size(); ++i) {
144     NSRange range = text_ranges[i].range.ToNSRange();
145     if (text_ranges[i].is_link) {
146       [contentsView addLinkRange:range
147                         withName:@(i)
148                        linkColor:[NSColor blueColor]];
149     } else {
150        [[contentsView textStorage]
151            addAttributes:@{ NSFontAttributeName : boldFont }
152                    range:range];
153     }
154   }
156   [contentsView setVerticallyResizable:YES];
157   [contentsView setFrameSize:NSMakeSize(bubbleWidth - 2 * kInset, CGFLOAT_MAX)];
158   [contentsView sizeToFit];
160   // Sizes are computed, now lay out the individual parts.
161   [contentsView setFrameOrigin:NSMakePoint(kInset, kInset)];
162   [titleView setFrameOrigin:
163       NSMakePoint(kInset, NSMaxY([contentsView frame]) + kTitlePadding)];
164   [[[self window] contentView] setSubviews:@[ contentsView, titleView ]];
166   // Update window frame.
167   NSRect windowFrame = [[self window] frame];
168   windowFrame.size =
169       NSMakeSize(bubbleWidth, NSMaxY([titleView frame]) + kInset);
170   [[self window] setFrame:windowFrame display:YES];
173 @end
176 namespace autofill {
178 // static
179 base::WeakPtr<GeneratedCreditCardBubbleView>
180     GeneratedCreditCardBubbleView::Create(
181         const base::WeakPtr<GeneratedCreditCardBubbleController>& controller) {
182   return (new GeneratedCreditCardBubbleCocoa(controller))->weak_ptr_factory_.
183       GetWeakPtr();
186 GeneratedCreditCardBubbleCocoa::GeneratedCreditCardBubbleCocoa(
187     const base::WeakPtr<GeneratedCreditCardBubbleController>& controller)
188     : bubbleController_(nil),
189       controller_(controller),
190       weak_ptr_factory_(this) {
193 GeneratedCreditCardBubbleCocoa::~GeneratedCreditCardBubbleCocoa() {}
195 void GeneratedCreditCardBubbleCocoa::Show() {
196   DCHECK(controller_.get());
197   NSView* browser_view =
198       controller_->web_contents()->GetView()->GetNativeView();
199   NSWindow* parent_window = [browser_view window];
200   LocationBarViewMac* location_bar =
201       [[parent_window windowController] locationBarBridge];
203   // |location_bar| can be NULL during initialization stages.
204   if (!location_bar) {
205     // Technically, Show() should never be called during initialization.
206     NOTREACHED();
208     delete this;
209     return;
210   }
212   if (!bubbleController_) {
213     bubbleController_ = [[GeneratedCreditCardBubbleControllerCocoa alloc]
214         initWithParentWindow:parent_window
215                       bridge:this];
216   }
218   // |bubbleController_| is supposed to take ownership of |this|. If it can't be
219   // constructed, clean up and abort showing.
220   if (!bubbleController_) {
221     delete this;
222     return;
223   }
225   NSPoint anchor = location_bar->GetGeneratedCreditCardBubblePoint();
226   [bubbleController_ showAtAnchor:[parent_window convertBaseToScreen:anchor]];
229 void GeneratedCreditCardBubbleCocoa::Hide() {
230   [bubbleController_ close];
233 bool GeneratedCreditCardBubbleCocoa::IsHiding() const {
234   return [bubbleController_ isHiding];
237 void GeneratedCreditCardBubbleCocoa::OnBubbleClosing() {
238   bubbleController_ = nil;
241 void GeneratedCreditCardBubbleCocoa::OnLinkClicked() {
242   if (controller_)
243     controller_->OnLinkClicked();
246 }  // autofill