OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.h" | 5 #import "chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/strings/sys_string_conversions.h" | 8 #include "base/strings/sys_string_conversions.h" |
9 #include "chrome/browser/ui/autofill/autofill_popup_controller.h" | 9 #include "chrome/browser/ui/autofill/autofill_popup_controller.h" |
10 #include "chrome/browser/ui/autofill/popup_constants.h" | 10 #include "chrome/browser/ui/autofill/popup_constants.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 using autofill::AutofillPopupView; | 21 using autofill::AutofillPopupView; |
22 | 22 |
23 @interface AutofillPopupViewCocoa () | 23 @interface AutofillPopupViewCocoa () |
24 | 24 |
25 #pragma mark - | 25 #pragma mark - |
26 #pragma mark Private methods | 26 #pragma mark Private methods |
27 | 27 |
28 // Draws an Autofill suggestion in the given |bounds|, labeled with the given | 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 | 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, | 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. | 31 // if the row requires it -- such as for credit cards. |imageFirst| indicates |
| 32 // whether the image should be drawn before the name, and with the same |
| 33 // alignment, or whether it should be drawn afterwards, with the opposite |
| 34 // alignment. |
32 - (void)drawSuggestionWithName:(NSString*)name | 35 - (void)drawSuggestionWithName:(NSString*)name |
33 subtext:(NSString*)subtext | 36 subtext:(NSString*)subtext |
34 index:(size_t)index | 37 index:(size_t)index |
35 bounds:(NSRect)bounds | 38 bounds:(NSRect)bounds |
36 selected:(BOOL)isSelected; | 39 selected:(BOOL)isSelected |
| 40 imageFirst:(BOOL)imageFirst |
| 41 textYOffset:(CGFloat)textYOffset; |
| 42 |
| 43 // This comment block applies to all three draw* methods that follow. |
| 44 // If |rightAlign| == YES. |
| 45 // Draws the widget with right border aligned to |x|. |
| 46 // Returns the x value of left border of the widget. |
| 47 // If |rightAlign| == NO. |
| 48 // Draws the widget with left border aligned to |x|. |
| 49 // Returns the x value of right border of the widget. |
| 50 - (CGFloat)drawName:(NSString*)name |
| 51 atX:(CGFloat)x |
| 52 index:(size_t)index |
| 53 rightAlign:(BOOL)rightAlign |
| 54 bounds:(NSRect)bounds |
| 55 textYOffset:(CGFloat)textYOffset; |
| 56 - (CGFloat)drawIconAtIndex:(size_t)index |
| 57 atX:(CGFloat)x |
| 58 rightAlign:(BOOL)rightAlign |
| 59 bounds:(NSRect)bounds; |
| 60 - (CGFloat)drawSubtext:(NSString*)subtext |
| 61 atX:(CGFloat)x |
| 62 rightAlign:(BOOL)rightAlign |
| 63 bounds:(NSRect)bounds |
| 64 textYOffset:(CGFloat)textYOffset; |
37 | 65 |
38 // Returns the icon for the row with the given |index|, or |nil| if there is | 66 // Returns the icon for the row with the given |index|, or |nil| if there is |
39 // none. | 67 // none. |
40 - (NSImage*)iconAtIndex:(size_t)index; | 68 - (NSImage*)iconAtIndex:(size_t)index; |
41 | 69 |
42 @end | 70 @end |
43 | 71 |
44 @implementation AutofillPopupViewCocoa | 72 @implementation AutofillPopupViewCocoa |
45 | 73 |
46 #pragma mark - | 74 #pragma mark - |
(...skipping 25 matching lines...) Expand all Loading... |
72 | 100 |
73 for (size_t i = 0; i < controller_->names().size(); ++i) { | 101 for (size_t i = 0; i < controller_->names().size(); ++i) { |
74 // Skip rows outside of the dirty rect. | 102 // Skip rows outside of the dirty rect. |
75 NSRect rowBounds = | 103 NSRect rowBounds = |
76 NSRectFromCGRect(controller_->GetRowBounds(i).ToCGRect()); | 104 NSRectFromCGRect(controller_->GetRowBounds(i).ToCGRect()); |
77 if (!NSIntersectsRect(rowBounds, dirtyRect)) | 105 if (!NSIntersectsRect(rowBounds, dirtyRect)) |
78 continue; | 106 continue; |
79 | 107 |
80 if (controller_->identifiers()[i] == autofill::POPUP_ITEM_ID_SEPARATOR) { | 108 if (controller_->identifiers()[i] == autofill::POPUP_ITEM_ID_SEPARATOR) { |
81 [self drawSeparatorWithBounds:rowBounds]; | 109 [self drawSeparatorWithBounds:rowBounds]; |
82 } else { | 110 continue; |
83 NSString* name = SysUTF16ToNSString(controller_->names()[i]); | |
84 NSString* subtext = SysUTF16ToNSString(controller_->subtexts()[i]); | |
85 BOOL isSelected = static_cast<int>(i) == controller_->selected_line(); | |
86 [self drawSuggestionWithName:name | |
87 subtext:subtext | |
88 index:i | |
89 bounds:rowBounds | |
90 selected:isSelected]; | |
91 } | 111 } |
| 112 |
| 113 // Additional offset applied to the text in the vertical direction. |
| 114 CGFloat textYOffset = 0; |
| 115 BOOL imageFirst = NO; |
| 116 if (controller_->identifiers()[i] == |
| 117 autofill::POPUP_ITEM_ID_MAC_ACCESS_CONTACTS) { |
| 118 // Due to the weighting of the asset used for this autofill entry, the |
| 119 // text needs to be bumped up by 1 pt to make it look vertically aligned. |
| 120 textYOffset = -1; |
| 121 imageFirst = YES; |
| 122 } |
| 123 |
| 124 NSString* name = SysUTF16ToNSString(controller_->names()[i]); |
| 125 NSString* subtext = SysUTF16ToNSString(controller_->subtexts()[i]); |
| 126 BOOL isSelected = static_cast<int>(i) == controller_->selected_line(); |
| 127 [self drawSuggestionWithName:name |
| 128 subtext:subtext |
| 129 index:i |
| 130 bounds:rowBounds |
| 131 selected:isSelected |
| 132 imageFirst:imageFirst |
| 133 textYOffset:textYOffset]; |
92 } | 134 } |
93 } | 135 } |
94 | 136 |
95 #pragma mark - | 137 #pragma mark - |
96 #pragma mark Public API: | 138 #pragma mark Public API: |
97 | 139 |
98 - (void)controllerDestroyed { | 140 - (void)controllerDestroyed { |
99 // Since the |controller_| either already has been destroyed or is about to | 141 // Since the |controller_| either already has been destroyed or is about to |
100 // be, about the only thing we can safely do with it is to null it out. | 142 // be, about the only thing we can safely do with it is to null it out. |
101 controller_ = NULL; | 143 controller_ = NULL; |
102 [super delegateDestroyed]; | 144 [super delegateDestroyed]; |
103 } | 145 } |
104 | 146 |
105 - (void)invalidateRow:(size_t)row { | 147 - (void)invalidateRow:(size_t)row { |
106 NSRect dirty_rect = | 148 NSRect dirty_rect = |
107 NSRectFromCGRect(controller_->GetRowBounds(row).ToCGRect()); | 149 NSRectFromCGRect(controller_->GetRowBounds(row).ToCGRect()); |
108 [self setNeedsDisplayInRect:dirty_rect]; | 150 [self setNeedsDisplayInRect:dirty_rect]; |
109 } | 151 } |
110 | 152 |
111 #pragma mark - | 153 #pragma mark - |
112 #pragma mark Private API: | 154 #pragma mark Private API: |
113 | 155 |
114 - (void)drawSuggestionWithName:(NSString*)name | 156 - (void)drawSuggestionWithName:(NSString*)name |
115 subtext:(NSString*)subtext | 157 subtext:(NSString*)subtext |
116 index:(size_t)index | 158 index:(size_t)index |
117 bounds:(NSRect)bounds | 159 bounds:(NSRect)bounds |
118 selected:(BOOL)isSelected { | 160 selected:(BOOL)isSelected |
| 161 imageFirst:(BOOL)imageFirst |
| 162 textYOffset:(CGFloat)textYOffset { |
119 // If this row is selected, highlight it. | 163 // If this row is selected, highlight it. |
120 if (isSelected) { | 164 if (isSelected) { |
121 [[self highlightColor] set]; | 165 [[self highlightColor] set]; |
122 [NSBezierPath fillRect:bounds]; | 166 [NSBezierPath fillRect:bounds]; |
123 } | 167 } |
124 | 168 |
125 BOOL isRTL = controller_->IsRTL(); | 169 BOOL isRTL = controller_->IsRTL(); |
126 | 170 |
| 171 // The X values of the left and right borders of the autofill widget. |
| 172 CGFloat leftX = NSMinX(bounds) + AutofillPopupView::kEndPadding; |
| 173 CGFloat rightX = NSMaxX(bounds) - AutofillPopupView::kEndPadding; |
| 174 |
| 175 // Draw left side if isRTL == NO, right side if isRTL == YES. |
| 176 CGFloat x = isRTL ? rightX : leftX; |
| 177 if (imageFirst) |
| 178 x = [self drawIconAtIndex:index atX:x rightAlign:isRTL bounds:bounds]; |
| 179 [self drawName:name |
| 180 atX:x |
| 181 index:index |
| 182 rightAlign:isRTL |
| 183 bounds:bounds |
| 184 textYOffset:textYOffset]; |
| 185 |
| 186 // Draw right side if isRTL == NO, left side if isRTL == YES. |
| 187 x = isRTL ? leftX : rightX; |
| 188 if (!imageFirst) |
| 189 x = [self drawIconAtIndex:index atX:x rightAlign:!isRTL bounds:bounds]; |
| 190 [self drawSubtext:subtext |
| 191 atX:x |
| 192 rightAlign:!isRTL |
| 193 bounds:bounds |
| 194 textYOffset:textYOffset]; |
| 195 } |
| 196 |
| 197 - (CGFloat)drawName:(NSString*)name |
| 198 atX:(CGFloat)x |
| 199 index:(size_t)index |
| 200 rightAlign:(BOOL)rightAlign |
| 201 bounds:(NSRect)bounds |
| 202 textYOffset:(CGFloat)textYOffset { |
127 NSColor* nameColor = | 203 NSColor* nameColor = |
128 controller_->IsWarning(index) ? [self warningColor] : [self nameColor]; | 204 controller_->IsWarning(index) ? [self warningColor] : [self nameColor]; |
129 NSDictionary* nameAttributes = | 205 NSDictionary* nameAttributes = |
130 [NSDictionary dictionaryWithObjectsAndKeys: | 206 [NSDictionary dictionaryWithObjectsAndKeys: |
131 controller_->GetNameFontListForRow(index).GetPrimaryFont(). | 207 controller_->GetNameFontListForRow(index).GetPrimaryFont(). |
132 GetNativeFont(), | 208 GetNativeFont(), |
133 NSFontAttributeName, nameColor, NSForegroundColorAttributeName, | 209 NSFontAttributeName, nameColor, NSForegroundColorAttributeName, |
134 nil]; | 210 nil]; |
135 NSSize nameSize = [name sizeWithAttributes:nameAttributes]; | 211 NSSize nameSize = [name sizeWithAttributes:nameAttributes]; |
136 CGFloat x = bounds.origin.x + | 212 x -= rightAlign ? nameSize.width : 0; |
137 (isRTL ? | |
138 bounds.size.width - AutofillPopupView::kEndPadding - nameSize.width : | |
139 AutofillPopupView::kEndPadding); | |
140 CGFloat y = bounds.origin.y + (bounds.size.height - nameSize.height) / 2; | 213 CGFloat y = bounds.origin.y + (bounds.size.height - nameSize.height) / 2; |
| 214 y += textYOffset; |
141 | 215 |
142 [name drawAtPoint:NSMakePoint(x, y) withAttributes:nameAttributes]; | 216 [name drawAtPoint:NSMakePoint(x, y) withAttributes:nameAttributes]; |
143 | 217 |
144 // The x-coordinate will be updated as each element is drawn. | 218 x += rightAlign ? 0 : nameSize.width; |
145 x = bounds.origin.x + | 219 return x; |
146 (isRTL ? | 220 } |
147 AutofillPopupView::kEndPadding : | |
148 bounds.size.width - AutofillPopupView::kEndPadding); | |
149 | 221 |
150 // Draw the Autofill icon, if one exists. | 222 - (CGFloat)drawIconAtIndex:(size_t)index |
| 223 atX:(CGFloat)x |
| 224 rightAlign:(BOOL)rightAlign |
| 225 bounds:(NSRect)bounds { |
151 NSImage* icon = [self iconAtIndex:index]; | 226 NSImage* icon = [self iconAtIndex:index]; |
152 if (icon) { | 227 if (!icon) |
153 NSSize iconSize = [icon size]; | 228 return x; |
154 x += isRTL ? 0 : -iconSize.width; | 229 NSSize iconSize = [icon size]; |
155 y = bounds.origin.y + (bounds.size.height - iconSize.height) / 2; | 230 x -= rightAlign ? iconSize.width : 0; |
| 231 CGFloat y = bounds.origin.y + (bounds.size.height - iconSize.height) / 2; |
156 [icon drawInRect:NSMakeRect(x, y, iconSize.width, iconSize.height) | 232 [icon drawInRect:NSMakeRect(x, y, iconSize.width, iconSize.height) |
157 fromRect:NSZeroRect | 233 fromRect:NSZeroRect |
158 operation:NSCompositeSourceOver | 234 operation:NSCompositeSourceOver |
159 fraction:1.0 | 235 fraction:1.0 |
160 respectFlipped:YES | 236 respectFlipped:YES |
161 hints:nil]; | 237 hints:nil]; |
162 | 238 |
163 x += isRTL ? | 239 x += rightAlign ? -AutofillPopupView::kIconPadding |
164 iconSize.width + AutofillPopupView::kIconPadding : | 240 : iconSize.width + AutofillPopupView::kIconPadding; |
165 -AutofillPopupView::kIconPadding; | 241 return x; |
166 } | 242 } |
167 | 243 |
168 // Draw the subtext. | 244 - (CGFloat)drawSubtext:(NSString*)subtext |
| 245 atX:(CGFloat)x |
| 246 rightAlign:(BOOL)rightAlign |
| 247 bounds:(NSRect)bounds |
| 248 textYOffset:(CGFloat)textYOffset { |
169 NSDictionary* subtextAttributes = | 249 NSDictionary* subtextAttributes = |
170 [NSDictionary dictionaryWithObjectsAndKeys: | 250 [NSDictionary dictionaryWithObjectsAndKeys: |
171 controller_->subtext_font_list().GetPrimaryFont().GetNativeFont(), | 251 controller_->subtext_font_list().GetPrimaryFont().GetNativeFont(), |
172 NSFontAttributeName, | 252 NSFontAttributeName, |
173 [self subtextColor], | 253 [self subtextColor], |
174 NSForegroundColorAttributeName, | 254 NSForegroundColorAttributeName, |
175 nil]; | 255 nil]; |
176 NSSize subtextSize = [subtext sizeWithAttributes:subtextAttributes]; | 256 NSSize subtextSize = [subtext sizeWithAttributes:subtextAttributes]; |
177 x += isRTL ? 0 : -subtextSize.width; | 257 x -= rightAlign ? subtextSize.width : 0; |
178 y = bounds.origin.y + (bounds.size.height - subtextSize.height) / 2; | 258 CGFloat y = bounds.origin.y + (bounds.size.height - subtextSize.height) / 2; |
| 259 y += textYOffset; |
179 | 260 |
180 [subtext drawAtPoint:NSMakePoint(x, y) withAttributes:subtextAttributes]; | 261 [subtext drawAtPoint:NSMakePoint(x, y) withAttributes:subtextAttributes]; |
| 262 x += rightAlign ? 0 : subtextSize.width; |
| 263 return x; |
181 } | 264 } |
182 | 265 |
183 - (NSImage*)iconAtIndex:(size_t)index { | 266 - (NSImage*)iconAtIndex:(size_t)index { |
184 if (controller_->icons()[index].empty()) | 267 if (controller_->icons()[index].empty()) |
185 return nil; | 268 return nil; |
186 | 269 |
187 int iconId = controller_->GetIconResourceID(controller_->icons()[index]); | 270 int iconId = controller_->GetIconResourceID(controller_->icons()[index]); |
188 DCHECK_NE(-1, iconId); | 271 DCHECK_NE(-1, iconId); |
189 | 272 |
190 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 273 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
191 return rb.GetNativeImageNamed(iconId).ToNSImage(); | 274 return rb.GetNativeImageNamed(iconId).ToNSImage(); |
192 } | 275 } |
193 | 276 |
194 @end | 277 @end |
OLD | NEW |