| 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" |
| 11 #include "chrome/browser/ui/cocoa/autofill/autofill_popup_view_bridge.h" | 11 #include "chrome/browser/ui/cocoa/autofill/autofill_popup_view_bridge.h" |
| 12 #include "components/autofill/core/browser/popup_item_ids.h" | 12 #include "components/autofill/core/browser/popup_item_ids.h" |
| 13 #include "grit/ui_resources.h" | 13 #include "grit/ui_resources.h" |
| 14 #include "ui/base/cocoa/window_size_constants.h" |
| 14 #include "ui/base/resource/resource_bundle.h" | 15 #include "ui/base/resource/resource_bundle.h" |
| 15 #include "ui/gfx/font_list.h" | 16 #include "ui/gfx/font_list.h" |
| 16 #include "ui/gfx/image/image.h" | 17 #include "ui/gfx/image/image.h" |
| 17 #include "ui/gfx/point.h" | 18 #include "ui/gfx/point.h" |
| 18 #include "ui/gfx/rect.h" | 19 #include "ui/gfx/rect.h" |
| 19 | 20 |
| 20 using autofill::AutofillPopupView; | 21 using autofill::AutofillPopupView; |
| 21 | 22 |
| 22 namespace { | 23 @interface AutofillPopupViewCocoa () |
| 23 | |
| 24 NSColor* BackgroundColor() { | |
| 25 return [NSColor whiteColor]; | |
| 26 } | |
| 27 | |
| 28 // The color of the border around the popup. | |
| 29 NSColor* BorderColor() { | |
| 30 return [NSColor colorForControlTint:[NSColor currentControlTint]]; | |
| 31 } | |
| 32 | |
| 33 NSColor* SeparatorColor() { | |
| 34 return [NSColor colorWithCalibratedWhite:220 / 255.0 alpha:1]; | |
| 35 } | |
| 36 | |
| 37 NSColor* HighlightColor() { | |
| 38 return [NSColor selectedControlColor]; | |
| 39 } | |
| 40 | |
| 41 NSColor* NameColor() { | |
| 42 return [NSColor blackColor]; | |
| 43 } | |
| 44 | |
| 45 NSColor* WarningColor() { | |
| 46 return [NSColor grayColor]; | |
| 47 } | |
| 48 | |
| 49 NSColor* SubtextColor() { | |
| 50 return [NSColor grayColor]; | |
| 51 } | |
| 52 | |
| 53 } // namespace | |
| 54 | 24 |
| 55 #pragma mark - | 25 #pragma mark - |
| 56 #pragma mark Private methods | 26 #pragma mark Private methods |
| 57 | 27 |
| 58 @interface AutofillPopupViewCocoa () | |
| 59 | |
| 60 // Draws a thin separator in the popup UI. | |
| 61 - (void)drawSeparatorWithBounds:(NSRect)bounds; | |
| 62 | |
| 63 // 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 |
| 64 // |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 |
| 65 // 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, |
| 66 // if the row requires it -- such as for credit cards. | 31 // if the row requires it -- such as for credit cards. |
| 67 - (void)drawSuggestionWithName:(NSString*)name | 32 - (void)drawSuggestionWithName:(NSString*)name |
| 68 subtext:(NSString*)subtext | 33 subtext:(NSString*)subtext |
| 69 index:(size_t)index | 34 index:(size_t)index |
| 70 bounds:(NSRect)bounds | 35 bounds:(NSRect)bounds |
| 71 selected:(BOOL)isSelected; | 36 selected:(BOOL)isSelected; |
| 72 | 37 |
| 73 // Returns the icon for the row with the given |index|, or |nil| if there is | 38 // Returns the icon for the row with the given |index|, or |nil| if there is |
| 74 // none. | 39 // none. |
| 75 - (NSImage*)iconAtIndex:(size_t)index; | 40 - (NSImage*)iconAtIndex:(size_t)index; |
| 76 | 41 |
| 77 @end | 42 @end |
| 78 | 43 |
| 79 @implementation AutofillPopupViewCocoa | 44 @implementation AutofillPopupViewCocoa |
| 80 | 45 |
| 81 #pragma mark - | 46 #pragma mark - |
| 82 #pragma mark Initialisers | 47 #pragma mark Initialisers |
| 83 | 48 |
| 84 - (id)initWithFrame:(NSRect)frame { | 49 - (id)initWithFrame:(NSRect)frame { |
| 85 NOTREACHED(); | 50 NOTREACHED(); |
| 86 return [self initWithController:NULL frame:frame]; | 51 return [self initWithController:NULL frame:frame]; |
| 87 } | 52 } |
| 88 | 53 |
| 89 - (id)initWithController:(autofill::AutofillPopupController*)controller | 54 - (id)initWithController:(autofill::AutofillPopupController*)controller |
| 90 frame:(NSRect)frame { | 55 frame:(NSRect)frame { |
| 91 self = [super initWithFrame:frame]; | 56 self = [super initWithDelegate:controller frame:frame]; |
| 92 if (self) | 57 if (self) |
| 93 controller_ = controller; | 58 controller_ = controller; |
| 94 | 59 |
| 95 return self; | 60 return self; |
| 96 } | 61 } |
| 97 | 62 |
| 98 #pragma mark - | 63 #pragma mark - |
| 99 #pragma mark NSView implementation: | 64 #pragma mark NSView implementation: |
| 100 | 65 |
| 101 // A slight optimization for drawing: | |
| 102 // https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Cocoa
ViewsGuide/Optimizing/Optimizing.html | |
| 103 - (BOOL)isOpaque { | |
| 104 return YES; | |
| 105 } | |
| 106 | |
| 107 - (BOOL)isFlipped { | |
| 108 // Flipped so that it's easier to share controller logic with other OSes. | |
| 109 return YES; | |
| 110 } | |
| 111 | |
| 112 - (void)drawRect:(NSRect)dirtyRect { | 66 - (void)drawRect:(NSRect)dirtyRect { |
| 113 // If the view is in the process of being destroyed, don't bother drawing. | 67 // If the view is in the process of being destroyed, don't bother drawing. |
| 114 if (!controller_) | 68 if (!controller_) |
| 115 return; | 69 return; |
| 116 | 70 |
| 117 // Draw the popup's background and border. | 71 [self drawBackgroundAndBorder]; |
| 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]; | |
| 130 | 72 |
| 131 for (size_t i = 0; i < controller_->names().size(); ++i) { | 73 for (size_t i = 0; i < controller_->names().size(); ++i) { |
| 132 // Skip rows outside of the dirty rect. | 74 // Skip rows outside of the dirty rect. |
| 133 NSRect rowBounds = | 75 NSRect rowBounds = |
| 134 NSRectFromCGRect(controller_->GetRowBounds(i).ToCGRect()); | 76 NSRectFromCGRect(controller_->GetRowBounds(i).ToCGRect()); |
| 135 if (!NSIntersectsRect(rowBounds, dirtyRect)) | 77 if (!NSIntersectsRect(rowBounds, dirtyRect)) |
| 136 continue; | 78 continue; |
| 137 | 79 |
| 138 if (controller_->identifiers()[i] == autofill::POPUP_ITEM_ID_SEPARATOR) { | 80 if (controller_->identifiers()[i] == autofill::POPUP_ITEM_ID_SEPARATOR) { |
| 139 [self drawSeparatorWithBounds:rowBounds]; | 81 [self drawSeparatorWithBounds:rowBounds]; |
| 140 } else { | 82 } else { |
| 141 NSString* name = SysUTF16ToNSString(controller_->names()[i]); | 83 NSString* name = SysUTF16ToNSString(controller_->names()[i]); |
| 142 NSString* subtext = SysUTF16ToNSString(controller_->subtexts()[i]); | 84 NSString* subtext = SysUTF16ToNSString(controller_->subtexts()[i]); |
| 143 BOOL isSelected = static_cast<int>(i) == controller_->selected_line(); | 85 BOOL isSelected = static_cast<int>(i) == controller_->selected_line(); |
| 144 [self drawSuggestionWithName:name | 86 [self drawSuggestionWithName:name |
| 145 subtext:subtext | 87 subtext:subtext |
| 146 index:i | 88 index:i |
| 147 bounds:rowBounds | 89 bounds:rowBounds |
| 148 selected:isSelected]; | 90 selected:isSelected]; |
| 149 } | 91 } |
| 150 } | 92 } |
| 151 } | 93 } |
| 152 | 94 |
| 153 - (void)mouseUp:(NSEvent*)theEvent { | |
| 154 // If the view is in the process of being destroyed, abort. | |
| 155 if (!controller_) | |
| 156 return; | |
| 157 | |
| 158 NSPoint location = [self convertPoint:[theEvent locationInWindow] | |
| 159 fromView:nil]; | |
| 160 | |
| 161 if (NSPointInRect(location, [self bounds])) { | |
| 162 controller_->SetSelectionAtPoint(gfx::Point(NSPointToCGPoint(location))); | |
| 163 controller_->AcceptSelectedLine(); | |
| 164 } | |
| 165 } | |
| 166 | |
| 167 - (void)mouseMoved:(NSEvent*)theEvent { | |
| 168 // If the view is in the process of being destroyed, abort. | |
| 169 if (!controller_) | |
| 170 return; | |
| 171 | |
| 172 NSPoint location = [self convertPoint:[theEvent locationInWindow] | |
| 173 fromView:nil]; | |
| 174 | |
| 175 controller_->SetSelectionAtPoint(gfx::Point(NSPointToCGPoint(location))); | |
| 176 } | |
| 177 | |
| 178 - (void)mouseDragged:(NSEvent*)theEvent { | |
| 179 [self mouseMoved:theEvent]; | |
| 180 } | |
| 181 | |
| 182 - (void)mouseExited:(NSEvent*)theEvent { | |
| 183 // If the view is in the process of being destroyed, abort. | |
| 184 if (!controller_) | |
| 185 return; | |
| 186 | |
| 187 controller_->SelectionCleared(); | |
| 188 } | |
| 189 | |
| 190 #pragma mark - | 95 #pragma mark - |
| 191 #pragma mark Public API: | 96 #pragma mark Public API: |
| 192 | 97 |
| 193 - (void)controllerDestroyed { | 98 - (void)controllerDestroyed { |
| 194 // Since the |controller_| either already has been destroyed or is about to | 99 // 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. | 100 // be, about the only thing we can safely do with it is to null it out. |
| 196 controller_ = NULL; | 101 controller_ = NULL; |
| 197 } | 102 } |
| 198 | 103 |
| 104 - (void)invalidateRow:(size_t)row { |
| 105 NSRect dirty_rect = |
| 106 NSRectFromCGRect(controller_->GetRowBounds(row).ToCGRect()); |
| 107 [self setNeedsDisplayInRect:dirty_rect]; |
| 108 } |
| 109 |
| 199 #pragma mark - | 110 #pragma mark - |
| 200 #pragma mark Private API: | 111 #pragma mark Private API: |
| 201 | 112 |
| 202 - (void)drawSeparatorWithBounds:(NSRect)bounds { | |
| 203 [SeparatorColor() set]; | |
| 204 [NSBezierPath fillRect:bounds]; | |
| 205 } | |
| 206 | |
| 207 - (void)drawSuggestionWithName:(NSString*)name | 113 - (void)drawSuggestionWithName:(NSString*)name |
| 208 subtext:(NSString*)subtext | 114 subtext:(NSString*)subtext |
| 209 index:(size_t)index | 115 index:(size_t)index |
| 210 bounds:(NSRect)bounds | 116 bounds:(NSRect)bounds |
| 211 selected:(BOOL)isSelected { | 117 selected:(BOOL)isSelected { |
| 212 // If this row is selected, highlight it. | 118 // If this row is selected, highlight it. |
| 213 if (isSelected) { | 119 if (isSelected) { |
| 214 [HighlightColor() set]; | 120 [[self highlightColor] set]; |
| 215 [NSBezierPath fillRect:bounds]; | 121 [NSBezierPath fillRect:bounds]; |
| 216 } | 122 } |
| 217 | 123 |
| 218 BOOL isRTL = controller_->IsRTL(); | 124 BOOL isRTL = controller_->IsRTL(); |
| 219 | 125 |
| 220 NSColor* nameColor = | 126 NSColor* nameColor = |
| 221 controller_->IsWarning(index) ? WarningColor() : NameColor(); | 127 controller_->IsWarning(index) ? [self warningColor] : [self nameColor]; |
| 222 NSDictionary* nameAttributes = | 128 NSDictionary* nameAttributes = |
| 223 [NSDictionary dictionaryWithObjectsAndKeys: | 129 [NSDictionary dictionaryWithObjectsAndKeys: |
| 224 controller_->GetNameFontListForRow(index).GetPrimaryFont(). | 130 controller_->GetNameFontListForRow(index).GetPrimaryFont(). |
| 225 GetNativeFont(), | 131 GetNativeFont(), |
| 226 NSFontAttributeName, nameColor, NSForegroundColorAttributeName, | 132 NSFontAttributeName, nameColor, NSForegroundColorAttributeName, |
| 227 nil]; | 133 nil]; |
| 228 NSSize nameSize = [name sizeWithAttributes:nameAttributes]; | 134 NSSize nameSize = [name sizeWithAttributes:nameAttributes]; |
| 229 CGFloat x = bounds.origin.x + | 135 CGFloat x = bounds.origin.x + |
| 230 (isRTL ? | 136 (isRTL ? |
| 231 bounds.size.width - AutofillPopupView::kEndPadding - nameSize.width : | 137 bounds.size.width - AutofillPopupView::kEndPadding - nameSize.width : |
| (...skipping 23 matching lines...) Expand all Loading... |
| 255 | 161 |
| 256 x += isRTL ? | 162 x += isRTL ? |
| 257 iconSize.width + AutofillPopupView::kIconPadding : | 163 iconSize.width + AutofillPopupView::kIconPadding : |
| 258 -AutofillPopupView::kIconPadding; | 164 -AutofillPopupView::kIconPadding; |
| 259 } | 165 } |
| 260 | 166 |
| 261 // Draw the subtext. | 167 // Draw the subtext. |
| 262 NSDictionary* subtextAttributes = | 168 NSDictionary* subtextAttributes = |
| 263 [NSDictionary dictionaryWithObjectsAndKeys: | 169 [NSDictionary dictionaryWithObjectsAndKeys: |
| 264 controller_->subtext_font_list().GetPrimaryFont().GetNativeFont(), | 170 controller_->subtext_font_list().GetPrimaryFont().GetNativeFont(), |
| 265 NSFontAttributeName, SubtextColor(), NSForegroundColorAttributeName, | 171 NSFontAttributeName, |
| 172 [self subtextColor], |
| 173 NSForegroundColorAttributeName, |
| 266 nil]; | 174 nil]; |
| 267 NSSize subtextSize = [subtext sizeWithAttributes:subtextAttributes]; | 175 NSSize subtextSize = [subtext sizeWithAttributes:subtextAttributes]; |
| 268 x += isRTL ? 0 : -subtextSize.width; | 176 x += isRTL ? 0 : -subtextSize.width; |
| 269 y = bounds.origin.y + (bounds.size.height - subtextSize.height) / 2; | 177 y = bounds.origin.y + (bounds.size.height - subtextSize.height) / 2; |
| 270 | 178 |
| 271 [subtext drawAtPoint:NSMakePoint(x, y) withAttributes:subtextAttributes]; | 179 [subtext drawAtPoint:NSMakePoint(x, y) withAttributes:subtextAttributes]; |
| 272 } | 180 } |
| 273 | 181 |
| 274 - (NSImage*)iconAtIndex:(size_t)index { | 182 - (NSImage*)iconAtIndex:(size_t)index { |
| 275 if (controller_->icons()[index].empty()) | 183 if (controller_->icons()[index].empty()) |
| 276 return nil; | 184 return nil; |
| 277 | 185 |
| 278 int iconId = controller_->GetIconResourceID(controller_->icons()[index]); | 186 int iconId = controller_->GetIconResourceID(controller_->icons()[index]); |
| 279 DCHECK_NE(-1, iconId); | 187 DCHECK_NE(-1, iconId); |
| 280 | 188 |
| 281 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 189 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 282 return rb.GetNativeImageNamed(iconId).ToNSImage(); | 190 return rb.GetNativeImageNamed(iconId).ToNSImage(); |
| 283 } | 191 } |
| 284 | 192 |
| 285 @end | 193 @end |
| OLD | NEW |