Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / autofill / autofill_popup_view_cocoa.mm
blob356f79584bb0b76af00e593ea71c498b0ac036d9
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.
5 #import "chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.h"
7 #include "base/logging.h"
8 #include "base/strings/sys_string_conversions.h"
9 #include "chrome/browser/ui/autofill/autofill_popup_controller.h"
10 #include "chrome/browser/ui/autofill/popup_constants.h"
11 #include "chrome/browser/ui/cocoa/autofill/autofill_popup_view_bridge.h"
12 #include "components/autofill/core/browser/popup_item_ids.h"
13 #include "grit/ui_resources.h"
14 #include "ui/base/resource/resource_bundle.h"
15 #include "ui/gfx/font_list.h"
16 #include "ui/gfx/image/image.h"
17 #include "ui/gfx/point.h"
18 #include "ui/gfx/rect.h"
20 using autofill::AutofillPopupView;
22 namespace {
24 NSColor* BackgroundColor() {
25   return [NSColor whiteColor];
28 // The color of the border around the popup.
29 NSColor* BorderColor() {
30   return [NSColor colorForControlTint:[NSColor currentControlTint]];
33 NSColor* SeparatorColor() {
34   return [NSColor colorWithCalibratedWhite:220 / 255.0 alpha:1];
37 NSColor* HighlightColor() {
38   return [NSColor selectedControlColor];
41 NSColor* NameColor() {
42   return [NSColor blackColor];
45 NSColor* WarningColor() {
46   return [NSColor grayColor];
49 NSColor* SubtextColor() {
50   return [NSColor grayColor];
53 }  // namespace
55 #pragma mark -
56 #pragma mark Private methods
58 @interface AutofillPopupViewCocoa ()
60 // Draws a thin separator in the popup UI.
61 - (void)drawSeparatorWithBounds:(NSRect)bounds;
63 // Draws an Autofill suggestion in the given |bounds|, labeled with the given
64 // |name| and |subtext| hint.  If the suggestion |isSelected|, then it is drawn
65 // with a highlight.  |index| determines the font to use, as well as the icon,
66 // if the row requires it -- such as for credit cards.
67 - (void)drawSuggestionWithName:(NSString*)name
68                        subtext:(NSString*)subtext
69                          index:(size_t)index
70                         bounds:(NSRect)bounds
71                       selected:(BOOL)isSelected;
73 // Returns the icon for the row with the given |index|, or |nil| if there is
74 // none.
75 - (NSImage*)iconAtIndex:(size_t)index;
77 @end
79 @implementation AutofillPopupViewCocoa
81 #pragma mark -
82 #pragma mark Initialisers
84 - (id)initWithFrame:(NSRect)frame {
85   NOTREACHED();
86   return [self initWithController:NULL frame:frame];
89 - (id)initWithController:(autofill::AutofillPopupController*)controller
90                    frame:(NSRect)frame {
91   self = [super initWithFrame:frame];
92   if (self)
93     controller_ = controller;
95   return self;
98 #pragma mark -
99 #pragma mark NSView implementation:
101 // A slight optimization for drawing:
102 // https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaViewsGuide/Optimizing/Optimizing.html
103 - (BOOL)isOpaque {
104   return YES;
107 - (BOOL)isFlipped {
108   // Flipped so that it's easier to share controller logic with other OSes.
109   return YES;
112 - (void)drawRect:(NSRect)dirtyRect {
113   // If the view is in the process of being destroyed, don't bother drawing.
114   if (!controller_)
115     return;
117   // Draw the popup's background and border.
118   // The inset is needed since the border is centered on the |path|.
119   // TODO(isherman): We should consider using asset-based drawing for the
120   // border, creating simple bitmaps for the view's border and background, and
121   // drawing them using NSDrawNinePartImage().
122   CGFloat inset = autofill::kPopupBorderThickness / 2.0;
123   NSRect borderRect = NSInsetRect([self bounds], inset, inset);
124   NSBezierPath* path = [NSBezierPath bezierPathWithRect:borderRect];
125   [BackgroundColor() setFill];
126   [path fill];
127   [path setLineWidth:autofill::kPopupBorderThickness];
128   [BorderColor() setStroke];
129   [path stroke];
131   for (size_t i = 0; i < controller_->names().size(); ++i) {
132     // Skip rows outside of the dirty rect.
133     NSRect rowBounds =
134         NSRectFromCGRect(controller_->GetRowBounds(i).ToCGRect());
135     if (!NSIntersectsRect(rowBounds, dirtyRect))
136       continue;
138     if (controller_->identifiers()[i] == autofill::POPUP_ITEM_ID_SEPARATOR) {
139       [self drawSeparatorWithBounds:rowBounds];
140     } else {
141       NSString* name = SysUTF16ToNSString(controller_->names()[i]);
142       NSString* subtext = SysUTF16ToNSString(controller_->subtexts()[i]);
143       BOOL isSelected = static_cast<int>(i) == controller_->selected_line();
144       [self drawSuggestionWithName:name
145                            subtext:subtext
146                              index:i
147                             bounds:rowBounds
148                           selected:isSelected];
149     }
150   }
153 - (void)mouseUp:(NSEvent*)theEvent {
154   // If the view is in the process of being destroyed, abort.
155   if (!controller_)
156     return;
158   NSPoint location = [self convertPoint:[theEvent locationInWindow]
159                                fromView:nil];
161   if (NSPointInRect(location, [self bounds])) {
162     controller_->SetSelectionAtPoint(gfx::Point(NSPointToCGPoint(location)));
163     controller_->AcceptSelectedLine();
164   }
167 - (void)mouseMoved:(NSEvent*)theEvent {
168   // If the view is in the process of being destroyed, abort.
169   if (!controller_)
170     return;
172   NSPoint location = [self convertPoint:[theEvent locationInWindow]
173                                fromView:nil];
175   controller_->SetSelectionAtPoint(gfx::Point(NSPointToCGPoint(location)));
178 - (void)mouseDragged:(NSEvent*)theEvent {
179   [self mouseMoved:theEvent];
182 - (void)mouseExited:(NSEvent*)theEvent {
183   // If the view is in the process of being destroyed, abort.
184   if (!controller_)
185     return;
187   controller_->SelectionCleared();
190 #pragma mark -
191 #pragma mark Public API:
193 - (void)controllerDestroyed {
194   // Since the |controller_| either already has been destroyed or is about to
195   // be, about the only thing we can safely do with it is to null it out.
196   controller_ = NULL;
199 #pragma mark -
200 #pragma mark Private API:
202 - (void)drawSeparatorWithBounds:(NSRect)bounds {
203   [SeparatorColor() set];
204   [NSBezierPath fillRect:bounds];
207 - (void)drawSuggestionWithName:(NSString*)name
208                        subtext:(NSString*)subtext
209                          index:(size_t)index
210                         bounds:(NSRect)bounds
211                       selected:(BOOL)isSelected {
212   // If this row is selected, highlight it.
213   if (isSelected) {
214     [HighlightColor() set];
215     [NSBezierPath fillRect:bounds];
216   }
218   BOOL isRTL = controller_->IsRTL();
220   NSColor* nameColor =
221       controller_->IsWarning(index) ? WarningColor() : NameColor();
222   NSDictionary* nameAttributes =
223       [NSDictionary dictionaryWithObjectsAndKeys:
224            controller_->GetNameFontListForRow(index).GetPrimaryFont().
225                GetNativeFont(),
226            NSFontAttributeName, nameColor, NSForegroundColorAttributeName,
227            nil];
228   NSSize nameSize = [name sizeWithAttributes:nameAttributes];
229   CGFloat x = bounds.origin.x +
230       (isRTL ?
231        bounds.size.width - AutofillPopupView::kEndPadding - nameSize.width :
232        AutofillPopupView::kEndPadding);
233   CGFloat y = bounds.origin.y + (bounds.size.height - nameSize.height) / 2;
235   [name drawAtPoint:NSMakePoint(x, y) withAttributes:nameAttributes];
237   // The x-coordinate will be updated as each element is drawn.
238   x = bounds.origin.x +
239       (isRTL ?
240        AutofillPopupView::kEndPadding :
241        bounds.size.width - AutofillPopupView::kEndPadding);
243   // Draw the Autofill icon, if one exists.
244   NSImage* icon = [self iconAtIndex:index];
245   if (icon) {
246     NSSize iconSize = [icon size];
247     x += isRTL ? 0 : -iconSize.width;
248     y = bounds.origin.y + (bounds.size.height - iconSize.height) / 2;
249     [icon drawInRect:NSMakeRect(x, y, iconSize.width, iconSize.height)
250             fromRect:NSZeroRect
251            operation:NSCompositeSourceOver
252             fraction:1.0
253       respectFlipped:YES
254                hints:nil];
256     x += isRTL ?
257         iconSize.width + AutofillPopupView::kIconPadding :
258         -AutofillPopupView::kIconPadding;
259   }
261   // Draw the subtext.
262   NSDictionary* subtextAttributes =
263       [NSDictionary dictionaryWithObjectsAndKeys:
264            controller_->subtext_font_list().GetPrimaryFont().GetNativeFont(),
265            NSFontAttributeName, SubtextColor(), NSForegroundColorAttributeName,
266            nil];
267   NSSize subtextSize = [subtext sizeWithAttributes:subtextAttributes];
268   x += isRTL ? 0 : -subtextSize.width;
269   y = bounds.origin.y + (bounds.size.height - subtextSize.height) / 2;
271   [subtext drawAtPoint:NSMakePoint(x, y) withAttributes:subtextAttributes];
274 - (NSImage*)iconAtIndex:(size_t)index {
275   if (controller_->icons()[index].empty())
276     return nil;
278   int iconId = controller_->GetIconResourceID(controller_->icons()[index]);
279   DCHECK_NE(-1, iconId);
281   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
282   return rb.GetNativeImageNamed(iconId).ToNSImage();
285 @end