summaryrefslogtreecommitdiffstats
path: root/chrome/browser/autocomplete
diff options
context:
space:
mode:
authorshess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-11 20:39:08 +0000
committershess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-11 20:39:08 +0000
commit56a7fbca5b93aadbfdfb0ff20a0a95ef5c91255a (patch)
treecc3993bc0ea1e2addba819d1d72d1af156405213 /chrome/browser/autocomplete
parent753abf571c333b695c3dbea83eeca55700ef4e80 (diff)
downloadchromium_src-56a7fbca5b93aadbfdfb0ff20a0a95ef5c91255a.zip
chromium_src-56a7fbca5b93aadbfdfb0ff20a0a95ef5c91255a.tar.gz
chromium_src-56a7fbca5b93aadbfdfb0ff20a0a95ef5c91255a.tar.bz2
Style the omnibox results for v2.
The style is based on the gtk code (autocomplete_popup_view_gtk.cc), with some local tweaks. I broke this off from the rest of the review so I could experiment with making it nail omnibox-v2, but eventually realized that I don't have enough data for that. This at least makes things look nicer, and I believe it provides all of the function that will be needed (the remainder is precisely defining fonts and colors and possibly minor highlighting variations). Summary: I want something concrete so that complaints about v2 wrongness can be specific. Review URL: http://codereview.chromium.org/99312 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15777 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/autocomplete')
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_view_mac.h12
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_view_mac.mm111
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_view_mac_unittest.mm424
3 files changed, 535 insertions, 12 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_mac.h b/chrome/browser/autocomplete/autocomplete_popup_view_mac.h
index 858e2fe..eb00d23 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view_mac.h
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_mac.h
@@ -70,6 +70,18 @@ class AutocompletePopupViewMac : public AutocompletePopupView {
// helper object.
void AcceptInput();
+ // Return the text to show for the match, based on the match's
+ // contents and description.
+ static NSMutableAttributedString* MatchText(const AutocompleteMatch& match);
+
+ // Helper for MatchText() to allow sharing code between the contents
+ // and description cases. Returns NSMutableAttributedString as a
+ // convenience for MatchText().
+ static NSMutableAttributedString* DecorateMatchedString(
+ const std::wstring &matchString,
+ const AutocompleteMatch::ACMatchClassifications &classifications,
+ NSColor* textColor);
+
private:
// Create the popup_ instance if needed.
void CreatePopupIfNeeded();
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm b/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm
index 244936b..c0a2b54 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm
@@ -22,6 +22,30 @@ NSColor* HoveredBackgroundColor() {
return [NSColor controlColor];
}
+// TODO(shess): These are totally unprincipled. I experimented with
+// +controlTextColor and the like, but found myself wondering whether
+// that was really appropriate. Circle back after consulting with
+// someone more knowledgeable about the ins and outs of this.
+static const NSColor* ContentTextColor() {
+ return [NSColor blackColor];
+}
+static const NSColor* URLTextColor() {
+ return [NSColor colorWithCalibratedRed:0.0 green:0.55 blue:0.0 alpha:1.0];
+}
+static const NSColor* DescriptionTextColor() {
+ return [NSColor darkGrayColor];
+}
+
+// TODO(shess): As with colors, there are a dozen ways to phrase this,
+// all of them probably wrong. Circle back with a ui-oriented
+// resource later.
+static const NSFont* NormalFont() {
+ return [NSFont userFontOfSize:12];
+}
+static const NSFont* BoldFont() {
+ return [NSFont boldSystemFontOfSize:12];
+}
+
// Return the appropriate icon for the given match. Derived from the
// gtk code.
NSImage* MatchIcon(const AutocompleteMatch& match) {
@@ -57,23 +81,86 @@ NSImage* MatchIcon(const AutocompleteMatch& match) {
return nil;
}
-// Return the text to show for the match, based on the match's
-// contents and description.
-// TODO(shess): Style the runs within the text.
-NSString* MatchText(const AutocompleteMatch& match) {
- NSString* s = base::SysWideToNSString(match.contents);
+} // namespace
- if (!match.description.empty()) {
- NSString* description = base::SysWideToNSString(match.description);
+// Helper for MatchText() to allow sharing code between the contents
+// and description cases. Returns NSMutableAttributedString as a
+// convenience for MatchText().
+NSMutableAttributedString* AutocompletePopupViewMac::DecorateMatchedString(
+ const std::wstring &matchString,
+ const AutocompleteMatch::ACMatchClassifications &classifications,
+ NSColor* textColor) {
+
+ // Start out with a string using the default style info.
+ NSString* s = base::SysWideToNSString(matchString);
+ NSDictionary* attributes = [NSDictionary dictionaryWithObjectsAndKeys:
+ NormalFont(), NSFontAttributeName,
+ textColor, NSForegroundColorAttributeName,
+ nil];
+ NSMutableAttributedString* as =
+ [[[NSMutableAttributedString alloc] initWithString:s
+ attributes:attributes]
+ autorelease];
+
+ // Mark up the runs which differ from the default.
+ for (ACMatchClassifications::const_iterator i = classifications.begin();
+ i != classifications.end(); ++i) {
+ const BOOL isLast = (i+1) == classifications.end();
+ const size_t nextOffset = (isLast ? matchString.length() : (i+1)->offset);
+ const NSInteger location = static_cast<NSInteger>(i->offset);
+ const NSInteger length = static_cast<NSInteger>(nextOffset - i->offset);
+ const NSRange range = NSMakeRange(location, length);
+
+ if (0 != (i->style & ACMatchClassification::URL)) {
+ [as addAttribute:NSForegroundColorAttributeName
+ value:URLTextColor() range:range];
+ }
- // Append an em dash (U-2014) and description.
- s = [s stringByAppendingFormat:@" %C %@", 0x2014, description];
+ if (0 != (i->style & ACMatchClassification::MATCH)) {
+ [as addAttribute:NSFontAttributeName value:BoldFont() range:range];
+ }
}
- return s;
+ return as;
}
-} // namespace
+// Return the text to show for the match, based on the match's
+// contents and description.
+NSMutableAttributedString* AutocompletePopupViewMac::MatchText(
+ const AutocompleteMatch& match) {
+ NSMutableAttributedString *as =
+ DecorateMatchedString(match.contents, match.contents_class,
+ ContentTextColor());
+
+ // If there is a description, append it, separated from the contents
+ // with an em dash, and decorated with a distinct color.
+ if (!match.description.empty()) {
+ NSDictionary* attributes =
+ [NSDictionary dictionaryWithObjectsAndKeys:
+ NormalFont(), NSFontAttributeName,
+ ContentTextColor(), NSForegroundColorAttributeName,
+ nil];
+ NSString* rawEmDash = [NSString stringWithFormat:@" %C ", 0x2014];
+ NSAttributedString* emDash =
+ [[[NSAttributedString alloc] initWithString:rawEmDash
+ attributes:attributes] autorelease];
+
+ NSAttributedString* description =
+ DecorateMatchedString(match.description, match.description_class,
+ DescriptionTextColor());
+
+ [as appendAttributedString:emDash];
+ [as appendAttributedString:description];
+ }
+
+ NSMutableParagraphStyle* style =
+ [[[NSMutableParagraphStyle alloc] init] autorelease];
+ [style setLineBreakMode:NSLineBreakByTruncatingTail];
+ [as addAttribute:NSParagraphStyleAttributeName value:style
+ range:NSMakeRange(0, [as length])];
+
+ return as;
+}
// AutocompleteButtonCell overrides how backgrounds are displayed to
// handle hover versus selected. So long as we're in there, it also
@@ -199,7 +286,7 @@ void AutocompletePopupViewMac::UpdatePopupAppearance() {
AutocompleteButtonCell* cell = [matrix cellAtRow:ii column:0];
const AutocompleteMatch& match = model_->result().match_at(ii);
[cell setImage:MatchIcon(match)];
- [cell setTitle:MatchText(match)];
+ [cell setAttributedTitle:MatchText(match)];
}
// Update the selection.
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_mac_unittest.mm b/chrome/browser/autocomplete/autocomplete_popup_view_mac_unittest.mm
new file mode 100644
index 0000000..059a5e1
--- /dev/null
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_mac_unittest.mm
@@ -0,0 +1,424 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/autocomplete/autocomplete_popup_view_mac.h"
+
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/autocomplete/autocomplete.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class AutocompletePopupViewMacTest : public testing::Test {
+ public:
+ AutocompletePopupViewMacTest() {
+ }
+
+ // Returns the length of the run starting at |location| for which
+ // |attributeName| remains the same.
+ static NSUInteger RunLengthForAttribute(NSAttributedString* string,
+ NSUInteger location,
+ NSString* attributeName) {
+ const NSRange fullRange = NSMakeRange(0, [string length]);
+ NSRange range;
+ [string attribute:attributeName
+ atIndex:location longestEffectiveRange:&range inRange:fullRange];
+
+ // In order to signal when the run doesn't start exactly at
+ // location, return a weirdo length. This causes the incorrect
+ // expectation to manifest at the calling location, which is more
+ // useful than an EXPECT_EQ() would be here.
+ if (range.location != location) {
+ return -1;
+ }
+
+ return range.length;
+ }
+
+ // Return true if the run starting at |location| has |color| for
+ // attribute NSForegroundColorAttributeName.
+ static bool RunHasColor(NSAttributedString* string,
+ NSUInteger location, NSColor* color) {
+ const NSRange fullRange = NSMakeRange(0, [string length]);
+ NSRange range;
+ NSColor* runColor = [string attribute:NSForegroundColorAttributeName
+ atIndex:location
+ longestEffectiveRange:&range inRange:fullRange];
+
+ // According to one "Ali Ozer", you can compare objects within the
+ // same color space using -isEqual:. Converting color spaces
+ // seems too heavyweight for these tests.
+ // http://lists.apple.com/archives/cocoa-dev/2005/May/msg00186.html
+ return [runColor isEqual:color] ? true : false;
+ }
+
+ // Return true if the run starting at |location| has the font
+ // trait(s) in |mask| font in NSFontAttributeName.
+ static bool RunHasFontTrait(NSAttributedString* string, NSUInteger location,
+ NSFontTraitMask mask) {
+ const NSRange fullRange = NSMakeRange(0, [string length]);
+ NSRange range;
+ NSFont* runFont = [string attribute:NSFontAttributeName
+ atIndex:location
+ longestEffectiveRange:&range inRange:fullRange];
+ NSFontManager* fontManager = [NSFontManager sharedFontManager];
+ if (runFont && (mask == ([fontManager traitsOfFont:runFont]&mask))) {
+ return true;
+ }
+ return false;
+ }
+
+ // AutocompleteMatch doesn't really have the right constructor for our
+ // needs. Fake one for us to use.
+ static AutocompleteMatch MakeMatch(const std::wstring &contents,
+ const std::wstring &description) {
+ AutocompleteMatch m(NULL, 1, true, AutocompleteMatch::URL_WHAT_YOU_TYPED);
+ m.contents = contents;
+ m.description = description;
+ return m;
+ }
+
+};
+
+// Simple inputs with no matches should result in styled output who's
+// text matches the input string, with the passed-in color, and
+// nothing bolded.
+TEST_F(AutocompletePopupViewMacTest, DecorateMatchedStringNoMatch) {
+ const NSString* string = @"This is a test";
+ AutocompleteMatch::ACMatchClassifications classifications;
+
+ NSAttributedString* decorated =
+ AutocompletePopupViewMac::DecorateMatchedString(
+ base::SysNSStringToWide(string), classifications,
+ [NSColor blackColor]);
+
+ // Result has same characters as the input.
+ EXPECT_EQ([decorated length], [string length]);
+ EXPECT_TRUE([[decorated string] isEqualToString:string]);
+
+ // Our passed-in color for the entire string.
+ EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
+ NSForegroundColorAttributeName),
+ [string length]);
+ EXPECT_TRUE(RunHasColor(decorated, 0U, [NSColor blackColor]));
+
+ // An unbolded font for the entire string.
+ EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
+ NSFontAttributeName), [string length]);
+ EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
+}
+
+// Identical to DecorateMatchedStringNoMatch, except test that URL
+// style gets a different color than we passed in.
+TEST_F(AutocompletePopupViewMacTest, DecorateMatchedStringURLNoMatch) {
+ const NSString* string = @"This is a test";
+ AutocompleteMatch::ACMatchClassifications classifications;
+
+ classifications.push_back(
+ ACMatchClassification(0, ACMatchClassification::URL));
+
+ NSAttributedString* decorated =
+ AutocompletePopupViewMac::DecorateMatchedString(
+ base::SysNSStringToWide(string), classifications,
+ [NSColor blackColor]);
+
+ // Result has same characters as the input.
+ EXPECT_EQ([decorated length], [string length]);
+ EXPECT_TRUE([[decorated string] isEqualToString:string]);
+
+ // One color for the entire string, and it's not the one we passed in.
+ EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
+ NSForegroundColorAttributeName),
+ [string length]);
+ EXPECT_FALSE(RunHasColor(decorated, 0U, [NSColor blackColor]));
+
+ // An unbolded font for the entire string.
+ EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
+ NSFontAttributeName), [string length]);
+ EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
+}
+
+// Test that DIM doesn't have any impact - true at this time.
+TEST_F(AutocompletePopupViewMacTest, DecorateMatchedStringDimNoMatch) {
+ const NSString* string = @"This is a test";
+
+ // Switch to DIM halfway through.
+ AutocompleteMatch::ACMatchClassifications classifications;
+ classifications.push_back(
+ ACMatchClassification(0, ACMatchClassification::NONE));
+ classifications.push_back(
+ ACMatchClassification([string length] / 2, ACMatchClassification::DIM));
+
+ NSAttributedString* decorated =
+ AutocompletePopupViewMac::DecorateMatchedString(
+ base::SysNSStringToWide(string), classifications,
+ [NSColor blackColor]);
+
+ // Result has same characters as the input.
+ EXPECT_EQ([decorated length], [string length]);
+ EXPECT_TRUE([[decorated string] isEqualToString:string]);
+
+ // Our passed-in color for the entire string.
+ EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
+ NSForegroundColorAttributeName),
+ [string length]);
+ EXPECT_TRUE(RunHasColor(decorated, 0U, [NSColor blackColor]));
+
+ // An unbolded font for the entire string.
+ EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
+ NSFontAttributeName), [string length]);
+ EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
+}
+
+// Test that the matched run gets bold-faced, but keeps the same
+// color.
+TEST_F(AutocompletePopupViewMacTest, DecorateMatchedStringMatch) {
+ const NSString* string = @"This is a test";
+ // Match "is".
+ const NSUInteger runLength1 = 5, runLength2 = 2, runLength3 = 7;
+ // Make sure nobody messed up the inputs.
+ EXPECT_EQ(runLength1 + runLength2 + runLength3, [string length]);
+
+ // Push each run onto classifications.
+ AutocompleteMatch::ACMatchClassifications classifications;
+ classifications.push_back(
+ ACMatchClassification(0, ACMatchClassification::NONE));
+ classifications.push_back(
+ ACMatchClassification(runLength1, ACMatchClassification::MATCH));
+ classifications.push_back(
+ ACMatchClassification(runLength1 + runLength2,
+ ACMatchClassification::NONE));
+
+ NSAttributedString* decorated =
+ AutocompletePopupViewMac::DecorateMatchedString(
+ base::SysNSStringToWide(string), classifications,
+ [NSColor blackColor]);
+
+ // Result has same characters as the input.
+ EXPECT_EQ([decorated length], [string length]);
+ EXPECT_TRUE([[decorated string] isEqualToString:string]);
+
+ // Our passed-in color for the entire string.
+ EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
+ NSForegroundColorAttributeName),
+ [string length]);
+ EXPECT_TRUE(RunHasColor(decorated, 0U, [NSColor blackColor]));
+
+ // Should have three font runs, not bold, bold, then not bold again.
+ EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
+ NSFontAttributeName), runLength1);
+ EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
+
+ EXPECT_EQ(RunLengthForAttribute(decorated, runLength1,
+ NSFontAttributeName), runLength2);
+ EXPECT_TRUE(RunHasFontTrait(decorated, runLength1, NSBoldFontMask));
+
+ EXPECT_EQ(RunLengthForAttribute(decorated, runLength1 + runLength2,
+ NSFontAttributeName), runLength3);
+ EXPECT_FALSE(RunHasFontTrait(decorated, runLength1 + runLength2,
+ NSBoldFontMask));
+}
+
+// Just like DecorateMatchedStringURLMatch, this time with URL style.
+TEST_F(AutocompletePopupViewMacTest, DecorateMatchedStringURLMatch) {
+ const NSString* string = @"http://hello.world/";
+ // Match "hello".
+ const NSUInteger runLength1 = 7, runLength2 = 5, runLength3 = 7;
+ // Make sure nobody messed up the inputs.
+ EXPECT_EQ(runLength1 + runLength2 + runLength3, [string length]);
+
+ // Push each run onto classifications.
+ AutocompleteMatch::ACMatchClassifications classifications;
+ classifications.push_back(
+ ACMatchClassification(0, ACMatchClassification::URL));
+ const int kURLMatch = ACMatchClassification::URL|ACMatchClassification::MATCH;
+ classifications.push_back(ACMatchClassification(runLength1, kURLMatch));
+ classifications.push_back(
+ ACMatchClassification(runLength1 + runLength2,
+ ACMatchClassification::URL));
+
+ NSAttributedString* decorated =
+ AutocompletePopupViewMac::DecorateMatchedString(
+ base::SysNSStringToWide(string), classifications,
+ [NSColor blackColor]);
+
+ // Result has same characters as the input.
+ EXPECT_EQ([decorated length], [string length]);
+ EXPECT_TRUE([[decorated string] isEqualToString:string]);
+
+ // One color for the entire string, and it's not the one we passed in.
+ EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
+ NSForegroundColorAttributeName),
+ [string length]);
+ EXPECT_FALSE(RunHasColor(decorated, 0U, [NSColor blackColor]));
+
+ // Should have three font runs, not bold, bold, then not bold again.
+ EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
+ NSFontAttributeName), runLength1);
+ EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
+
+ EXPECT_EQ(RunLengthForAttribute(decorated, runLength1,
+ NSFontAttributeName), runLength2);
+ EXPECT_TRUE(RunHasFontTrait(decorated, runLength1, NSBoldFontMask));
+
+ EXPECT_EQ(RunLengthForAttribute(decorated, runLength1 + runLength2,
+ NSFontAttributeName), runLength3);
+ EXPECT_FALSE(RunHasFontTrait(decorated, runLength1 + runLength2,
+ NSBoldFontMask));
+}
+
+// Check that matches with both contents and description come back
+// with contents at the beginning, description at the end, and
+// something separating them. Not being specific about the separator
+// on purpose, in case it changes.
+TEST_F(AutocompletePopupViewMacTest, MatchText) {
+ const NSString* contents = @"contents";
+ const NSString* description = @"description";
+ AutocompleteMatch m = MakeMatch(base::SysNSStringToWide(contents),
+ base::SysNSStringToWide(description));
+
+ NSAttributedString* decorated = AutocompletePopupViewMac::MatchText(m);
+
+ // Result contains the characters of the input in the right places.
+ EXPECT_GT([decorated length], [contents length] + [description length]);
+ EXPECT_TRUE([[decorated string] hasPrefix:contents]);
+ EXPECT_TRUE([[decorated string] hasSuffix:description]);
+
+ // Check that the description is a different color from the
+ // contents.
+ const NSUInteger descriptionLocation =
+ [decorated length] - [description length];
+ EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
+ NSForegroundColorAttributeName),
+ descriptionLocation);
+ EXPECT_EQ(RunLengthForAttribute(decorated, descriptionLocation,
+ NSForegroundColorAttributeName),
+ [description length]);
+
+ // Same font all the way through, nothing bold.
+ EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
+ NSFontAttributeName), [decorated length]);
+ EXPECT_FALSE(RunHasFontTrait(decorated, 0, NSBoldFontMask));
+}
+
+// Check that MatchText() styles content matches as expected.
+TEST_F(AutocompletePopupViewMacTest, MatchTextContentsMatch) {
+ const NSString* contents = @"This is a test";
+ // Match "is".
+ const NSUInteger runLength1 = 5, runLength2 = 2, runLength3 = 7;
+ // Make sure nobody messed up the inputs.
+ EXPECT_EQ(runLength1 + runLength2 + runLength3, [contents length]);
+
+ AutocompleteMatch m = MakeMatch(base::SysNSStringToWide(contents),
+ std::wstring());
+
+ // Push each run onto contents classifications.
+ m.contents_class.push_back(
+ ACMatchClassification(0, ACMatchClassification::NONE));
+ m.contents_class.push_back(
+ ACMatchClassification(runLength1, ACMatchClassification::MATCH));
+ m.contents_class.push_back(
+ ACMatchClassification(runLength1 + runLength2,
+ ACMatchClassification::NONE));
+
+ NSAttributedString* decorated = AutocompletePopupViewMac::MatchText(m);
+
+ // Result has same characters as the input.
+ EXPECT_EQ([decorated length], [contents length]);
+ EXPECT_TRUE([[decorated string] isEqualToString:contents]);
+
+ // Result is all one color.
+ EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
+ NSForegroundColorAttributeName),
+ [contents length]);
+
+ // Should have three font runs, not bold, bold, then not bold again.
+ EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
+ NSFontAttributeName), runLength1);
+ EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
+
+ EXPECT_EQ(RunLengthForAttribute(decorated, runLength1,
+ NSFontAttributeName), runLength2);
+ EXPECT_TRUE(RunHasFontTrait(decorated, runLength1, NSBoldFontMask));
+
+ EXPECT_EQ(RunLengthForAttribute(decorated, runLength1 + runLength2,
+ NSFontAttributeName), runLength3);
+ EXPECT_FALSE(RunHasFontTrait(decorated, runLength1 + runLength2,
+ NSBoldFontMask));
+}
+
+// Check that MatchText() styles description matches as expected.
+TEST_F(AutocompletePopupViewMacTest, MatchTextDescriptionMatch) {
+ const NSString* contents = @"This is a test";
+ const NSString* description = @"That was a test";
+ // Match "That was".
+ const NSUInteger runLength1 = 8, runLength2 = 7;
+ // Make sure nobody messed up the inputs.
+ EXPECT_EQ(runLength1 + runLength2, [description length]);
+
+ AutocompleteMatch m = MakeMatch(base::SysNSStringToWide(contents),
+ base::SysNSStringToWide(description));
+
+ // Push each run onto contents classifications.
+ m.description_class.push_back(
+ ACMatchClassification(0, ACMatchClassification::MATCH));
+ m.description_class.push_back(
+ ACMatchClassification(runLength1, ACMatchClassification::NONE));
+
+ NSAttributedString* decorated = AutocompletePopupViewMac::MatchText(m);
+
+ // Result contains the characters of the input.
+ EXPECT_GT([decorated length], [contents length] + [description length]);
+ EXPECT_TRUE([[decorated string] hasPrefix:contents]);
+ EXPECT_TRUE([[decorated string] hasSuffix:description]);
+
+ // Check that the description is a different color from the
+ // contents.
+ const NSUInteger descriptionLocation =
+ [decorated length] - [description length];
+ EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
+ NSForegroundColorAttributeName),
+ descriptionLocation);
+ EXPECT_EQ(RunLengthForAttribute(decorated, descriptionLocation,
+ NSForegroundColorAttributeName),
+ [description length]);
+
+ // Should have three font runs, not bold, bold, then not bold again.
+ // The first run is the contents and the separator, the second run
+ // is the first run of the description.
+ EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
+ NSFontAttributeName), descriptionLocation);
+ EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
+
+ EXPECT_EQ(RunLengthForAttribute(decorated, descriptionLocation,
+ NSFontAttributeName), runLength1);
+ EXPECT_TRUE(RunHasFontTrait(decorated, descriptionLocation, NSBoldFontMask));
+
+ EXPECT_EQ(RunLengthForAttribute(decorated, descriptionLocation + runLength1,
+ NSFontAttributeName), runLength2);
+ EXPECT_FALSE(RunHasFontTrait(decorated, descriptionLocation + runLength1,
+ NSBoldFontMask));
+}
+
+// TODO(shess): Test that
+// AutocompletePopupViewMac::UpdatePopupAppearance() creates/destroys
+// the popup according to result contents. Test that the matrix gets
+// the right number of results. Test the contents of the cells for
+// the right strings. Icons? Maybe, that seems harder to test.
+// Styling seems almost impossible.
+
+// TODO(shess): Test that AutocompletePopupViewMac::PaintUpdatesNow()
+// updates the matrix selection.
+
+// TODO(shess): Test that AutocompletePopupViewMac::AcceptInput()
+// updates the model's selection from the matrix before returning.
+// Could possibly test that via -select:.
+
+// TODO(shess): Test that AutocompleteButtonCell returns the right
+// background colors for on, highlighted, and neither.
+
+// TODO(shess): Test that AutocompleteMatrixTarget can be initialized
+// and then sends -select: to the view.
+
+} // namespace