OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #import "chrome/browser/ui/cocoa/autofill/autofill_notification_controller.h" | |
6 | |
7 #include <algorithm> | |
8 | |
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/components_scaled_resources.h" | |
19 #include "skia/ext/skia_utils_mac.h" | |
20 #import "ui/base/cocoa/controls/hyperlink_text_view.h" | |
21 | |
22 @interface AutofillNotificationView : NSView { | |
23 @private | |
24 base::scoped_nsobject<NSColor> backgroundColor_; | |
25 base::scoped_nsobject<NSColor> borderColor_; | |
26 } | |
27 | |
28 @property (nonatomic, retain) NSColor* backgroundColor; | |
29 @property (nonatomic, retain) NSColor* borderColor; | |
30 | |
31 @end | |
32 | |
33 @implementation AutofillNotificationView | |
34 | |
35 - (void)drawRect:(NSRect)dirtyRect { | |
36 [super drawRect:dirtyRect]; | |
37 | |
38 NSBezierPath* path; | |
39 NSRect bounds = [self bounds]; | |
40 path = [NSBezierPath bezierPathWithRect:bounds]; | |
41 | |
42 [backgroundColor_ setFill]; | |
43 [path fill]; | |
44 [borderColor_ setStroke]; | |
45 [path stroke]; | |
46 } | |
47 | |
48 - (NSColor*)backgroundColor { | |
49 return backgroundColor_; | |
50 } | |
51 | |
52 - (void)setBackgroundColor:(NSColor*)backgroundColor { | |
53 backgroundColor_.reset([backgroundColor retain]); | |
54 } | |
55 | |
56 - (NSColor*)borderColor { | |
57 return borderColor_; | |
58 } | |
59 | |
60 - (void)setBorderColor:(NSColor*)borderColor { | |
61 borderColor_.reset([borderColor retain]); | |
62 } | |
63 | |
64 @end | |
65 | |
66 @implementation AutofillNotificationController | |
67 | |
68 - (id)initWithNotification:(const autofill::DialogNotification*)notification | |
69 delegate:(autofill::AutofillDialogViewDelegate*)delegate { | |
70 if (self = [super init]) { | |
71 delegate_ = delegate; | |
72 notificationType_ = notification->type(); | |
73 | |
74 base::scoped_nsobject<AutofillNotificationView> view( | |
75 [[AutofillNotificationView alloc] initWithFrame:NSZeroRect]); | |
76 [view setBackgroundColor: | |
77 skia::SkColorToCalibratedNSColor(notification->GetBackgroundColor())]; | |
78 [view setBorderColor: | |
79 skia::SkColorToCalibratedNSColor(notification->GetBorderColor())]; | |
80 [self setView:view]; | |
81 | |
82 textview_.reset([[HyperlinkTextView alloc] initWithFrame:NSZeroRect]); | |
83 NSColor* textColor = | |
84 skia::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 linkURL_ = notification->link_url(); | |
90 [textview_ setDelegate:self]; | |
91 [textview_ addLinkRange:notification->link_range().ToNSRange() | |
92 withURL:base::SysUTF8ToNSString(linkURL_.spec()) | |
93 linkColor:[NSColor blueColor]]; | |
94 } | |
95 | |
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]; | |
105 | |
106 [view setSubviews:@[ textview_, [tooltipController_ view] ]]; | |
107 } | |
108 return self; | |
109 } | |
110 | |
111 - (AutofillNotificationView*)notificationView { | |
112 return base::mac::ObjCCastStrict<AutofillNotificationView>([self view]); | |
113 } | |
114 | |
115 - (NSTextView*)textview { | |
116 return textview_; | |
117 } | |
118 | |
119 - (NSView*)tooltipView { | |
120 return [tooltipController_ view]; | |
121 } | |
122 | |
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); | |
132 | |
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]; | |
137 | |
138 // Compute preferred size. | |
139 [textview_ setFrameSize:NSMakeSize(width, frame.size.height)]; | |
140 [textview_ setVerticallyResizable:YES]; | |
141 [textview_ sizeToFit]; | |
142 preferredSize = [textview_ frame].size; | |
143 | |
144 // Restore original properties, since this method is logically const. | |
145 [textview_ setFrame:frame]; | |
146 [textview_ setVerticallyResizable:NO]; | |
147 | |
148 preferredSize.height += 2 * autofill::kNotificationPadding; | |
149 return preferredSize; | |
150 } | |
151 | |
152 - (NSSize)preferredSize { | |
153 NOTREACHED(); | |
154 return NSZeroSize; | |
155 } | |
156 | |
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 } | |
169 | |
170 NSView* label = textview_.get(); | |
171 [label setFrame:labelFrame]; | |
172 | |
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 } | |
180 } | |
181 | |
182 - (BOOL)textView:(NSTextView *)textView | |
183 clickedOnLink:(id)link | |
184 atIndex:(NSUInteger)charIndex { | |
185 delegate_->LinkClicked(linkURL_); | |
186 return YES; | |
187 } | |
188 | |
189 @end | |
OLD | NEW |