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

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

Issue 17774002: OmniboxPopupViewMac refactoring Part 3 (truncation) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 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 | Annotate | Revision Log
OLDNEW
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 #include "chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h" 5 #include "chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "base/strings/sys_string_conversions.h" 10 #include "base/strings/sys_string_conversions.h"
11 #include "chrome/browser/autocomplete/autocomplete_match.h" 11 #include "chrome/browser/autocomplete/autocomplete_match.h"
12 #include "chrome/browser/search/search.h" 12 #include "chrome/browser/search/search.h"
13 #include "chrome/browser/ui/cocoa/browser_window_controller.h" 13 #include "chrome/browser/ui/cocoa/browser_window_controller.h"
14 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h" 14 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h"
15 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view.h" 15 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view.h"
16 #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h" 16 #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
17 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h" 17 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
18 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h" 18 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
19 #include "chrome/common/autocomplete_match_type.h" 19 #include "chrome/common/autocomplete_match_type.h"
20 #include "grit/theme_resources.h" 20 #include "grit/theme_resources.h"
21 #include "skia/ext/skia_utils_mac.h" 21 #include "skia/ext/skia_utils_mac.h"
22 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h" 22 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
23 #import "ui/base/cocoa/cocoa_event_utils.h" 23 #import "ui/base/cocoa/cocoa_event_utils.h"
24 #import "ui/base/cocoa/flipped_view.h" 24 #import "ui/base/cocoa/flipped_view.h"
25 #include "ui/base/cocoa/window_size_constants.h" 25 #include "ui/base/cocoa/window_size_constants.h"
26 #include "ui/base/resource/resource_bundle.h" 26 #include "ui/base/resource/resource_bundle.h"
27 #include "ui/base/text/text_elider.h"
28 #include "ui/gfx/rect.h" 27 #include "ui/gfx/rect.h"
29 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
30 28
31 namespace { 29 namespace {
32 30
33 // How much to adjust the cell sizing up from the default determined 31 // How much to adjust the cell sizing up from the default determined
34 // by the font. 32 // by the font.
35 const CGFloat kCellHeightAdjust = 6.0; 33 const CGFloat kCellHeightAdjust = 6.0;
36 34
37 // Padding between matrix and the top and bottom of the popup window. 35 // Padding between matrix and the top and bottom of the popup window.
38 const CGFloat kPopupPaddingVertical = 5.0; 36 const CGFloat kPopupPaddingVertical = 5.0;
39 37
40 // How far to offset the text column from the left.
41 const CGFloat kTextXOffset = 28.0;
42
43 // Animation duration when animating the popup window smaller. 38 // Animation duration when animating the popup window smaller.
44 const NSTimeInterval kShrinkAnimationDuration = 0.1; 39 const NSTimeInterval kShrinkAnimationDuration = 0.1;
45 40
46 // Maximum fraction of the popup width that can be used to display match
47 // contents.
48 const CGFloat kMaxContentsFraction = 0.7;
49
50 // Background colors for different states of the popup elements. 41 // Background colors for different states of the popup elements.
51 NSColor* BackgroundColor() { 42 NSColor* BackgroundColor() {
52 return [NSColor controlBackgroundColor]; 43 return [NSColor controlBackgroundColor];
53 } 44 }
54 45
55 NSColor* ContentTextColor() { 46 NSColor* ContentTextColor() {
56 return [NSColor blackColor]; 47 return [NSColor blackColor];
57 } 48 }
58 NSColor* DimContentTextColor() { 49 NSColor* DimContentTextColor() {
59 return [NSColor darkGrayColor]; 50 return [NSColor darkGrayColor];
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 const CGFloat matrix_width = NSWidth([field_ bounds]); 111 const CGFloat matrix_width = NSWidth([field_ bounds]);
121 DCHECK_GT(matrix_width, 0.0); 112 DCHECK_GT(matrix_width, 0.0);
122 113
123 // Load the results into the popup's matrix. 114 // Load the results into the popup's matrix.
124 DCHECK_GT(rows, 0U); 115 DCHECK_GT(rows, 0U);
125 [matrix_ renewRows:rows columns:1]; 116 [matrix_ renewRows:rows columns:1];
126 for (size_t ii = 0; ii < rows; ++ii) { 117 for (size_t ii = 0; ii < rows; ++ii) {
127 OmniboxPopupCell* cell = [matrix_ cellAtRow:ii column:0]; 118 OmniboxPopupCell* cell = [matrix_ cellAtRow:ii column:0];
128 const AutocompleteMatch& match = GetResult().match_at(ii + start_match); 119 const AutocompleteMatch& match = GetResult().match_at(ii + start_match);
129 [cell setImage:ImageForMatch(match)]; 120 [cell setImage:ImageForMatch(match)];
130 [cell setAttributedTitle:MatchText(match, result_font, matrix_width)]; 121 [cell setContentText:DecorateMatchedString(match.contents,
122 match.contents_class,
123 ContentTextColor(),
124 DimContentTextColor(),
125 result_font)];
126 if (match.description.empty()) {
127 [cell setDescriptionText:nil];
128 } else {
129 [cell setDescriptionText:DecorateMatchedString(match.description,
130 match.description_class,
131 DimContentTextColor(),
132 DimContentTextColor(),
133 result_font)];
134 }
131 } 135 }
132 136
133 // Set the cell size to fit a line of text in the cell's font. All 137 // Set the cell size to fit a line of text in the cell's font. All
134 // cells should use the same font and each should layout in one 138 // cells should use the same font and each should layout in one
135 // line, so they should all be about the same height. 139 // line, so they should all be about the same height.
136 const NSSize cell_size = [[matrix_ cellAtRow:0 column:0] cellSize]; 140 const NSSize cell_size = [[matrix_ cellAtRow:0 column:0] cellSize];
137 DCHECK_GT(cell_size.height, 0.0); 141 DCHECK_GT(cell_size.height, 0.0);
138 const CGFloat cell_height = cell_size.height + kCellHeightAdjust; 142 const CGFloat cell_height = cell_size.height + kCellHeightAdjust;
139 [matrix_ setCellSize:NSMakeSize(matrix_width, cell_height)]; 143 [matrix_ setCellSize:NSMakeSize(matrix_width, cell_height)];
140 144
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 size_t row) { 182 size_t row) {
179 OpenURLForRow(row, 183 OpenURLForRow(row,
180 ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent])); 184 ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent]));
181 } 185 }
182 186
183 void OmniboxPopupViewMac::OnMatrixRowMiddleClicked(OmniboxPopupMatrix* matrix, 187 void OmniboxPopupViewMac::OnMatrixRowMiddleClicked(OmniboxPopupMatrix* matrix,
184 size_t row) { 188 size_t row) {
185 OpenURLForRow(row, NEW_BACKGROUND_TAB); 189 OpenURLForRow(row, NEW_BACKGROUND_TAB);
186 } 190 }
187 191
188 // Return the text to show for the match, based on the match's
189 // contents and description. Result will be in |font|, with the
190 // boldfaced version used for matches.
191 NSAttributedString* OmniboxPopupViewMac::MatchText(
192 const AutocompleteMatch& match,
193 gfx::Font& font,
194 float cell_width) {
195 NSMutableAttributedString *as =
196 DecorateMatchedString(match.contents,
197 match.contents_class,
198 ContentTextColor(),
199 DimContentTextColor(),
200 font);
201
202 // If there is a description, append it, separated from the contents
203 // with an en dash, and decorated with a distinct color.
204 if (!match.description.empty()) {
205 // Make sure the current string fits w/in kMaxContentsFraction of
206 // the cell to make sure the description will be at least
207 // partially visible.
208 // TODO(shess): Consider revising our NSCell subclass to have two
209 // bits and just draw them right, rather than truncating here.
210 const float text_width = cell_width - kTextXOffset;
211 as = ElideString(as, match.contents, font,
212 text_width * kMaxContentsFraction);
213
214 NSDictionary* attributes = @{
215 NSFontAttributeName : font.GetNativeFont(),
216 NSForegroundColorAttributeName : ContentTextColor()
217 };
218 NSString* raw_en_dash = @" \u2013 ";
219 NSAttributedString* en_dash =
220 [[[NSAttributedString alloc] initWithString:raw_en_dash
221 attributes:attributes] autorelease];
222
223 // In Windows, a boolean force_dim is passed as true for the
224 // description. Here, we pass the dim text color for both normal and dim,
225 // to accomplish the same thing.
226 NSAttributedString* description =
227 DecorateMatchedString(match.description, match.description_class,
228 DimContentTextColor(),
229 DimContentTextColor(),
230 font);
231
232 [as appendAttributedString:en_dash];
233 [as appendAttributedString:description];
234 }
235
236 NSMutableParagraphStyle* style =
237 [[[NSMutableParagraphStyle alloc] init] autorelease];
238 [style setLineBreakMode:NSLineBreakByTruncatingTail];
239 [style setTighteningFactorForTruncation:0.0];
240 [as addAttribute:NSParagraphStyleAttributeName value:style
241 range:NSMakeRange(0, [as length])];
242
243 return as;
244 }
245
246 // static 192 // static
247 NSMutableAttributedString* OmniboxPopupViewMac::DecorateMatchedString( 193 NSMutableAttributedString* OmniboxPopupViewMac::DecorateMatchedString(
248 const string16& match_string, 194 const string16& match_string,
249 const AutocompleteMatch::ACMatchClassifications& classifications, 195 const AutocompleteMatch::ACMatchClassifications& classifications,
250 NSColor* text_color, 196 NSColor* text_color,
251 NSColor* dim_text_color, 197 NSColor* dim_text_color,
252 gfx::Font& font) { 198 gfx::Font& font) {
253 // Cache for on-demand computation of the bold version of |font|. 199 // Cache for on-demand computation of the bold version of |font|.
254 NSFont* bold_font = nil; 200 NSFont* bold_font = nil;
255 201
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 if (0 != (i->style & ACMatchClassification::DIM)) { 247 if (0 != (i->style & ACMatchClassification::DIM)) {
302 [as addAttribute:NSForegroundColorAttributeName 248 [as addAttribute:NSForegroundColorAttributeName
303 value:dim_text_color 249 value:dim_text_color
304 range:range]; 250 range:range];
305 } 251 }
306 } 252 }
307 253
308 return as; 254 return as;
309 } 255 }
310 256
311 NSMutableAttributedString* OmniboxPopupViewMac::ElideString(
312 NSMutableAttributedString* a_string,
313 const string16& original_string,
314 const gfx::Font& font,
315 const float width) {
316 // If it already fits, nothing to be done.
317 if ([a_string size].width <= width) {
318 return a_string;
319 }
320
321 // If ElideText() decides to do nothing, nothing to be done.
322 const string16 elided =
323 ui::ElideText(original_string, font, width, ui::ELIDE_AT_END);
324 if (0 == elided.compare(original_string)) {
325 return a_string;
326 }
327
328 // If everything was elided away, clear the string.
329 if (elided.empty()) {
330 [a_string deleteCharactersInRange:NSMakeRange(0, [a_string length])];
331 return a_string;
332 }
333
334 // The ellipses should be the last character, and everything before
335 // that should match the original string.
336 const size_t i(elided.length() - 1);
337 DCHECK_NE(0, elided.compare(0, i, original_string));
338
339 // Replace the end of |aString| with the ellipses from |elided|.
340 NSString* s = base::SysUTF16ToNSString(elided.substr(i));
341 [a_string replaceCharactersInRange:NSMakeRange(i, [a_string length] - i)
342 withString:s];
343
344 return a_string;
345 }
346
347 const AutocompleteResult& OmniboxPopupViewMac::GetResult() const { 257 const AutocompleteResult& OmniboxPopupViewMac::GetResult() const {
348 return model_->result(); 258 return model_->result();
349 } 259 }
350 260
351 void OmniboxPopupViewMac::CreatePopupIfNeeded() { 261 void OmniboxPopupViewMac::CreatePopupIfNeeded() {
352 if (!popup_) { 262 if (!popup_) {
353 popup_.reset( 263 popup_.reset(
354 [[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater 264 [[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater
355 styleMask:NSBorderlessWindowMask 265 styleMask:NSBorderlessWindowMask
356 backing:NSBackingStoreBuffered 266 backing:NSBackingStoreBuffered
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 void OmniboxPopupViewMac::OpenURLForRow(size_t row, 404 void OmniboxPopupViewMac::OpenURLForRow(size_t row,
495 WindowOpenDisposition disposition) { 405 WindowOpenDisposition disposition) {
496 DCHECK_GE(row, 0u); 406 DCHECK_GE(row, 0u);
497 407
498 // OpenMatch() may close the popup, which will clear the result set and, by 408 // OpenMatch() may close the popup, which will clear the result set and, by
499 // extension, |match| and its contents. So copy the relevant match out to 409 // extension, |match| and its contents. So copy the relevant match out to
500 // make sure it stays alive until the call completes. 410 // make sure it stays alive until the call completes.
501 AutocompleteMatch match = GetResult().match_at(row); 411 AutocompleteMatch match = GetResult().match_at(row);
502 omnibox_view_->OpenMatch(match, disposition, GURL(), row); 412 omnibox_view_->OpenMatch(match, disposition, GURL(), row);
503 } 413 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698