| OLD | NEW | 
|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 #include "chrome/browser/autocomplete/autocomplete_popup_view_mac.h" | 5 #include "chrome/browser/autocomplete/autocomplete_popup_view_mac.h" | 
| 6 | 6 | 
| 7 #include "base/sys_string_conversions.h" | 7 #include "base/sys_string_conversions.h" | 
| 8 #include "chrome/browser/autocomplete/autocomplete_edit.h" | 8 #include "chrome/browser/autocomplete/autocomplete_edit.h" | 
| 9 #include "chrome/browser/autocomplete/autocomplete_edit_view_mac.h" | 9 #include "chrome/browser/autocomplete/autocomplete_edit_view_mac.h" | 
| 10 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" | 10 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
| 29 static const NSColor* ContentTextColor() { | 29 static const NSColor* ContentTextColor() { | 
| 30   return [NSColor blackColor]; | 30   return [NSColor blackColor]; | 
| 31 } | 31 } | 
| 32 static const NSColor* URLTextColor() { | 32 static const NSColor* URLTextColor() { | 
| 33   return [NSColor colorWithCalibratedRed:0.0 green:0.55 blue:0.0 alpha:1.0]; | 33   return [NSColor colorWithCalibratedRed:0.0 green:0.55 blue:0.0 alpha:1.0]; | 
| 34 } | 34 } | 
| 35 static const NSColor* DescriptionTextColor() { | 35 static const NSColor* DescriptionTextColor() { | 
| 36   return [NSColor darkGrayColor]; | 36   return [NSColor darkGrayColor]; | 
| 37 } | 37 } | 
| 38 | 38 | 
| 39 // TODO(shess): As with colors, there are a dozen ways to phrase this, |  | 
| 40 // all of them probably wrong.  Circle back with a ui-oriented |  | 
| 41 // resource later. |  | 
| 42 static const NSFont* NormalFont() { |  | 
| 43   return [NSFont userFontOfSize:12]; |  | 
| 44 } |  | 
| 45 static const NSFont* BoldFont() { |  | 
| 46   return [NSFont boldSystemFontOfSize:12]; |  | 
| 47 } |  | 
| 48 |  | 
| 49 // Return the appropriate icon for the given match.  Derived from the | 39 // Return the appropriate icon for the given match.  Derived from the | 
| 50 // gtk code. | 40 // gtk code. | 
| 51 NSImage* MatchIcon(const AutocompleteMatch& match) { | 41 NSImage* MatchIcon(const AutocompleteMatch& match) { | 
| 52   if (match.starred) { | 42   if (match.starred) { | 
| 53     return [NSImage imageNamed:@"o2_star.png"]; | 43     return [NSImage imageNamed:@"o2_star.png"]; | 
| 54   } | 44   } | 
| 55 | 45 | 
| 56   switch (match.type) { | 46   switch (match.type) { | 
| 57     case AutocompleteMatch::URL_WHAT_YOU_TYPED: | 47     case AutocompleteMatch::URL_WHAT_YOU_TYPED: | 
| 58     case AutocompleteMatch::NAVSUGGEST: { | 48     case AutocompleteMatch::NAVSUGGEST: { | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 82 } | 72 } | 
| 83 | 73 | 
| 84 }  // namespace | 74 }  // namespace | 
| 85 | 75 | 
| 86 // Helper for MatchText() to allow sharing code between the contents | 76 // Helper for MatchText() to allow sharing code between the contents | 
| 87 // and description cases.  Returns NSMutableAttributedString as a | 77 // and description cases.  Returns NSMutableAttributedString as a | 
| 88 // convenience for MatchText(). | 78 // convenience for MatchText(). | 
| 89 NSMutableAttributedString* AutocompletePopupViewMac::DecorateMatchedString( | 79 NSMutableAttributedString* AutocompletePopupViewMac::DecorateMatchedString( | 
| 90     const std::wstring &matchString, | 80     const std::wstring &matchString, | 
| 91     const AutocompleteMatch::ACMatchClassifications &classifications, | 81     const AutocompleteMatch::ACMatchClassifications &classifications, | 
| 92     NSColor* textColor) { | 82     NSColor* textColor, NSFont* font) { | 
|  | 83   // Cache for on-demand computation of the bold version of |font|. | 
|  | 84   NSFont* boldFont = nil; | 
| 93 | 85 | 
| 94   // Start out with a string using the default style info. | 86   // Start out with a string using the default style info. | 
| 95   NSString* s = base::SysWideToNSString(matchString); | 87   NSString* s = base::SysWideToNSString(matchString); | 
| 96   NSDictionary* attributes = [NSDictionary dictionaryWithObjectsAndKeys: | 88   NSDictionary* attributes = [NSDictionary dictionaryWithObjectsAndKeys: | 
| 97                                   NormalFont(), NSFontAttributeName, | 89                                   font, NSFontAttributeName, | 
| 98                                   textColor, NSForegroundColorAttributeName, | 90                                   textColor, NSForegroundColorAttributeName, | 
| 99                                   nil]; | 91                                   nil]; | 
| 100   NSMutableAttributedString* as = | 92   NSMutableAttributedString* as = | 
| 101       [[[NSMutableAttributedString alloc] initWithString:s | 93       [[[NSMutableAttributedString alloc] initWithString:s | 
| 102                                               attributes:attributes] | 94                                               attributes:attributes] | 
| 103         autorelease]; | 95         autorelease]; | 
| 104 | 96 | 
| 105   // Mark up the runs which differ from the default. | 97   // Mark up the runs which differ from the default. | 
| 106   for (ACMatchClassifications::const_iterator i = classifications.begin(); | 98   for (ACMatchClassifications::const_iterator i = classifications.begin(); | 
| 107        i != classifications.end(); ++i) { | 99        i != classifications.end(); ++i) { | 
| 108     const BOOL isLast = (i+1) == classifications.end(); | 100     const BOOL isLast = (i+1) == classifications.end(); | 
| 109     const size_t nextOffset = (isLast ? matchString.length() : (i+1)->offset); | 101     const size_t nextOffset = (isLast ? matchString.length() : (i+1)->offset); | 
| 110     const NSInteger location = static_cast<NSInteger>(i->offset); | 102     const NSInteger location = static_cast<NSInteger>(i->offset); | 
| 111     const NSInteger length = static_cast<NSInteger>(nextOffset - i->offset); | 103     const NSInteger length = static_cast<NSInteger>(nextOffset - i->offset); | 
| 112     const NSRange range = NSMakeRange(location, length); | 104     const NSRange range = NSMakeRange(location, length); | 
| 113 | 105 | 
| 114     if (0 != (i->style & ACMatchClassification::URL)) { | 106     if (0 != (i->style & ACMatchClassification::URL)) { | 
| 115       [as addAttribute:NSForegroundColorAttributeName | 107       [as addAttribute:NSForegroundColorAttributeName | 
| 116                  value:URLTextColor() range:range]; | 108                  value:URLTextColor() range:range]; | 
| 117     } | 109     } | 
| 118 | 110 | 
| 119     if (0 != (i->style & ACMatchClassification::MATCH)) { | 111     if (0 != (i->style & ACMatchClassification::MATCH)) { | 
| 120       [as addAttribute:NSFontAttributeName value:BoldFont() range:range]; | 112       if (!boldFont) { | 
|  | 113         NSFontManager* fontManager = [NSFontManager sharedFontManager]; | 
|  | 114         boldFont = [fontManager convertFont:font toHaveTrait:NSBoldFontMask]; | 
|  | 115       } | 
|  | 116       [as addAttribute:NSFontAttributeName value:boldFont range:range]; | 
| 121     } | 117     } | 
| 122   } | 118   } | 
| 123 | 119 | 
| 124   return as; | 120   return as; | 
| 125 } | 121 } | 
| 126 | 122 | 
| 127 // Return the text to show for the match, based on the match's | 123 // Return the text to show for the match, based on the match's | 
| 128 // contents and description. | 124 // contents and description.  Result will be in |font|, with the | 
| 129 NSMutableAttributedString* AutocompletePopupViewMac::MatchText( | 125 // boldfaced version used for matches. | 
| 130     const AutocompleteMatch& match) { | 126 NSAttributedString* AutocompletePopupViewMac::MatchText( | 
|  | 127     const AutocompleteMatch& match, NSFont* font) { | 
| 131   NSMutableAttributedString *as = | 128   NSMutableAttributedString *as = | 
| 132       DecorateMatchedString(match.contents, match.contents_class, | 129       DecorateMatchedString(match.contents, match.contents_class, | 
| 133                             ContentTextColor()); | 130                             ContentTextColor(), font); | 
| 134 | 131 | 
| 135   // If there is a description, append it, separated from the contents | 132   // If there is a description, append it, separated from the contents | 
| 136   // with an em dash, and decorated with a distinct color. | 133   // with an em dash, and decorated with a distinct color. | 
| 137   if (!match.description.empty()) { | 134   if (!match.description.empty()) { | 
| 138     NSDictionary* attributes = | 135     NSDictionary* attributes = | 
| 139         [NSDictionary dictionaryWithObjectsAndKeys: | 136         [NSDictionary dictionaryWithObjectsAndKeys: | 
| 140              NormalFont(), NSFontAttributeName, | 137              font, NSFontAttributeName, | 
| 141              ContentTextColor(), NSForegroundColorAttributeName, | 138              ContentTextColor(), NSForegroundColorAttributeName, | 
| 142              nil]; | 139              nil]; | 
| 143     NSString* rawEmDash = [NSString stringWithFormat:@" %C ", 0x2014]; | 140     NSString* rawEmDash = [NSString stringWithFormat:@" %C ", 0x2014]; | 
| 144     NSAttributedString* emDash = | 141     NSAttributedString* emDash = | 
| 145         [[[NSAttributedString alloc] initWithString:rawEmDash | 142         [[[NSAttributedString alloc] initWithString:rawEmDash | 
| 146                                          attributes:attributes] autorelease]; | 143                                          attributes:attributes] autorelease]; | 
| 147 | 144 | 
| 148     NSAttributedString* description = | 145     NSAttributedString* description = | 
| 149         DecorateMatchedString(match.description, match.description_class, | 146         DecorateMatchedString(match.description, match.description_class, | 
| 150                               DescriptionTextColor()); | 147                               DescriptionTextColor(), font); | 
| 151 | 148 | 
| 152     [as appendAttributedString:emDash]; | 149     [as appendAttributedString:emDash]; | 
| 153     [as appendAttributedString:description]; | 150     [as appendAttributedString:description]; | 
| 154   } | 151   } | 
| 155 | 152 | 
| 156   NSMutableParagraphStyle* style = | 153   NSMutableParagraphStyle* style = | 
| 157       [[[NSMutableParagraphStyle alloc] init] autorelease]; | 154       [[[NSMutableParagraphStyle alloc] init] autorelease]; | 
| 158   [style setLineBreakMode:NSLineBreakByTruncatingTail]; | 155   [style setLineBreakMode:NSLineBreakByTruncatingTail]; | 
| 159   [as addAttribute:NSParagraphStyleAttributeName value:style | 156   [as addAttribute:NSParagraphStyleAttributeName value:style | 
| 160              range:NSMakeRange(0, [as length])]; | 157              range:NSMakeRange(0, [as length])]; | 
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 256     NSMatrix* matrix = [popup_ contentView]; | 253     NSMatrix* matrix = [popup_ contentView]; | 
| 257     [matrix setTarget:nil]; | 254     [matrix setTarget:nil]; | 
| 258 | 255 | 
| 259     popup_.reset(nil); | 256     popup_.reset(nil); | 
| 260 | 257 | 
| 261     return; | 258     return; | 
| 262   } | 259   } | 
| 263 | 260 | 
| 264   CreatePopupIfNeeded(); | 261   CreatePopupIfNeeded(); | 
| 265 | 262 | 
|  | 263   // Load the results into the popup's matrix. | 
|  | 264   AutocompleteMatrix* matrix = [popup_ contentView]; | 
|  | 265   const size_t rows = model_->result().size(); | 
|  | 266   DCHECK_GT(rows, 0U); | 
|  | 267   [matrix renewRows:rows columns:1]; | 
|  | 268   for (size_t ii = 0; ii < rows; ++ii) { | 
|  | 269     AutocompleteButtonCell* cell = [matrix cellAtRow:ii column:0]; | 
|  | 270     const AutocompleteMatch& match = model_->result().match_at(ii); | 
|  | 271     [cell setImage:MatchIcon(match)]; | 
|  | 272     [cell setAttributedTitle:MatchText(match, [field_ font])]; | 
|  | 273   } | 
|  | 274 | 
| 266   // Layout the popup and size it to land underneath the field. | 275   // Layout the popup and size it to land underneath the field. | 
| 267   // TODO(shess) Consider refactoring to remove this depenency, | 276   // TODO(shess) Consider refactoring to remove this depenency, | 
| 268   // because the popup doesn't need any of the field-like aspects of | 277   // because the popup doesn't need any of the field-like aspects of | 
| 269   // field_.  The edit view could expose helper methods for attaching | 278   // field_.  The edit view could expose helper methods for attaching | 
| 270   // the window to the field. | 279   // the window to the field. | 
| 271   NSRect r = [field_ bounds]; | 280   NSRect r = [field_ bounds]; | 
| 272   r = [field_ convertRectToBase:r]; | 281   r = [field_ convertRectToBase:r]; | 
| 273   r.origin = [[field_ window] convertBaseToScreen:r.origin]; | 282   r.origin = [[field_ window] convertBaseToScreen:r.origin]; | 
| 274 | 283 | 
| 275   AutocompleteMatrix* matrix = [popup_ contentView]; | 284   // Set the cell size to fit a line of text in the cell's font.  All | 
| 276   [matrix setCellSize:NSMakeSize(r.size.width, [matrix cellSize].height)]; | 285   // cells should use the same font and layout to one line. | 
|  | 286   NSRect bigRect = [matrix bounds]; | 
|  | 287   // TODO(shess): Why 1000.0?  Because it's "big enough".  Find | 
|  | 288   // something better. | 
|  | 289   bigRect.size.height = 1000.0; | 
|  | 290   NSSize cellSize = [[matrix cellAtRow:0 column:0] cellSizeForBounds:bigRect]; | 
|  | 291   [matrix setCellSize:NSMakeSize(r.size.width, cellSize.height)]; | 
|  | 292 | 
|  | 293   // Make the matrix big enough to hold all the cells. | 
|  | 294   [matrix sizeToCells]; | 
| 277   [matrix setFrameSize:NSMakeSize(r.size.width, [matrix frame].size.height)]; | 295   [matrix setFrameSize:NSMakeSize(r.size.width, [matrix frame].size.height)]; | 
| 278 | 296 | 
| 279   size_t rows = model_->result().size(); | 297   // Make the window just as big. | 
| 280   [matrix renewRows:rows columns:1]; |  | 
| 281   [matrix sizeToCells]; |  | 
| 282   r.size.height = [matrix frame].size.height; | 298   r.size.height = [matrix frame].size.height; | 
| 283   r.origin.y -= r.size.height + 2; | 299   r.origin.y -= r.size.height + 2; | 
| 284 | 300 | 
| 285   for (size_t ii = 0; ii < rows; ++ii) { |  | 
| 286     AutocompleteButtonCell* cell = [matrix cellAtRow:ii column:0]; |  | 
| 287     const AutocompleteMatch& match = model_->result().match_at(ii); |  | 
| 288     [cell setImage:MatchIcon(match)]; |  | 
| 289     [cell setAttributedTitle:MatchText(match)]; |  | 
| 290   } |  | 
| 291 |  | 
| 292   // Update the selection. | 301   // Update the selection. | 
| 293   PaintUpdatesNow(); | 302   PaintUpdatesNow(); | 
| 294 | 303 | 
| 295   [popup_ setFrame:r display:YES]; | 304   [popup_ setFrame:r display:YES]; | 
| 296 | 305 | 
| 297   if (!IsOpen()) { | 306   if (!IsOpen()) { | 
| 298     [[field_ window] addChildWindow:popup_ ordered:NSWindowAbove]; | 307     [[field_ window] addChildWindow:popup_ ordered:NSWindowAbove]; | 
| 299   } | 308   } | 
| 300 } | 309 } | 
| 301 | 310 | 
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 432   } | 441   } | 
| 433   return self; | 442   return self; | 
| 434 } | 443 } | 
| 435 | 444 | 
| 436 - (void)select:sender { | 445 - (void)select:sender { | 
| 437   DCHECK(popup_view_); | 446   DCHECK(popup_view_); | 
| 438   popup_view_->AcceptInput(); | 447   popup_view_->AcceptInput(); | 
| 439 } | 448 } | 
| 440 | 449 | 
| 441 @end | 450 @end | 
| OLD | NEW | 
|---|