Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(332)

Side by Side Diff: chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm

Issue 1821823004: [Mac][Material Design] Update Omnibox dropdown on Mac to MD (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address feedback. Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/omnibox/omnibox_popup_cell.h" 5 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <cmath> 10 #include <cmath>
11 11
12 #include "base/i18n/rtl.h" 12 #include "base/i18n/rtl.h"
13 #include "base/mac/foundation_util.h" 13 #include "base/mac/foundation_util.h"
14 #include "base/mac/scoped_nsobject.h" 14 #include "base/mac/scoped_nsobject.h"
15 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_util.h" 16 #include "base/strings/string_util.h"
17 #include "base/strings/sys_string_conversions.h" 17 #include "base/strings/sys_string_conversions.h"
18 #include "base/strings/utf_string_conversions.h" 18 #include "base/strings/utf_string_conversions.h"
19 #include "chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h" 19 #include "chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h"
20 #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h" 20 #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
21 #import "chrome/browser/ui/cocoa/themed_window.h"
21 #include "chrome/grit/generated_resources.h" 22 #include "chrome/grit/generated_resources.h"
22 #include "components/omnibox/browser/omnibox_popup_model.h" 23 #include "components/omnibox/browser/omnibox_popup_model.h"
23 #include "components/omnibox/browser/suggestion_answer.h" 24 #include "components/omnibox/browser/suggestion_answer.h"
24 #include "skia/ext/skia_utils_mac.h" 25 #include "skia/ext/skia_utils_mac.h"
25 #include "ui/base/l10n/l10n_util.h" 26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/base/material_design/material_design_controller.h"
28 #include "ui/gfx/color_palette.h"
26 #include "ui/gfx/font.h" 29 #include "ui/gfx/font.h"
27 30
28 namespace { 31 namespace {
29 32
30 // How far to offset image column from the left. 33 // How far to offset image column from the left.
31 const CGFloat kImageXOffset = 5.0; 34 const CGFloat kImageXOffset = 5.0;
32 35
33 // How far to offset image and text. 36 // How far to offset text.
34 const CGFloat kPaddingOffset = 3.0; 37 const CGFloat kVerticalTextPadding = 3.0;
35 38
36 // How far to offset the text column from the left. 39 const CGFloat kVerticalImagePadding = 3.0;
40 const CGFloat kMaterialVerticalImagePadding = 5.0;
41
37 const CGFloat kTextStartOffset = 28.0; 42 const CGFloat kTextStartOffset = 28.0;
43 const CGFloat kMaterialTextStartOffset = 25.0;
38 44
39 // Rounding radius of selection and hover background on popup items. 45 // Rounding radius of selection and hover background on popup items.
40 const CGFloat kCellRoundingRadius = 2.0; 46 const CGFloat kCellRoundingRadius = 2.0;
41 47
48 // How far to offset the image.
49 CGFloat VerticalImagePadding() {
50 if (!ui::MaterialDesignController::IsModeMaterial()) {
51 return kVerticalImagePadding;
52 }
53 return kMaterialVerticalImagePadding;
54 }
55
56 // How far to offset the text column from the left.
57 CGFloat TextStartOffset() {
58 if (!ui::MaterialDesignController::IsModeMaterial()) {
59 return kTextStartOffset;
60 }
61 return kMaterialTextStartOffset;
62 }
63
42 // Flips the given |rect| in context of the given |frame|. 64 // Flips the given |rect| in context of the given |frame|.
43 NSRect FlipIfRTL(NSRect rect, NSRect frame) { 65 NSRect FlipIfRTL(NSRect rect, NSRect frame) {
44 DCHECK_LE(NSMinX(frame), NSMinX(rect)); 66 DCHECK_LE(NSMinX(frame), NSMinX(rect));
45 DCHECK_GE(NSMaxX(frame), NSMaxX(rect)); 67 DCHECK_GE(NSMaxX(frame), NSMaxX(rect));
46 if (base::i18n::IsRTL()) { 68 if (base::i18n::IsRTL()) {
47 NSRect result = rect; 69 NSRect result = rect;
48 result.origin.x = NSMinX(frame) + (NSMaxX(frame) - NSMaxX(rect)); 70 result.origin.x = NSMinX(frame) + (NSMaxX(frame) - NSMaxX(rect));
49 return result; 71 return result;
50 } 72 }
51 return rect; 73 return rect;
52 } 74 }
53 75
54 NSColor* SelectedBackgroundColor() { 76 NSColor* SelectedBackgroundColor(BOOL is_dark_theme) {
77 if (is_dark_theme && ui::MaterialDesignController::IsModeMaterial()) {
78 return skia::SkColorToSRGBNSColor(SkColorSetA(SK_ColorWHITE, 0x14));
79 }
55 return [NSColor selectedControlColor]; 80 return [NSColor selectedControlColor];
56 } 81 }
57 NSColor* HoveredBackgroundColor() { 82
83 NSColor* HoveredBackgroundColor(BOOL is_dark_theme) {
84 if (is_dark_theme) {
85 return skia::SkColorToSRGBNSColor(SkColorSetA(SK_ColorWHITE, 0x0D));
86 }
58 return [NSColor controlHighlightColor]; 87 return [NSColor controlHighlightColor];
59 } 88 }
60 89
61 NSColor* ContentTextColor() { 90 NSColor* ContentTextColor(BOOL is_dark_theme) {
91 if (ui::MaterialDesignController::IsModeMaterial() && is_dark_theme) {
92 return [NSColor whiteColor];
93 }
62 return [NSColor blackColor]; 94 return [NSColor blackColor];
63 } 95 }
64 NSColor* DimTextColor() { 96 NSColor* DimTextColor(BOOL is_dark_theme) {
65 return [NSColor darkGrayColor]; 97 if (!ui::MaterialDesignController::IsModeMaterial()) {
98 return [NSColor darkGrayColor];
99 }
100 if (is_dark_theme) {
101 return skia::SkColorToSRGBNSColor(SkColorSetA(SK_ColorWHITE, 0x7F));
102 }
103 return skia::SkColorToSRGBNSColor(SkColorSetRGB(0x64, 0x64, 0x64));
66 } 104 }
67 NSColor* PositiveTextColor() { 105 NSColor* PositiveTextColor() {
68 return skia::SkColorToCalibratedNSColor(SkColorSetRGB(0x3d, 0x94, 0x00)); 106 return skia::SkColorToCalibratedNSColor(SkColorSetRGB(0x3d, 0x94, 0x00));
69 } 107 }
70 NSColor* NegativeTextColor() { 108 NSColor* NegativeTextColor() {
71 return skia::SkColorToCalibratedNSColor(SkColorSetRGB(0xdd, 0x4b, 0x39)); 109 return skia::SkColorToCalibratedNSColor(SkColorSetRGB(0xdd, 0x4b, 0x39));
72 } 110 }
73 NSColor* URLTextColor() { 111 NSColor* URLTextColor(BOOL is_dark_theme) {
112 if (ui::MaterialDesignController::IsModeMaterial() && is_dark_theme) {
113 return skia::SkColorToSRGBNSColor(gfx::kGoogleBlue300);
114 }
74 return [NSColor colorWithCalibratedRed:0.0 green:0.55 blue:0.0 alpha:1.0]; 115 return [NSColor colorWithCalibratedRed:0.0 green:0.55 blue:0.0 alpha:1.0];
75 } 116 }
76 117
77 NSFont* FieldFont() { 118 NSFont* FieldFont() {
78 return OmniboxViewMac::GetFieldFont(gfx::Font::NORMAL); 119 return OmniboxViewMac::GetFieldFont(gfx::Font::NORMAL);
79 } 120 }
80 NSFont* BoldFieldFont() { 121 NSFont* BoldFieldFont() {
81 return OmniboxViewMac::GetFieldFont(gfx::Font::BOLD); 122 return OmniboxViewMac::GetFieldFont(gfx::Font::BOLD);
82 } 123 }
83 NSFont* LargeFont() { 124 NSFont* LargeFont() {
84 return OmniboxViewMac::GetLargeFont(gfx::Font::NORMAL); 125 return OmniboxViewMac::GetLargeFont(gfx::Font::NORMAL);
85 } 126 }
86 NSFont* LargeSuperscriptFont() { 127 NSFont* LargeSuperscriptFont() {
87 NSFont* font = OmniboxViewMac::GetLargeFont(gfx::Font::NORMAL); 128 NSFont* font = OmniboxViewMac::GetLargeFont(gfx::Font::NORMAL);
88 // Calculate a slightly smaller font. The ratio here is somewhat arbitrary. 129 // Calculate a slightly smaller font. The ratio here is somewhat arbitrary.
89 // Proportions from 5/9 to 5/7 all look pretty good. 130 // Proportions from 5/9 to 5/7 all look pretty good.
90 CGFloat size = [font pointSize] * 5.0 / 9.0; 131 CGFloat size = [font pointSize] * 5.0 / 9.0;
91 NSFontDescriptor* descriptor = [font fontDescriptor]; 132 NSFontDescriptor* descriptor = [font fontDescriptor];
92 return [NSFont fontWithDescriptor:descriptor size:size]; 133 return [NSFont fontWithDescriptor:descriptor size:size];
93 } 134 }
94 NSFont* SmallFont() { 135 NSFont* SmallFont() {
95 return OmniboxViewMac::GetSmallFont(gfx::Font::NORMAL); 136 return OmniboxViewMac::GetSmallFont(gfx::Font::NORMAL);
96 } 137 }
97 138
98 CGFloat GetContentAreaWidth(NSRect cellFrame) { 139 CGFloat GetContentAreaWidth(NSRect cellFrame) {
99 return NSWidth(cellFrame) - kTextStartOffset; 140 return NSWidth(cellFrame) - TextStartOffset();
100 } 141 }
101 142
102 NSAttributedString* CreateAnswerStringHelper(const base::string16& text, 143 NSAttributedString* CreateAnswerStringHelper(const base::string16& text,
103 NSInteger style_type, 144 NSInteger style_type,
104 bool is_bold) { 145 bool is_bold,
146 BOOL is_dark_theme) {
105 NSDictionary* answer_style = nil; 147 NSDictionary* answer_style = nil;
148 NSFont* answer_font = nil;
149 bool is_mode_material = ui::MaterialDesignController::IsModeMaterial();
106 switch (style_type) { 150 switch (style_type) {
107 case SuggestionAnswer::TOP_ALIGNED: 151 case SuggestionAnswer::TOP_ALIGNED:
108 answer_style = @{ 152 answer_style = @{
109 NSForegroundColorAttributeName : DimTextColor(), 153 NSForegroundColorAttributeName : DimTextColor(is_dark_theme),
110 NSFontAttributeName : LargeSuperscriptFont(), 154 NSFontAttributeName : LargeSuperscriptFont(),
111 NSSuperscriptAttributeName : @1 155 NSSuperscriptAttributeName : @1
112 }; 156 };
113 break; 157 break;
114 case SuggestionAnswer::DESCRIPTION_NEGATIVE: 158 case SuggestionAnswer::DESCRIPTION_NEGATIVE:
115 answer_style = @{ 159 answer_style = @{
116 NSForegroundColorAttributeName : NegativeTextColor(), 160 NSForegroundColorAttributeName : NegativeTextColor(),
117 NSFontAttributeName : LargeSuperscriptFont() 161 NSFontAttributeName : LargeSuperscriptFont()
118 }; 162 };
119 break; 163 break;
120 case SuggestionAnswer::DESCRIPTION_POSITIVE: 164 case SuggestionAnswer::DESCRIPTION_POSITIVE:
121 answer_style = @{ 165 answer_style = @{
122 NSForegroundColorAttributeName : PositiveTextColor(), 166 NSForegroundColorAttributeName : PositiveTextColor(),
123 NSFontAttributeName : LargeSuperscriptFont() 167 NSFontAttributeName : LargeSuperscriptFont()
124 }; 168 };
125 break; 169 break;
126 case SuggestionAnswer::PERSONALIZED_SUGGESTION: 170 case SuggestionAnswer::PERSONALIZED_SUGGESTION:
127 answer_style = @{ 171 answer_style = @{
128 NSForegroundColorAttributeName : ContentTextColor(), 172 NSForegroundColorAttributeName : ContentTextColor(is_dark_theme),
129 NSFontAttributeName : FieldFont() 173 NSFontAttributeName : FieldFont()
130 }; 174 };
131 break; 175 break;
132 case SuggestionAnswer::ANSWER_TEXT_MEDIUM: 176 case SuggestionAnswer::ANSWER_TEXT_MEDIUM:
133 answer_style = @{ 177 answer_style = @{
134 NSForegroundColorAttributeName : ContentTextColor(), 178 NSForegroundColorAttributeName : ContentTextColor(is_dark_theme),
135 NSFontAttributeName : FieldFont() 179 NSFontAttributeName : FieldFont()
136 }; 180 };
137 break; 181 break;
138 case SuggestionAnswer::ANSWER_TEXT_LARGE: 182 case SuggestionAnswer::ANSWER_TEXT_LARGE:
139 answer_style = @{ 183 answer_style = @{
140 NSForegroundColorAttributeName : ContentTextColor(), 184 NSForegroundColorAttributeName : ContentTextColor(is_dark_theme),
141 NSFontAttributeName : LargeFont() 185 NSFontAttributeName : LargeFont()
142 }; 186 };
143 break; 187 break;
144 case SuggestionAnswer::SUGGESTION_SECONDARY_TEXT_SMALL: 188 case SuggestionAnswer::SUGGESTION_SECONDARY_TEXT_SMALL:
189 answer_font = is_mode_material ? FieldFont()
190 : SmallFont();
145 answer_style = @{ 191 answer_style = @{
146 NSForegroundColorAttributeName : DimTextColor(), 192 NSForegroundColorAttributeName : DimTextColor(is_dark_theme),
147 NSFontAttributeName : SmallFont() 193 NSFontAttributeName : answer_font
148 }; 194 };
149 break; 195 break;
150 case SuggestionAnswer::SUGGESTION_SECONDARY_TEXT_MEDIUM: 196 case SuggestionAnswer::SUGGESTION_SECONDARY_TEXT_MEDIUM:
197 answer_font = is_mode_material ? LargeSuperscriptFont()
198 : FieldFont();
151 answer_style = @{ 199 answer_style = @{
152 NSForegroundColorAttributeName : DimTextColor(), 200 NSForegroundColorAttributeName : DimTextColor(is_dark_theme),
153 NSFontAttributeName : FieldFont() 201 NSFontAttributeName : answer_font
154 }; 202 };
155 break; 203 break;
156 case SuggestionAnswer::SUGGESTION: // Fall through. 204 case SuggestionAnswer::SUGGESTION: // Fall through.
157 default: 205 default:
158 answer_style = @{ 206 answer_style = @{
159 NSForegroundColorAttributeName : ContentTextColor (), 207 NSForegroundColorAttributeName : ContentTextColor(is_dark_theme),
160 NSFontAttributeName : FieldFont() 208 NSFontAttributeName : FieldFont()
161 }; 209 };
162 break; 210 break;
163 } 211 }
164 212
165 if (is_bold) { 213 if (is_bold) {
166 NSMutableDictionary* bold_style = [answer_style mutableCopy]; 214 NSMutableDictionary* bold_style = [answer_style mutableCopy];
167 // TODO(dschuyler): Account for bolding fonts other than FieldFont. 215 // TODO(dschuyler): Account for bolding fonts other than FieldFont.
168 // Field font is the only one currently necessary to bold. 216 // Field font is the only one currently necessary to bold.
169 [bold_style setObject:BoldFieldFont() forKey:NSFontAttributeName]; 217 [bold_style setObject:BoldFieldFont() forKey:NSFontAttributeName];
170 answer_style = bold_style; 218 answer_style = bold_style;
171 } 219 }
172 220
173 return [[[NSAttributedString alloc] 221 return [[[NSAttributedString alloc]
174 initWithString:base::SysUTF16ToNSString(text) 222 initWithString:base::SysUTF16ToNSString(text)
175 attributes:answer_style] autorelease]; 223 attributes:answer_style] autorelease];
176 } 224 }
177 225
178 NSAttributedString* CreateAnswerString(const base::string16& text, 226 NSAttributedString* CreateAnswerString(const base::string16& text,
179 NSInteger style_type) { 227 NSInteger style_type,
228 BOOL is_dark_theme) {
180 // TODO(dschuyler): make this better. Right now this only supports unnested 229 // TODO(dschuyler): make this better. Right now this only supports unnested
181 // bold tags. In the future we'll need to flag unexpected tags while adding 230 // bold tags. In the future we'll need to flag unexpected tags while adding
182 // support for b, i, u, sub, and sup. We'll also need to support HTML 231 // support for b, i, u, sub, and sup. We'll also need to support HTML
183 // entities (&lt; for '<', etc.). 232 // entities (&lt; for '<', etc.).
184 const base::string16 begin_tag = base::ASCIIToUTF16("<b>"); 233 const base::string16 begin_tag = base::ASCIIToUTF16("<b>");
185 const base::string16 end_tag = base::ASCIIToUTF16("</b>"); 234 const base::string16 end_tag = base::ASCIIToUTF16("</b>");
186 size_t begin = 0; 235 size_t begin = 0;
187 base::scoped_nsobject<NSMutableAttributedString> result( 236 base::scoped_nsobject<NSMutableAttributedString> result(
188 [[NSMutableAttributedString alloc] init]); 237 [[NSMutableAttributedString alloc] init]);
189 while (true) { 238 while (true) {
190 size_t end = text.find(begin_tag, begin); 239 size_t end = text.find(begin_tag, begin);
191 if (end == base::string16::npos) { 240 if (end == base::string16::npos) {
192 [result 241 [result
193 appendAttributedString:CreateAnswerStringHelper( 242 appendAttributedString:CreateAnswerStringHelper(
194 text.substr(begin), 243 text.substr(begin),
195 style_type, false)]; 244 style_type,
245 false,
246 is_dark_theme)];
196 break; 247 break;
197 } 248 }
198 [result appendAttributedString:CreateAnswerStringHelper( 249 [result appendAttributedString:CreateAnswerStringHelper(
199 text.substr(begin, end - begin), 250 text.substr(begin, end - begin),
200 style_type, false)]; 251 style_type,
252 false,
253 is_dark_theme)];
201 begin = end + begin_tag.length(); 254 begin = end + begin_tag.length();
202 end = text.find(end_tag, begin); 255 end = text.find(end_tag, begin);
203 if (end == base::string16::npos) 256 if (end == base::string16::npos)
204 break; 257 break;
205 [result appendAttributedString:CreateAnswerStringHelper( 258 [result appendAttributedString:CreateAnswerStringHelper(
206 text.substr(begin, end - begin), 259 text.substr(begin, end - begin),
207 style_type, true)]; 260 style_type,
261 true,
262 is_dark_theme)];
208 begin = end + end_tag.length(); 263 begin = end + end_tag.length();
209 } 264 }
210 return result.autorelease(); 265 return result.autorelease();
211 } 266 }
212 267
213 NSAttributedString* CreateAnswerLine(const SuggestionAnswer::ImageLine& line) { 268 NSAttributedString* CreateAnswerLine(const SuggestionAnswer::ImageLine& line,
269 BOOL is_dark_theme) {
214 base::scoped_nsobject<NSMutableAttributedString> answer_string( 270 base::scoped_nsobject<NSMutableAttributedString> answer_string(
215 [[NSMutableAttributedString alloc] init]); 271 [[NSMutableAttributedString alloc] init]);
216 DCHECK(!line.text_fields().empty()); 272 DCHECK(!line.text_fields().empty());
217 for (const SuggestionAnswer::TextField& text_field : line.text_fields()) { 273 for (const SuggestionAnswer::TextField& text_field : line.text_fields()) {
218 [answer_string 274 [answer_string
219 appendAttributedString:CreateAnswerString(text_field.text(), 275 appendAttributedString:CreateAnswerString(text_field.text(),
220 text_field.type())]; 276 text_field.type(),
277 is_dark_theme)];
221 } 278 }
222 const base::string16 space(base::ASCIIToUTF16(" ")); 279 const base::string16 space(base::ASCIIToUTF16(" "));
223 const SuggestionAnswer::TextField* text_field = line.additional_text(); 280 const SuggestionAnswer::TextField* text_field = line.additional_text();
224 if (text_field) { 281 if (text_field) {
225 [answer_string 282 [answer_string
226 appendAttributedString:CreateAnswerString(space + text_field->text(), 283 appendAttributedString:CreateAnswerString(space + text_field->text(),
227 text_field->type())]; 284 text_field->type(),
285 is_dark_theme)];
228 } 286 }
229 text_field = line.status_text(); 287 text_field = line.status_text();
230 if (text_field) { 288 if (text_field) {
231 [answer_string 289 [answer_string
232 appendAttributedString:CreateAnswerString(space + text_field->text(), 290 appendAttributedString:CreateAnswerString(space + text_field->text(),
233 text_field->type())]; 291 text_field->type(),
292 is_dark_theme)];
234 } 293 }
235 base::scoped_nsobject<NSMutableParagraphStyle> style( 294 base::scoped_nsobject<NSMutableParagraphStyle> style(
236 [[NSMutableParagraphStyle alloc] init]); 295 [[NSMutableParagraphStyle alloc] init]);
237 [style setLineBreakMode:NSLineBreakByTruncatingTail]; 296 [style setLineBreakMode:NSLineBreakByTruncatingTail];
238 [style setTighteningFactorForTruncation:0.0]; 297 [style setTighteningFactorForTruncation:0.0];
239 [answer_string addAttribute:NSParagraphStyleAttributeName 298 [answer_string addAttribute:NSParagraphStyleAttributeName
240 value:style 299 value:style
241 range:NSMakeRange(0, [answer_string length])]; 300 range:NSMakeRange(0, [answer_string length])];
242 return answer_string.autorelease(); 301 return answer_string.autorelease();
243 } 302 }
(...skipping 26 matching lines...) Expand all
270 329
271 NSMutableAttributedString* CreateAttributedString( 330 NSMutableAttributedString* CreateAttributedString(
272 const base::string16& text, 331 const base::string16& text,
273 NSColor* text_color) { 332 NSColor* text_color) {
274 return CreateAttributedString(text, text_color, NSNaturalTextAlignment); 333 return CreateAttributedString(text, text_color, NSNaturalTextAlignment);
275 } 334 }
276 335
277 NSAttributedString* CreateClassifiedAttributedString( 336 NSAttributedString* CreateClassifiedAttributedString(
278 const base::string16& text, 337 const base::string16& text,
279 NSColor* text_color, 338 NSColor* text_color,
280 const ACMatchClassifications& classifications) { 339 const ACMatchClassifications& classifications,
340 BOOL is_dark_theme) {
281 NSMutableAttributedString* attributedString = 341 NSMutableAttributedString* attributedString =
282 CreateAttributedString(text, text_color); 342 CreateAttributedString(text, text_color);
283 NSUInteger match_length = [attributedString length]; 343 NSUInteger match_length = [attributedString length];
284 344
285 // Mark up the runs which differ from the default. 345 // Mark up the runs which differ from the default.
286 for (ACMatchClassifications::const_iterator i = classifications.begin(); 346 for (ACMatchClassifications::const_iterator i = classifications.begin();
287 i != classifications.end(); ++i) { 347 i != classifications.end(); ++i) {
288 const bool is_last = ((i + 1) == classifications.end()); 348 const bool is_last = ((i + 1) == classifications.end());
289 const NSUInteger next_offset = 349 const NSUInteger next_offset =
290 (is_last ? match_length : static_cast<NSUInteger>((i + 1)->offset)); 350 (is_last ? match_length : static_cast<NSUInteger>((i + 1)->offset));
291 const NSUInteger location = static_cast<NSUInteger>(i->offset); 351 const NSUInteger location = static_cast<NSUInteger>(i->offset);
292 const NSUInteger length = next_offset - static_cast<NSUInteger>(i->offset); 352 const NSUInteger length = next_offset - static_cast<NSUInteger>(i->offset);
293 // Guard against bad, off-the-end classification ranges. 353 // Guard against bad, off-the-end classification ranges.
294 if (location >= match_length || length <= 0) 354 if (location >= match_length || length <= 0)
295 break; 355 break;
296 const NSRange range = 356 const NSRange range =
297 NSMakeRange(location, std::min(length, match_length - location)); 357 NSMakeRange(location, std::min(length, match_length - location));
298 358
299 if (0 != (i->style & ACMatchClassification::MATCH)) { 359 if (0 != (i->style & ACMatchClassification::MATCH)) {
300 [attributedString addAttribute:NSFontAttributeName 360 [attributedString addAttribute:NSFontAttributeName
301 value:BoldFieldFont() 361 value:BoldFieldFont()
302 range:range]; 362 range:range];
303 } 363 }
304 364
305 if (0 != (i->style & ACMatchClassification::URL)) { 365 if (0 != (i->style & ACMatchClassification::URL)) {
306 [attributedString addAttribute:NSForegroundColorAttributeName 366 [attributedString addAttribute:NSForegroundColorAttributeName
307 value:URLTextColor() 367 value:URLTextColor(is_dark_theme)
308 range:range]; 368 range:range];
309 } else if (0 != (i->style & ACMatchClassification::DIM)) { 369 } else if (0 != (i->style & ACMatchClassification::DIM)) {
310 [attributedString addAttribute:NSForegroundColorAttributeName 370 [attributedString addAttribute:NSForegroundColorAttributeName
311 value:DimTextColor() 371 value:DimTextColor(is_dark_theme)
312 range:range]; 372 range:range];
313 } 373 }
314 } 374 }
315 375
316 return attributedString; 376 return attributedString;
317 } 377 }
318 378
319 } // namespace 379 } // namespace
320 380
321 @interface OmniboxPopupCell () 381 @interface OmniboxPopupCell ()
322 - (CGFloat)drawMatchPart:(NSAttributedString*)attributedString 382 - (CGFloat)drawMatchPart:(NSAttributedString*)attributedString
323 withFrame:(NSRect)cellFrame 383 withFrame:(NSRect)cellFrame
324 origin:(NSPoint)origin 384 origin:(NSPoint)origin
325 withMaxWidth:(int)maxWidth; 385 withMaxWidth:(int)maxWidth
386 forDarkTheme:(BOOL)isDarkTheme;
326 - (CGFloat)drawMatchPrefixWithFrame:(NSRect)cellFrame 387 - (CGFloat)drawMatchPrefixWithFrame:(NSRect)cellFrame
327 tableView:(OmniboxPopupMatrix*)tableView 388 tableView:(OmniboxPopupMatrix*)tableView
328 withContentsMaxWidth:(int*)contentsMaxWidth; 389 withContentsMaxWidth:(int*)contentsMaxWidth
390 forDarkTheme:(BOOL)isDarkTheme;
329 - (void)drawMatchWithFrame:(NSRect)cellFrame inView:(NSView*)controlView; 391 - (void)drawMatchWithFrame:(NSRect)cellFrame inView:(NSView*)controlView;
330 @end 392 @end
331 393
332 @implementation OmniboxPopupCellData 394 @implementation OmniboxPopupCellData
333 395
334 @synthesize contents = contents_; 396 @synthesize contents = contents_;
335 @synthesize description = description_; 397 @synthesize description = description_;
336 @synthesize prefix = prefix_; 398 @synthesize prefix = prefix_;
337 @synthesize image = image_; 399 @synthesize image = image_;
400 @synthesize incognitoImage = incognitoImage_;
338 @synthesize answerImage = answerImage_; 401 @synthesize answerImage = answerImage_;
339 @synthesize contentsOffset = contentsOffset_; 402 @synthesize contentsOffset = contentsOffset_;
340 @synthesize isContentsRTL = isContentsRTL_; 403 @synthesize isContentsRTL = isContentsRTL_;
341 @synthesize isAnswer = isAnswer_; 404 @synthesize isAnswer = isAnswer_;
342 @synthesize matchType = matchType_; 405 @synthesize matchType = matchType_;
343 406
344 - (instancetype)initWithMatch:(const AutocompleteMatch&)match 407 - (instancetype)initWithMatch:(const AutocompleteMatch&)match
345 contentsOffset:(CGFloat)contentsOffset 408 contentsOffset:(CGFloat)contentsOffset
346 image:(NSImage*)image 409 image:(NSImage*)image
347 answerImage:(NSImage*)answerImage { 410 answerImage:(NSImage*)answerImage
411 forDarkTheme:(BOOL)isDarkTheme {
348 if ((self = [super init])) { 412 if ((self = [super init])) {
349 image_ = [image retain]; 413 image_ = [image retain];
350 answerImage_ = [answerImage retain]; 414 answerImage_ = [answerImage retain];
351 contentsOffset_ = contentsOffset; 415 contentsOffset_ = contentsOffset;
352 416
353 isContentsRTL_ = 417 isContentsRTL_ =
354 (base::i18n::RIGHT_TO_LEFT == 418 (base::i18n::RIGHT_TO_LEFT ==
355 base::i18n::GetFirstStrongCharacterDirection(match.contents)); 419 base::i18n::GetFirstStrongCharacterDirection(match.contents));
356 matchType_ = match.type; 420 matchType_ = match.type;
357 421
358 // Prefix may not have any characters with strong directionality, and may 422 // Prefix may not have any characters with strong directionality, and may
359 // take the UI directionality. But prefix needs to appear in continuation 423 // take the UI directionality. But prefix needs to appear in continuation
360 // of the contents so we force the directionality. 424 // of the contents so we force the directionality.
361 NSTextAlignment textAlignment = 425 NSTextAlignment textAlignment =
362 isContentsRTL_ ? NSRightTextAlignment : NSLeftTextAlignment; 426 isContentsRTL_ ? NSRightTextAlignment : NSLeftTextAlignment;
363 prefix_ = 427 prefix_ =
364 [CreateAttributedString(base::UTF8ToUTF16(match.GetAdditionalInfo( 428 [CreateAttributedString(base::UTF8ToUTF16(match.GetAdditionalInfo(
365 kACMatchPropertyContentsPrefix)), 429 kACMatchPropertyContentsPrefix)),
366 ContentTextColor(), textAlignment) retain]; 430 ContentTextColor(isDarkTheme),
431 textAlignment) retain];
367 432
368 isAnswer_ = !!match.answer; 433 isAnswer_ = !!match.answer;
369 if (isAnswer_) { 434 if (isAnswer_) {
370 contents_ = [CreateAnswerLine(match.answer->first_line()) retain]; 435 contents_ =
371 description_ = [CreateAnswerLine(match.answer->second_line()) retain]; 436 [CreateAnswerLine(match.answer->first_line(), isDarkTheme) retain];
437 description_ =
438 [CreateAnswerLine(match.answer->second_line(), isDarkTheme) retain];
372 } else { 439 } else {
373 contents_ = [CreateClassifiedAttributedString( 440 contents_ =
374 match.contents, ContentTextColor(), match.contents_class) retain]; 441 [CreateClassifiedAttributedString(match.contents,
442 ContentTextColor(isDarkTheme),
443 match.contents_class,
444 isDarkTheme) retain];
375 if (!match.description.empty()) { 445 if (!match.description.empty()) {
376 description_ = [CreateClassifiedAttributedString( 446 description_ =
377 match.description, DimTextColor(), match.description_class) retain]; 447 [CreateClassifiedAttributedString(match.description,
448 DimTextColor(isDarkTheme),
449 match.description_class,
450 isDarkTheme) retain];
378 } 451 }
379 } 452 }
380 } 453 }
381 return self; 454 return self;
382 } 455 }
383 456
457 - (void)dealloc {
458 [incognitoImage_ release];
459 [super dealloc];
460 }
461
384 - (instancetype)copyWithZone:(NSZone*)zone { 462 - (instancetype)copyWithZone:(NSZone*)zone {
385 return [self retain]; 463 return [self retain];
386 } 464 }
387 465
388 - (CGFloat)getMatchContentsWidth { 466 - (CGFloat)getMatchContentsWidth {
389 return [contents_ size].width; 467 return [contents_ size].width;
390 } 468 }
391 469
392 @end 470 @end
393 471
394 @implementation OmniboxPopupCell 472 @implementation OmniboxPopupCell
395 473
396 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { 474 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
475 OmniboxPopupMatrix* matrix =
476 base::mac::ObjCCastStrict<OmniboxPopupMatrix>(controlView);
477 BOOL isDarkTheme = [matrix hasDarkTheme];
478
397 if ([self state] == NSOnState || [self isHighlighted]) { 479 if ([self state] == NSOnState || [self isHighlighted]) {
398 if ([self state] == NSOnState) 480 if ([self state] == NSOnState) {
399 [SelectedBackgroundColor() set]; 481 [SelectedBackgroundColor(isDarkTheme) set];
400 else 482 } else {
401 [HoveredBackgroundColor() set]; 483 [HoveredBackgroundColor(isDarkTheme) set];
402 NSBezierPath* path = 484 }
403 [NSBezierPath bezierPathWithRoundedRect:cellFrame 485 if (ui::MaterialDesignController::IsModeMaterial()) {
404 xRadius:kCellRoundingRadius 486 NSRectFillUsingOperation(cellFrame, NSCompositeSourceOver);
405 yRadius:kCellRoundingRadius]; 487 } else {
406 [path fill]; 488 NSBezierPath* path =
489 [NSBezierPath bezierPathWithRoundedRect:cellFrame
490 xRadius:kCellRoundingRadius
491 yRadius:kCellRoundingRadius];
492 [path fill];
493 }
407 } 494 }
408 495
409 [self drawMatchWithFrame:cellFrame inView:controlView]; 496 [self drawMatchWithFrame:cellFrame inView:controlView];
410 } 497 }
411 498
412 - (void)drawMatchWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { 499 - (void)drawMatchWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
413 OmniboxPopupCellData* cellData = 500 OmniboxPopupCellData* cellData =
414 base::mac::ObjCCastStrict<OmniboxPopupCellData>([self objectValue]); 501 base::mac::ObjCCastStrict<OmniboxPopupCellData>([self objectValue]);
415 OmniboxPopupMatrix* tableView = 502 OmniboxPopupMatrix* tableView =
416 base::mac::ObjCCastStrict<OmniboxPopupMatrix>(controlView); 503 base::mac::ObjCCastStrict<OmniboxPopupMatrix>(controlView);
417 CGFloat remainingWidth = GetContentAreaWidth(cellFrame); 504 CGFloat remainingWidth =
505 GetContentAreaWidth(cellFrame) - [tableView contentLeftPadding];
418 CGFloat contentsWidth = [cellData getMatchContentsWidth]; 506 CGFloat contentsWidth = [cellData getMatchContentsWidth];
419 CGFloat separatorWidth = [[tableView separator] size].width; 507 CGFloat separatorWidth = [[tableView separator] size].width;
420 CGFloat descriptionWidth = 508 CGFloat descriptionWidth =
421 [cellData description] ? [[cellData description] size].width : 0; 509 [cellData description] ? [[cellData description] size].width : 0;
422 int contentsMaxWidth, descriptionMaxWidth; 510 int contentsMaxWidth, descriptionMaxWidth;
423 OmniboxPopupModel::ComputeMatchMaxWidths( 511 OmniboxPopupModel::ComputeMatchMaxWidths(
424 ceilf(contentsWidth), ceilf(separatorWidth), ceilf(descriptionWidth), 512 ceilf(contentsWidth), ceilf(separatorWidth), ceilf(descriptionWidth),
425 ceilf(remainingWidth), 513 ceilf(remainingWidth),
426 [cellData isAnswer], 514 [cellData isAnswer],
427 !AutocompleteMatch::IsSearchType([cellData matchType]), 515 !AutocompleteMatch::IsSearchType([cellData matchType]),
428 &contentsMaxWidth, 516 &contentsMaxWidth,
429 &descriptionMaxWidth); 517 &descriptionMaxWidth);
430 518
519 NSWindow* parentWindow = [[controlView window] parentWindow];
520 BOOL isDarkTheme = [parentWindow hasDarkTheme];
431 NSRect imageRect = cellFrame; 521 NSRect imageRect = cellFrame;
432 imageRect.size = [[cellData image] size]; 522 NSImage* theImage =
433 imageRect.origin.x += kImageXOffset; 523 isDarkTheme ? [cellData incognitoImage] : [cellData image];
434 imageRect.origin.y += kPaddingOffset; 524 imageRect.size = [theImage size];
435 [[cellData image] drawInRect:FlipIfRTL(imageRect, cellFrame) 525 imageRect.origin.x += kImageXOffset + [tableView contentLeftPadding];
436 fromRect:NSZeroRect 526 imageRect.origin.y += VerticalImagePadding();
437 operation:NSCompositeSourceOver 527 [theImage drawInRect:FlipIfRTL(imageRect, cellFrame)
438 fraction:1.0 528 fromRect:NSZeroRect
439 respectFlipped:YES 529 operation:NSCompositeSourceOver
440 hints:nil]; 530 fraction:1.0
531 respectFlipped:YES
532 hints:nil];
441 533
442 NSPoint origin = NSMakePoint(kTextStartOffset, kPaddingOffset); 534 NSPoint origin = NSMakePoint(
535 TextStartOffset() + [tableView contentLeftPadding], kVerticalTextPadding);
443 if ([cellData matchType] == AutocompleteMatchType::SEARCH_SUGGEST_TAIL) { 536 if ([cellData matchType] == AutocompleteMatchType::SEARCH_SUGGEST_TAIL) {
444 // Infinite suggestions are rendered with a prefix (usually ellipsis), which 537 // Infinite suggestions are rendered with a prefix (usually ellipsis), which
445 // appear vertically stacked. 538 // appear vertically stacked.
446 origin.x += [self drawMatchPrefixWithFrame:cellFrame 539 origin.x += [self drawMatchPrefixWithFrame:cellFrame
447 tableView:tableView 540 tableView:tableView
448 withContentsMaxWidth:&contentsMaxWidth]; 541 withContentsMaxWidth:&contentsMaxWidth
542 forDarkTheme:isDarkTheme];
449 } 543 }
450 origin.x += [self drawMatchPart:[cellData contents] 544 origin.x += [self drawMatchPart:[cellData contents]
451 withFrame:cellFrame 545 withFrame:cellFrame
452 origin:origin 546 origin:origin
453 withMaxWidth:contentsMaxWidth]; 547 withMaxWidth:contentsMaxWidth
548 forDarkTheme:isDarkTheme];
454 549
455 if (descriptionMaxWidth > 0) { 550 if (descriptionMaxWidth > 0) {
456 if ([cellData isAnswer]) { 551 if ([cellData isAnswer]) {
457 origin = 552 origin = NSMakePoint(TextStartOffset() + [tableView contentLeftPadding],
458 NSMakePoint(kTextStartOffset, kContentLineHeight - kPaddingOffset); 553 kContentLineHeight - kVerticalTextPadding);
459 CGFloat imageSize = [tableView answerLineHeight]; 554 CGFloat imageSize = [tableView answerLineHeight];
460 NSRect imageRect = 555 NSRect imageRect =
461 NSMakeRect(NSMinX(cellFrame) + origin.x, NSMinY(cellFrame) + origin.y, 556 NSMakeRect(NSMinX(cellFrame) + origin.x, NSMinY(cellFrame) + origin.y,
462 imageSize, imageSize); 557 imageSize, imageSize);
463 [[cellData answerImage] drawInRect:FlipIfRTL(imageRect, cellFrame) 558 [[cellData answerImage] drawInRect:FlipIfRTL(imageRect, cellFrame)
464 fromRect:NSZeroRect 559 fromRect:NSZeroRect
465 operation:NSCompositeSourceOver 560 operation:NSCompositeSourceOver
466 fraction:1.0 561 fraction:1.0
467 respectFlipped:YES 562 respectFlipped:YES
468 hints:nil]; 563 hints:nil];
469 if ([cellData answerImage]) 564 if ([cellData answerImage]) {
470 origin.x += imageSize + kPaddingOffset; 565 origin.x += imageSize + VerticalImagePadding();
566
567 // Have to nudge the baseline down 1pt in Material Design for the text
568 // that follows, so that it's the same as the bottom of the image.
569 if (ui::MaterialDesignController::IsModeMaterial()) {
570 origin.y += 1;
571 }
572 }
471 } else { 573 } else {
472 origin.x += [self drawMatchPart:[tableView separator] 574 origin.x += [self drawMatchPart:[tableView separator]
473 withFrame:cellFrame 575 withFrame:cellFrame
474 origin:origin 576 origin:origin
475 withMaxWidth:separatorWidth]; 577 withMaxWidth:separatorWidth
578 forDarkTheme:isDarkTheme];
476 } 579 }
477 origin.x += [self drawMatchPart:[cellData description] 580 origin.x += [self drawMatchPart:[cellData description]
478 withFrame:cellFrame 581 withFrame:cellFrame
479 origin:origin 582 origin:origin
480 withMaxWidth:descriptionMaxWidth]; 583 withMaxWidth:descriptionMaxWidth
584 forDarkTheme:isDarkTheme];
481 } 585 }
482 } 586 }
483 587
484 - (CGFloat)drawMatchPrefixWithFrame:(NSRect)cellFrame 588 - (CGFloat)drawMatchPrefixWithFrame:(NSRect)cellFrame
485 tableView:(OmniboxPopupMatrix*)tableView 589 tableView:(OmniboxPopupMatrix*)tableView
486 withContentsMaxWidth:(int*)contentsMaxWidth { 590 withContentsMaxWidth:(int*)contentsMaxWidth
591 forDarkTheme:(BOOL)isDarkTheme {
487 OmniboxPopupCellData* cellData = 592 OmniboxPopupCellData* cellData =
488 base::mac::ObjCCastStrict<OmniboxPopupCellData>([self objectValue]); 593 base::mac::ObjCCastStrict<OmniboxPopupCellData>([self objectValue]);
489 CGFloat offset = 0.0f; 594 CGFloat offset = 0.0f;
490 CGFloat remainingWidth = GetContentAreaWidth(cellFrame); 595 CGFloat remainingWidth =
596 GetContentAreaWidth(cellFrame) - [tableView contentLeftPadding];
491 CGFloat prefixWidth = [[cellData prefix] size].width; 597 CGFloat prefixWidth = [[cellData prefix] size].width;
492 598
493 CGFloat prefixOffset = 0.0f; 599 CGFloat prefixOffset = 0.0f;
494 if (base::i18n::IsRTL() != [cellData isContentsRTL]) { 600 if (base::i18n::IsRTL() != [cellData isContentsRTL]) {
495 // The contents is rendered between the contents offset extending towards 601 // The contents is rendered between the contents offset extending towards
496 // the start edge, while prefix is rendered in opposite direction. Ideally 602 // the start edge, while prefix is rendered in opposite direction. Ideally
497 // the prefix should be rendered at |contentsOffset_|. If that is not 603 // the prefix should be rendered at |contentsOffset_|. If that is not
498 // sufficient to render the widest suggestion, we increase it to 604 // sufficient to render the widest suggestion, we increase it to
499 // |maxMatchContentsWidth|. If |remainingWidth| is not sufficient to 605 // |maxMatchContentsWidth|. If |remainingWidth| is not sufficient to
500 // accommodate that, we reduce the offset so that the prefix gets rendered. 606 // accommodate that, we reduce the offset so that the prefix gets rendered.
501 prefixOffset = std::min( 607 prefixOffset = std::min(
502 remainingWidth - prefixWidth, 608 remainingWidth - prefixWidth,
503 std::max([cellData contentsOffset], [tableView maxMatchContentsWidth])); 609 std::max([cellData contentsOffset], [tableView maxMatchContentsWidth]));
504 offset = std::max<CGFloat>(0.0, prefixOffset - *contentsMaxWidth); 610 offset = std::max<CGFloat>(0.0, prefixOffset - *contentsMaxWidth);
505 } else { // The direction of contents is same as UI direction. 611 } else { // The direction of contents is same as UI direction.
506 // Ideally the offset should be |contentsOffset_|. If the max total width 612 // Ideally the offset should be |contentsOffset_|. If the max total width
507 // (|prefixWidth| + |maxMatchContentsWidth|) from offset will exceed the 613 // (|prefixWidth| + |maxMatchContentsWidth|) from offset will exceed the
508 // |remainingWidth|, then we shift the offset to the left , so that all 614 // |remainingWidth|, then we shift the offset to the left , so that all
509 // postfix suggestions are visible. 615 // postfix suggestions are visible.
510 // We have to render the prefix, so offset has to be at least |prefixWidth|. 616 // We have to render the prefix, so offset has to be at least |prefixWidth|.
511 offset = 617 offset =
512 std::max(prefixWidth, 618 std::max(prefixWidth,
513 std::min(remainingWidth - [tableView maxMatchContentsWidth], 619 std::min(remainingWidth - [tableView maxMatchContentsWidth],
514 [cellData contentsOffset])); 620 [cellData contentsOffset]));
515 prefixOffset = offset - prefixWidth; 621 prefixOffset = offset - prefixWidth;
516 } 622 }
517 *contentsMaxWidth = std::min((int)ceilf(remainingWidth - prefixWidth), 623 *contentsMaxWidth = std::min((int)ceilf(remainingWidth - prefixWidth),
518 *contentsMaxWidth); 624 *contentsMaxWidth);
625 NSPoint origin = NSMakePoint(
626 prefixOffset + TextStartOffset() + [tableView contentLeftPadding], 0);
519 [self drawMatchPart:[cellData prefix] 627 [self drawMatchPart:[cellData prefix]
520 withFrame:cellFrame 628 withFrame:cellFrame
521 origin:NSMakePoint(prefixOffset + kTextStartOffset, 0) 629 origin:origin
522 withMaxWidth:prefixWidth]; 630 withMaxWidth:prefixWidth
631 forDarkTheme:isDarkTheme];
523 return offset; 632 return offset;
524 } 633 }
525 634
526 - (CGFloat)drawMatchPart:(NSAttributedString*)attributedString 635 - (CGFloat)drawMatchPart:(NSAttributedString*)attributedString
527 withFrame:(NSRect)cellFrame 636 withFrame:(NSRect)cellFrame
528 origin:(NSPoint)origin 637 origin:(NSPoint)origin
529 withMaxWidth:(int)maxWidth { 638 withMaxWidth:(int)maxWidth
639 forDarkTheme:(BOOL)isDarkTheme {
530 NSRect renderRect = NSIntersectionRect( 640 NSRect renderRect = NSIntersectionRect(
531 cellFrame, NSOffsetRect(cellFrame, origin.x, origin.y)); 641 cellFrame, NSOffsetRect(cellFrame, origin.x, origin.y));
532 renderRect.size.width = 642 renderRect.size.width =
533 std::min(NSWidth(renderRect), static_cast<CGFloat>(maxWidth)); 643 std::min(NSWidth(renderRect), static_cast<CGFloat>(maxWidth));
534 if (!NSIsEmptyRect(renderRect)) 644 if (!NSIsEmptyRect(renderRect))
535 [attributedString drawInRect:FlipIfRTL(renderRect, cellFrame)]; 645 [attributedString drawInRect:FlipIfRTL(renderRect, cellFrame)];
536 return NSWidth(renderRect); 646 return NSWidth(renderRect);
537 } 647 }
538 648
539 + (CGFloat)computeContentsOffset:(const AutocompleteMatch&)match { 649 + (CGFloat)computeContentsOffset:(const AutocompleteMatch&)match {
540 const base::string16& inputText = base::UTF8ToUTF16( 650 const base::string16& inputText = base::UTF8ToUTF16(
541 match.GetAdditionalInfo(kACMatchPropertyInputText)); 651 match.GetAdditionalInfo(kACMatchPropertyInputText));
542 int contentsStartIndex = 0; 652 int contentsStartIndex = 0;
543 base::StringToInt( 653 base::StringToInt(
544 match.GetAdditionalInfo(kACMatchPropertyContentsStartIndex), 654 match.GetAdditionalInfo(kACMatchPropertyContentsStartIndex),
545 &contentsStartIndex); 655 &contentsStartIndex);
546 // Ignore invalid state. 656 // Ignore invalid state.
547 if (!base::StartsWith(match.fill_into_edit, inputText, 657 if (!base::StartsWith(match.fill_into_edit, inputText,
548 base::CompareCase::SENSITIVE) || 658 base::CompareCase::SENSITIVE) ||
549 !base::EndsWith(match.fill_into_edit, match.contents, 659 !base::EndsWith(match.fill_into_edit, match.contents,
550 base::CompareCase::SENSITIVE) || 660 base::CompareCase::SENSITIVE) ||
551 ((size_t)contentsStartIndex >= inputText.length())) { 661 ((size_t)contentsStartIndex >= inputText.length())) {
552 return 0; 662 return 0;
553 } 663 }
554 bool isContentsRTL = (base::i18n::RIGHT_TO_LEFT == 664 bool isContentsRTL = (base::i18n::RIGHT_TO_LEFT ==
555 base::i18n::GetFirstStrongCharacterDirection(match.contents)); 665 base::i18n::GetFirstStrongCharacterDirection(match.contents));
556 666
557 // Color does not matter. 667 // Color does not matter.
558 NSAttributedString* attributedString = 668 NSAttributedString* attributedString =
559 CreateAttributedString(inputText, DimTextColor()); 669 CreateAttributedString(inputText, DimTextColor(false));
560 base::scoped_nsobject<NSTextStorage> textStorage( 670 base::scoped_nsobject<NSTextStorage> textStorage(
561 [[NSTextStorage alloc] initWithAttributedString:attributedString]); 671 [[NSTextStorage alloc] initWithAttributedString:attributedString]);
562 base::scoped_nsobject<NSLayoutManager> layoutManager( 672 base::scoped_nsobject<NSLayoutManager> layoutManager(
563 [[NSLayoutManager alloc] init]); 673 [[NSLayoutManager alloc] init]);
564 base::scoped_nsobject<NSTextContainer> textContainer( 674 base::scoped_nsobject<NSTextContainer> textContainer(
565 [[NSTextContainer alloc] init]); 675 [[NSTextContainer alloc] init]);
566 [layoutManager addTextContainer:textContainer]; 676 [layoutManager addTextContainer:textContainer];
567 [textStorage addLayoutManager:layoutManager]; 677 [textStorage addLayoutManager:layoutManager];
568 678
569 NSUInteger charIndex = static_cast<NSUInteger>(contentsStartIndex); 679 NSUInteger charIndex = static_cast<NSUInteger>(contentsStartIndex);
(...skipping 27 matching lines...) Expand all
597 glyphWidth = std::min(glyphWidth, offset - glyphOffset); 707 glyphWidth = std::min(glyphWidth, offset - glyphOffset);
598 } 708 }
599 glyphOffset -= minOffset; 709 glyphOffset -= minOffset;
600 if (glyphWidth == 0) 710 if (glyphWidth == 0)
601 glyphWidth = inputWidth - glyphOffset; 711 glyphWidth = inputWidth - glyphOffset;
602 if (isContentsRTL) 712 if (isContentsRTL)
603 glyphOffset += glyphWidth; 713 glyphOffset += glyphWidth;
604 return base::i18n::IsRTL() ? (inputWidth - glyphOffset) : glyphOffset; 714 return base::i18n::IsRTL() ? (inputWidth - glyphOffset) : glyphOffset;
605 } 715 }
606 716
607 + (NSAttributedString*)createSeparatorString { 717 + (NSAttributedString*)createSeparatorStringForDarkTheme:(BOOL)isDarkTheme {
608 base::string16 raw_separator = 718 base::string16 raw_separator =
609 l10n_util::GetStringUTF16(IDS_AUTOCOMPLETE_MATCH_DESCRIPTION_SEPARATOR); 719 l10n_util::GetStringUTF16(IDS_AUTOCOMPLETE_MATCH_DESCRIPTION_SEPARATOR);
610 return CreateAttributedString(raw_separator, DimTextColor()); 720 return CreateAttributedString(raw_separator, DimTextColor(isDarkTheme));
611 } 721 }
612 722
613 @end 723 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698