Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / autofill / autofill_popup_view_cocoa.mm
blob53abdfa34c4576a4ddbb7113116d84d3ec58884a
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 "components/autofill/core/browser/suggestion.h"
14 #include "ui/base/cocoa/window_size_constants.h"
15 #include "ui/base/resource/resource_bundle.h"
16 #include "ui/gfx/font_list.h"
17 #include "ui/gfx/geometry/point.h"
18 #include "ui/gfx/geometry/rect.h"
19 #include "ui/gfx/image/image.h"
21 using autofill::AutofillPopupView;
23 @interface AutofillPopupViewCocoa ()
25 #pragma mark -
26 #pragma mark Private methods
28 // Draws an Autofill suggestion in the given |bounds|, labeled with the given
29 // |name| and |subtext| hint.  If the suggestion |isSelected|, then it is drawn
30 // with a highlight.  |index| determines the font to use, as well as the icon,
31 // if the row requires it -- such as for credit cards.
32 - (void)drawSuggestionWithName:(NSString*)name
33                        subtext:(NSString*)subtext
34                          index:(size_t)index
35                         bounds:(NSRect)bounds
36                       selected:(BOOL)isSelected
37                    textYOffset:(CGFloat)textYOffset;
39 // This comment block applies to all three draw* methods that follow.
40 // If |rightAlign| == YES.
41 //   Draws the widget with right border aligned to |x|.
42 //   Returns the x value of left border of the widget.
43 // If |rightAlign| == NO.
44 //   Draws the widget with left border aligned to |x|.
45 //   Returns the x value of right border of the widget.
46 - (CGFloat)drawName:(NSString*)name
47                 atX:(CGFloat)x
48               index:(size_t)index
49          rightAlign:(BOOL)rightAlign
50              bounds:(NSRect)bounds
51         textYOffset:(CGFloat)textYOffset;
52 - (CGFloat)drawIconAtIndex:(size_t)index
53                        atX:(CGFloat)x
54                 rightAlign:(BOOL)rightAlign
55                     bounds:(NSRect)bounds;
56 - (CGFloat)drawSubtext:(NSString*)subtext
57                    atX:(CGFloat)x
58             rightAlign:(BOOL)rightAlign
59                 bounds:(NSRect)bounds
60            textYOffset:(CGFloat)textYOffset;
62 // Returns the icon for the row with the given |index|, or |nil| if there is
63 // none.
64 - (NSImage*)iconAtIndex:(size_t)index;
66 @end
68 @implementation AutofillPopupViewCocoa
70 #pragma mark -
71 #pragma mark Initialisers
73 - (id)initWithFrame:(NSRect)frame {
74   NOTREACHED();
75   return [self initWithController:NULL frame:frame];
78 - (id)initWithController:(autofill::AutofillPopupController*)controller
79                    frame:(NSRect)frame {
80   self = [super initWithDelegate:controller frame:frame];
81   if (self)
82     controller_ = controller;
84   return self;
87 #pragma mark -
88 #pragma mark NSView implementation:
90 - (void)drawRect:(NSRect)dirtyRect {
91   // If the view is in the process of being destroyed, don't bother drawing.
92   if (!controller_)
93     return;
95   [self drawBackgroundAndBorder];
97   for (size_t i = 0; i < controller_->GetLineCount(); ++i) {
98     // Skip rows outside of the dirty rect.
99     NSRect rowBounds =
100         NSRectFromCGRect(controller_->GetRowBounds(i).ToCGRect());
101     if (!NSIntersectsRect(rowBounds, dirtyRect))
102       continue;
103     const autofill::Suggestion& suggestion = controller_->GetSuggestionAt(i);
105     if (suggestion.frontend_id == autofill::POPUP_ITEM_ID_SEPARATOR) {
106       [self drawSeparatorWithBounds:rowBounds];
107       continue;
108     }
110     // Additional offset applied to the text in the vertical direction.
111     CGFloat textYOffset = 0;
113     NSString* value = SysUTF16ToNSString(controller_->GetElidedValueAt(i));
114     NSString* label = SysUTF16ToNSString(controller_->GetElidedLabelAt(i));
115     BOOL isSelected = static_cast<int>(i) == controller_->selected_line();
116     [self drawSuggestionWithName:value
117                          subtext:label
118                            index:i
119                           bounds:rowBounds
120                         selected:isSelected
121                      textYOffset:textYOffset];
122   }
125 #pragma mark -
126 #pragma mark Public API:
128 - (void)controllerDestroyed {
129   // Since the |controller_| either already has been destroyed or is about to
130   // be, about the only thing we can safely do with it is to null it out.
131   controller_ = NULL;
132   [super delegateDestroyed];
135 - (void)invalidateRow:(size_t)row {
136   NSRect dirty_rect =
137       NSRectFromCGRect(controller_->GetRowBounds(row).ToCGRect());
138   [self setNeedsDisplayInRect:dirty_rect];
141 #pragma mark -
142 #pragma mark Private API:
144 - (void)drawSuggestionWithName:(NSString*)name
145                        subtext:(NSString*)subtext
146                          index:(size_t)index
147                         bounds:(NSRect)bounds
148                       selected:(BOOL)isSelected
149                    textYOffset:(CGFloat)textYOffset {
150   // If this row is selected, highlight it.
151   if (isSelected) {
152     [[self highlightColor] set];
153     [NSBezierPath fillRect:bounds];
154   }
156   BOOL isRTL = controller_->IsRTL();
158   // The X values of the left and right borders of the autofill widget.
159   CGFloat leftX = NSMinX(bounds) + AutofillPopupView::kEndPadding;
160   CGFloat rightX = NSMaxX(bounds) - AutofillPopupView::kEndPadding;
162   // Draw left side if isRTL == NO, right side if isRTL == YES.
163   CGFloat x = isRTL ? rightX : leftX;
164   [self drawName:name
165               atX:x
166             index:index
167        rightAlign:isRTL
168            bounds:bounds
169       textYOffset:textYOffset];
171   // Draw right side if isRTL == NO, left side if isRTL == YES.
172   x = isRTL ? leftX : rightX;
173   x = [self drawIconAtIndex:index atX:x rightAlign:!isRTL bounds:bounds];
174   [self drawSubtext:subtext
175                 atX:x
176          rightAlign:!isRTL
177              bounds:bounds
178         textYOffset:textYOffset];
181 - (CGFloat)drawName:(NSString*)name
182                 atX:(CGFloat)x
183               index:(size_t)index
184          rightAlign:(BOOL)rightAlign
185              bounds:(NSRect)bounds
186         textYOffset:(CGFloat)textYOffset {
187   NSColor* nameColor =
188       controller_->IsWarning(index) ? [self warningColor] : [self nameColor];
189   NSDictionary* nameAttributes =
190       [NSDictionary dictionaryWithObjectsAndKeys:
191            controller_->GetValueFontListForRow(index).GetPrimaryFont().
192                GetNativeFont(),
193            NSFontAttributeName, nameColor, NSForegroundColorAttributeName,
194            nil];
195   NSSize nameSize = [name sizeWithAttributes:nameAttributes];
196   x -= rightAlign ? nameSize.width : 0;
197   CGFloat y = bounds.origin.y + (bounds.size.height - nameSize.height) / 2;
198   y += textYOffset;
200   [name drawAtPoint:NSMakePoint(x, y) withAttributes:nameAttributes];
202   x += rightAlign ? 0 : nameSize.width;
203   return x;
206 - (CGFloat)drawIconAtIndex:(size_t)index
207                        atX:(CGFloat)x
208                 rightAlign:(BOOL)rightAlign
209                     bounds:(NSRect)bounds {
210   NSImage* icon = [self iconAtIndex:index];
211   if (!icon)
212     return x;
213   NSSize iconSize = [icon size];
214   x -= rightAlign ? iconSize.width : 0;
215   CGFloat y = bounds.origin.y + (bounds.size.height - iconSize.height) / 2;
216     [icon drawInRect:NSMakeRect(x, y, iconSize.width, iconSize.height)
217             fromRect:NSZeroRect
218            operation:NSCompositeSourceOver
219             fraction:1.0
220       respectFlipped:YES
221                hints:nil];
223     x += rightAlign ? -AutofillPopupView::kIconPadding
224                     : iconSize.width + AutofillPopupView::kIconPadding;
225     return x;
228 - (CGFloat)drawSubtext:(NSString*)subtext
229                    atX:(CGFloat)x
230             rightAlign:(BOOL)rightAlign
231                 bounds:(NSRect)bounds
232            textYOffset:(CGFloat)textYOffset {
233   NSDictionary* subtextAttributes =
234       [NSDictionary dictionaryWithObjectsAndKeys:
235            controller_->GetLabelFontList().GetPrimaryFont().GetNativeFont(),
236            NSFontAttributeName,
237            [self subtextColor],
238            NSForegroundColorAttributeName,
239            nil];
240   NSSize subtextSize = [subtext sizeWithAttributes:subtextAttributes];
241   x -= rightAlign ? subtextSize.width : 0;
242   CGFloat y = bounds.origin.y + (bounds.size.height - subtextSize.height) / 2;
243   y += textYOffset;
245   [subtext drawAtPoint:NSMakePoint(x, y) withAttributes:subtextAttributes];
246   x += rightAlign ? 0 : subtextSize.width;
247   return x;
250 - (NSImage*)iconAtIndex:(size_t)index {
251   const base::string16& icon = controller_->GetSuggestionAt(index).icon;
252   if (icon.empty())
253     return nil;
255   int iconId = controller_->GetIconResourceID(icon);
256   DCHECK_NE(-1, iconId);
258   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
259   return rb.GetNativeImageNamed(iconId).ToNSImage();
262 @end