Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / autofill / autofill_notification_controller.mm
blob93590e30af1990ac0c2c141009ec1559e0a99c67
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 #import "chrome/browser/ui/cocoa/autofill/autofill_notification_controller.h"
7 #include <algorithm>
9 #include "base/logging.h"
10 #include "base/mac/foundation_util.h"
11 #include "base/mac/scoped_nsobject.h"
12 #include "base/strings/sys_string_conversions.h"
13 #include "chrome/browser/ui/autofill/autofill_dialog_types.h"
14 #include "chrome/browser/ui/autofill/autofill_dialog_view_delegate.h"
15 #include "chrome/browser/ui/chrome_style.h"
16 #include "chrome/browser/ui/cocoa/autofill/autofill_dialog_constants.h"
17 #import "chrome/browser/ui/cocoa/autofill/autofill_tooltip_controller.h"
18 #include "grit/theme_resources.h"
19 #include "skia/ext/skia_utils_mac.h"
20 #import "ui/base/cocoa/controls/hyperlink_text_view.h"
22 @interface AutofillNotificationView : NSView {
23  @private
24   base::scoped_nsobject<NSColor> backgroundColor_;
25   base::scoped_nsobject<NSColor> borderColor_;
28 @property (nonatomic, retain) NSColor* backgroundColor;
29 @property (nonatomic, retain) NSColor* borderColor;
31 @end
33 @implementation AutofillNotificationView
35 - (void)drawRect:(NSRect)dirtyRect {
36   [super drawRect:dirtyRect];
38   NSBezierPath* path;
39   NSRect bounds = [self bounds];
40   path = [NSBezierPath bezierPathWithRect:bounds];
42   [backgroundColor_ setFill];
43   [path fill];
44   [borderColor_ setStroke];
45   [path stroke];
48 - (NSColor*)backgroundColor {
49   return backgroundColor_;
52 - (void)setBackgroundColor:(NSColor*)backgroundColor {
53   backgroundColor_.reset([backgroundColor retain]);
56 - (NSColor*)borderColor {
57   return borderColor_;
60 - (void)setBorderColor:(NSColor*)borderColor {
61   borderColor_.reset([borderColor retain]);
64 @end
66 @implementation AutofillNotificationController
68 - (id)initWithNotification:(const autofill::DialogNotification*)notification
69                   delegate:(autofill::AutofillDialogViewDelegate*)delegate {
70   if (self = [super init]) {
71     delegate_ = delegate;
72     notificationType_ = notification->type();
74     base::scoped_nsobject<AutofillNotificationView> view(
75         [[AutofillNotificationView alloc] initWithFrame:NSZeroRect]);
76     [view setBackgroundColor:
77         gfx::SkColorToCalibratedNSColor(notification->GetBackgroundColor())];
78     [view setBorderColor:
79         gfx::SkColorToCalibratedNSColor(notification->GetBorderColor())];
80     [self setView:view];
82     textview_.reset([[HyperlinkTextView alloc] initWithFrame:NSZeroRect]);
83     NSColor* textColor =
84         gfx::SkColorToCalibratedNSColor(notification->GetTextColor());
85     [textview_ setMessage:base::SysUTF16ToNSString(notification->display_text())
86                  withFont:[NSFont labelFontOfSize:[[textview_ font] pointSize]]
87              messageColor:textColor];
88     if (!notification->link_range().is_empty()) {
89       [textview_ setDelegate:self];
90       [textview_ addLinkRange:notification->link_range().ToNSRange()
91                      withName:self
92                     linkColor:[NSColor blueColor]];
93       linkURL_ = notification->link_url();
94     }
96     tooltipController_.reset([[AutofillTooltipController alloc]
97                                  initWithArrowLocation:info_bubble::kTopRight]);
98     [tooltipController_ setImage:
99         ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
100             IDR_AUTOFILL_TOOLTIP_ICON).ToNSImage()];
101     [tooltipController_ setMessage:
102         base::SysUTF16ToNSString(notification->tooltip_text())];
103     [[tooltipController_ view] setHidden:
104         [[tooltipController_ message] length] == 0];
106     [view setSubviews:@[ textview_, [tooltipController_ view] ]];
107   }
108   return self;
111 - (AutofillNotificationView*)notificationView {
112   return base::mac::ObjCCastStrict<AutofillNotificationView>([self view]);
115 - (NSTextView*)textview {
116   return textview_;
119 - (NSView*)tooltipView {
120   return [tooltipController_ view];
123 - (NSSize)preferredSizeForWidth:(CGFloat)width {
124   width -= 2 * chrome_style::kHorizontalPadding;
125   if (![[tooltipController_ view] isHidden]) {
126     width -= NSWidth([[tooltipController_ view] frame]) +
127         chrome_style::kHorizontalPadding;
128   }
129   // TODO(isherman): Restore the DCHECK below once I figure out why it causes
130   // unit tests to fail.
131   //DCHECK_GT(width, 0);
133   NSSize preferredSize;
134   // This method is logically const. Hence, cache the original frame so that
135   // it can be restored once the preferred size has been computed.
136   NSRect frame = [textview_ frame];
138   // Compute preferred size.
139   [textview_ setFrameSize:NSMakeSize(width, frame.size.height)];
140   [textview_ setVerticallyResizable:YES];
141   [textview_ sizeToFit];
142   preferredSize = [textview_ frame].size;
144   // Restore original properties, since this method is logically const.
145   [textview_ setFrame:frame];
146   [textview_ setVerticallyResizable:NO];
148   preferredSize.height += 2 * autofill::kNotificationPadding;
149   return preferredSize;
152 - (NSSize)preferredSize {
153   NOTREACHED();
154   return NSZeroSize;
157 - (void)performLayout {
158   NSRect bounds = [[self view] bounds];
159   // Calculate the frame size, leaving room for padding around the notification,
160   // as well as for the tooltip if it is visible.
161   NSRect labelFrame = NSInsetRect(bounds,
162                                  chrome_style::kHorizontalPadding,
163                                  autofill::kNotificationPadding);
164   NSView* tooltipView = [tooltipController_ view];
165   if (![tooltipView isHidden]) {
166     labelFrame.size.width -=
167         NSWidth([tooltipView frame]) + chrome_style::kHorizontalPadding;
168   }
170   NSView* label = textview_.get();
171   [label setFrame:labelFrame];
173   if (![tooltipView isHidden]) {
174     NSPoint tooltipOrigin =
175         NSMakePoint(
176             NSMaxX(labelFrame) + chrome_style::kHorizontalPadding,
177             NSMidY(labelFrame) - (NSHeight([tooltipView frame]) / 2.0));
178     [tooltipView setFrameOrigin:tooltipOrigin];
179   }
182 - (BOOL)textView:(NSTextView *)textView
183    clickedOnLink:(id)link
184          atIndex:(NSUInteger)charIndex {
185   delegate_->LinkClicked(linkURL_);
186   return YES;
189 @end