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

Side by Side Diff: chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.mm

Issue 11740033: [Autofill] Add Mac implementation for the in-browser process popup view. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Screen handling Created 7 years, 11 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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_popup_view_cocoa.h"
6
7 #include "base/i18n/rtl.h"
8 #include "base/logging.h"
9 #include "base/sys_string_conversions.h"
10 #include "chrome/browser/ui/autofill/autofill_popup_controller.h"
11 #include "chrome/browser/ui/cocoa/autofill/autofill_popup_view_mac.h"
12 #include "grit/ui_resources.h"
13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAutofillClient.h"
14 #include "ui/base/resource/resource_bundle.h"
15 #include "ui/gfx/image/image.h"
16 #include "ui/gfx/point.h"
17 #include "ui/gfx/rect.h"
18
19 namespace {
20
21 NSColor* BorderColor() {
22 // TODO(isherman): This color does not match the other platforms, but it
23 // matches what the existing UI on Mac has as the color. The other platforms
24 // have a strange color: the RGB values are almost, but not quite, identical
25 // to each other.
26 // TODO(isherman): Maybe use a system color for this?
27 return [NSColor colorWithCalibratedRed:127/255.0
28 green:157/255.0
29 blue:185/255.0
30 alpha:1.0];
31 }
32
33 NSColor* SeparatorColor() {
34 return [NSColor colorWithCalibratedWhite:220/255.0 alpha:1];
Nico 2013/01/11 16:27:38 spaces around /
Ilya Sherman 2013/01/11 23:32:26 Done.
35 }
36
37 NSColor* HighlightColor() {
38 return [NSColor colorWithCalibratedWhite:(205 / 255.0) alpha:1];
Nico 2013/01/11 16:27:38 no parens
Ilya Sherman 2013/01/11 23:32:26 Done.
39 }
40
41 } // anonymous namespace
42
43 #pragma mark -
44 #pragma mark Private methods
45
46 @interface AutofillPopupViewCocoa ()
47
48 // Draws a thin separator in the popup UI.
49 - (void)drawSeparatorWithBounds:(NSRect)bounds;
50
51 // Draws an Autofill suggestion in the given |bounds|, labeled with the given
52 // |name| and |subtext| hint. If the suggestion |isSelected|, then it is drawn
53 // with a highlight. Some suggestions -- such as for credit cards -- might also
54 // include an |icon| -- e.g. for the card type. Finally, if |canDelete| is
55 // true, a delete icon is also drawn.
56 - (void)drawSuggestionWithName:(NSString*)name
57 subtext:(NSString*)subtext
58 icon:(NSImage*)icon
59 bounds:(NSRect)bounds
60 selected:(BOOL)isSelected
61 canDelete:(BOOL)canDelete;
62
63 // Returns the icon for the row with the given |index|, or |nil| if there is
64 // none.
65 - (NSImage*)iconAtIndex:(size_t)index;
66
67 @end
68
69 @implementation AutofillPopupViewCocoa
70
71 #pragma mark -
72 #pragma mark Initialisers
73
74 - (id)initWithFrame:(NSRect)frame {
75 NOTREACHED();
76 return [self initWithController:NULL frame:frame];
77 }
78
79 - (id)initWithController:(AutofillPopupController*)controller
80 frame:(NSRect)frame {
81 self = [super initWithFrame:frame];
82 if (self)
83 controller_ = controller;
84
85 return self;
86 }
87
88 #pragma mark -
89 #pragma mark NSView implementation:
90
91 // A slight optimization for drawing:
92 // https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Cocoa ViewsGuide/Optimizing/Optimizing.html
93 - (BOOL)isOpaque {
94 return YES;
95 }
96
97 - (BOOL)isFlipped {
98 // Flipped so that it's easier to share controller logic with other OSes.
99 return YES;
100 }
101
102 - (void)drawRect:(NSRect)dirtyRect {
103 // If the view is in the process of being destroyed, don't bother drawing.
104 if (!controller_)
105 return;
106
107 // TODO(isherman): Is there a better way to leave room for the border?
108 // TODO(isherman): Drawing the border as part of the content view means that
109 // the rest of the content has to be careful not to overlap the border.
110 // Should the border be part of the window instead? If not, should the rest
111 // of the view be a subview? Or should I just draw the window content
112 // carefully?
113 NSRect borderRect = NSInsetRect([self bounds], 0.5, 0.5);
114 NSBezierPath* border = [NSBezierPath bezierPathWithRect:borderRect];
115
116 [[NSColor whiteColor] set];
117 [border fill];
118
119 // TODO(isherman): This color does not match the other platforms, but it
120 // matches what the existing UI on Mac has as the color. The other platforms
121 // have a strange color: the RGB values are almost, but not quite, identical
122 // to each other.
123 // TODO(isherman): Maybe use a system color for this?
124 [BorderColor() set];
125 [border stroke];
Nico 2013/01/11 16:27:38 Is there any chance to move all drawing to assets?
Ilya Sherman 2013/01/11 23:32:26 Sorry, I don't understand the question :/ Could y
Nico 2013/01/11 23:40:12 Loading bitmap resources and drawing them, so that
126
127 for (size_t i = 0; i < controller_->names().size(); ++i) {
128 // Skip rows outside of the dirty rect.
129 NSRect rowBounds =
130 NSRectFromCGRect(controller_->GetRowBounds(i).ToCGRect());
131 if (!NSIntersectsRect(rowBounds, dirtyRect))
132 continue;
133
134 if (controller_->identifiers()[i] ==
135 WebKit::WebAutofillClient::MenuItemIDSeparator) {
136 [self drawSeparatorWithBounds:rowBounds];
137 } else {
138 NSString* name = SysUTF16ToNSString(controller_->names()[i]);
139 NSString* subtext = SysUTF16ToNSString(controller_->subtexts()[i]);
140 BOOL isSelected = static_cast<int>(i) == controller_->selected_line();
141 [self drawSuggestionWithName:name
142 subtext:subtext
143 icon:[self iconAtIndex:i]
144 bounds:rowBounds
145 selected:isSelected
146 canDelete:controller_->CanDelete(i)];
147 }
148 }
149 }
150
151 - (void)mouseUp:(NSEvent*)theEvent {
152 // If the view is in the process of being destroyed, abort.
153 if (!controller_)
154 return;
155
156 NSPoint location = [self convertPoint:[theEvent locationInWindow]
157 fromView:nil];
158
159 if (NSPointInRect(location, [self bounds])) {
160 controller_->MouseClicked(static_cast<int>(location.x),
161 static_cast<int>(location.y));
162 }
163 }
164
165 - (void)mouseMoved:(NSEvent*)theEvent {
166 // If the view is in the process of being destroyed, abort.
167 if (!controller_)
168 return;
169
170 NSPoint location = [self convertPoint:[theEvent locationInWindow]
171 fromView:nil];
172
173 controller_->MouseHovered(static_cast<int>(location.x),
174 static_cast<int>(location.y));
175 }
176
177 - (void)mouseDragged:(NSEvent*)theEvent {
178 [self mouseMoved:theEvent];
179 }
180
181 - (void)mouseExited:(NSEvent*)theEvent {
182 // If the view is in the process of being destroyed, abort.
183 if (!controller_)
184 return;
185
186 controller_->MouseExitedPopup();
187 }
188
189 #pragma mark -
190 #pragma mark Public API:
191
192 - (void)controllerDestroyed {
193 // Since the |controller_| either already has been destroyed or is about to
194 // be, about the only thing we can safely do with it is to null it out.
195 controller_ = NULL;
196 }
197
198 #pragma mark -
199 #pragma mark Private API:
200
201 - (void)drawSeparatorWithBounds:(NSRect)bounds {
202 [SeparatorColor() set];
203 [NSBezierPath fillRect:bounds];
204 }
205
206 - (void)drawSuggestionWithName:(NSString*)name
207 subtext:(NSString*)subtext
208 icon:(NSImage*)icon
209 bounds:(NSRect)bounds
210 selected:(BOOL)isSelected
211 canDelete:(BOOL)canDelete {
212 // If this row is selected, highlight it.
213 if (isSelected) {
214 // TODO(isherman): The highlight color should match the system highlight
215 // color. Maybe use controlHighlightColor or selectedTextBackgroundColor
216 // for this?
217 [HighlightColor() set];
218 [NSBezierPath fillRect:bounds];
219 }
220
221 BOOL isRTL = base::i18n::IsRTL();
Nico 2013/01/11 16:27:38 We don't really support RTL anywhere else (just sa
Ilya Sherman 2013/01/11 23:32:26 The (WebKit) UI this is replacing supports RTL, so
Nico 2013/01/11 23:40:12 OS X didn't support it until 10.8 (or 7?) as far a
Scott Hess - ex-Googler 2013/01/11 23:56:56 Do we have any idea how often the RTL is in use?
222
223 // TODO(isherman): Set font, colors, and any other appropriate attributes.
224 NSSize nameSize = [name sizeWithAttributes:nil];
225 CGFloat x = bounds.origin.x +
226 (isRTL ?
227 bounds.size.width - AutofillPopupView::kEndPadding - nameSize.width:
228 AutofillPopupView::kEndPadding);
229 CGFloat y = bounds.origin.y + (bounds.size.height - nameSize.height) / 2;
230
231 [name drawAtPoint:NSMakePoint(x, y) withAttributes:nil];
232
233 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
234
235 // The x-coordinate will be updated as each element is drawn.
236 x = bounds.origin.x +
237 (isRTL ?
238 AutofillPopupView::kEndPadding :
239 bounds.size.width - AutofillPopupView::kEndPadding);
240
241 // Draw the delete icon, if one is needed.
Nico 2013/01/11 16:27:38 Shouldn't this be a subview?
Ilya Sherman 2013/01/11 23:32:26 What's the advantage? In general, I'm not sure wh
Nico 2013/01/11 23:40:12 Abstraction, less code, composability and so on.
Scott Hess - ex-Googler 2013/01/11 23:56:56 If you're already manually drawing and manually po
242 if (canDelete) {
243 // TODO(csharp): Create a custom resource for the delete icon.
244 // http://crbug.com/131801
245 NSImage* deleteIcon;
246 if (isSelected && controller_->delete_icon_hovered())
247 deleteIcon = rb.GetNativeImageNamed(IDR_CLOSE_BAR_H).ToNSImage();
248 else
249 deleteIcon = rb.GetNativeImageNamed(IDR_CLOSE_BAR).ToNSImage();
250
251 NSSize iconSize = [deleteIcon size];
252 x += isRTL ? 0 : -iconSize.width;
253 y = bounds.origin.y + (bounds.size.height - iconSize.height) / 2;
254 [deleteIcon drawInRect:NSMakeRect(x, y, iconSize.width, iconSize.height)
255 fromRect:NSZeroRect
256 operation:NSCompositeSourceOver
257 fraction:1.0
258 respectFlipped:YES
259 hints:nil];
260
261 x += isRTL ?
262 iconSize.width + AutofillPopupView::kIconPadding :
263 -AutofillPopupView::kIconPadding;
264 }
265
266 // Draw the Autofill icon, if one exists.
267 if (icon) {
268 NSSize iconSize = [icon size];
269 x += isRTL ? 0 : -iconSize.width;
270 y = bounds.origin.y + (bounds.size.height - iconSize.height) / 2;
271 [icon drawInRect:NSMakeRect(x, y, iconSize.width, iconSize.height)
272 fromRect:NSZeroRect
273 operation:NSCompositeSourceOver
274 fraction:1.0
275 respectFlipped:YES
276 hints:nil];
277
278 x += isRTL ?
279 iconSize.width + AutofillPopupView::kIconPadding :
280 -AutofillPopupView::kIconPadding;
281 }
282
283 // Draw the subtext.
284 NSSize subtextSize = [subtext sizeWithAttributes:nil];
285 x += isRTL ? 0 : -subtextSize.width;
286 y = bounds.origin.y + (bounds.size.height - subtextSize.height) / 2;
287
288 [subtext drawAtPoint:NSMakePoint(x, y) withAttributes:nil];
289 }
290
291 - (NSImage*)iconAtIndex:(size_t)index {
292 if (controller_->icons()[index].empty())
293 return nil;
294
295 int iconId = controller_->GetIconResourceID(controller_->icons()[index]);
296 DCHECK_NE(-1, iconId);
297
298 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
299 return rb.GetNativeImageNamed(iconId).ToNSImage();
300 }
301
302 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698