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

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, 5 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/browser/ui/omnibox/omnibox_popup_non_view.h" 19 #include "chrome/browser/ui/omnibox/omnibox_popup_non_view.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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 DCHECK_GT(matrix_width, 0.0); 110 DCHECK_GT(matrix_width, 0.0);
120 111
121 // Load the results into the popup's matrix. 112 // Load the results into the popup's matrix.
122 const size_t rows = GetResult().size(); 113 const size_t rows = GetResult().size();
123 DCHECK_GT(rows, 0U); 114 DCHECK_GT(rows, 0U);
124 [matrix_ renewRows:rows columns:1]; 115 [matrix_ renewRows:rows columns:1];
125 for (size_t ii = 0; ii < rows; ++ii) { 116 for (size_t ii = 0; ii < rows; ++ii) {
126 OmniboxPopupCell* cell = [matrix_ cellAtRow:ii column:0]; 117 OmniboxPopupCell* cell = [matrix_ cellAtRow:ii column:0];
127 const AutocompleteMatch& match = GetResult().match_at(ii); 118 const AutocompleteMatch& match = GetResult().match_at(ii);
128 [cell setImage:ImageForMatch(match)]; 119 [cell setImage:ImageForMatch(match)];
129 [cell setAttributedTitle:MatchText(match, result_font, matrix_width)]; 120 [cell setContentText:DecorateMatchedString(match.contents,
121 match.contents_class,
122 ContentTextColor(),
123 DimContentTextColor(),
124 result_font)];
125 if (match.description.empty()) {
126 [cell setDescriptionText:nil];
127 } else {
128 [cell setDescriptionText:DecorateMatchedString(match.description,
129 match.description_class,
130 DimContentTextColor(),
131 DimContentTextColor(),
132 result_font)];
133 }
130 } 134 }
131 135
132 // Set the cell size to fit a line of text in the cell's font. All 136 // Set the cell size to fit a line of text in the cell's font. All
133 // cells should use the same font and each should layout in one 137 // cells should use the same font and each should layout in one
134 // line, so they should all be about the same height. 138 // line, so they should all be about the same height.
135 const NSSize cell_size = [[matrix_ cellAtRow:0 column:0] cellSize]; 139 const NSSize cell_size = [[matrix_ cellAtRow:0 column:0] cellSize];
136 DCHECK_GT(cell_size.height, 0.0); 140 DCHECK_GT(cell_size.height, 0.0);
137 const CGFloat cell_height = cell_size.height + kCellHeightAdjust; 141 const CGFloat cell_height = cell_size.height + kCellHeightAdjust;
138 [matrix_ setCellSize:NSMakeSize(matrix_width, cell_height)]; 142 [matrix_ setCellSize:NSMakeSize(matrix_width, cell_height)];
139 143
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 size_t row) { 175 size_t row) {
172 OpenURLForRow(row, 176 OpenURLForRow(row,
173 ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent])); 177 ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent]));
174 } 178 }
175 179
176 void OmniboxPopupViewMac::OnMatrixRowMiddleClicked(OmniboxPopupMatrix* matrix, 180 void OmniboxPopupViewMac::OnMatrixRowMiddleClicked(OmniboxPopupMatrix* matrix,
177 size_t row) { 181 size_t row) {
178 OpenURLForRow(row, NEW_BACKGROUND_TAB); 182 OpenURLForRow(row, NEW_BACKGROUND_TAB);
179 } 183 }
180 184
181 // Return the text to show for the match, based on the match's
182 // contents and description. Result will be in |font|, with the
183 // boldfaced version used for matches.
184 NSAttributedString* OmniboxPopupViewMac::MatchText(
185 const AutocompleteMatch& match,
186 gfx::Font& font,
187 float cell_width) {
188 NSMutableAttributedString *as =
189 DecorateMatchedString(match.contents,
190 match.contents_class,
191 ContentTextColor(),
192 DimContentTextColor(),
193 font);
194
195 // If there is a description, append it, separated from the contents
196 // with an en dash, and decorated with a distinct color.
197 if (!match.description.empty()) {
198 // Make sure the current string fits w/in kMaxContentsFraction of
199 // the cell to make sure the description will be at least
200 // partially visible.
201 // TODO(shess): Consider revising our NSCell subclass to have two
202 // bits and just draw them right, rather than truncating here.
203 const float text_width = cell_width - kTextXOffset;
204 as = ElideString(as, match.contents, font,
205 text_width * kMaxContentsFraction);
206
207 NSDictionary* attributes = @{
208 NSFontAttributeName : font.GetNativeFont(),
209 NSForegroundColorAttributeName : ContentTextColor()
210 };
211 NSString* raw_en_dash = @" \u2013 ";
212 NSAttributedString* en_dash =
213 [[[NSAttributedString alloc] initWithString:raw_en_dash
214 attributes:attributes] autorelease];
215
216 // In Windows, a boolean force_dim is passed as true for the
217 // description. Here, we pass the dim text color for both normal and dim,
218 // to accomplish the same thing.
219 NSAttributedString* description =
220 DecorateMatchedString(match.description, match.description_class,
221 DimContentTextColor(),
222 DimContentTextColor(),
223 font);
224
225 [as appendAttributedString:en_dash];
226 [as appendAttributedString:description];
227 }
228
229 NSMutableParagraphStyle* style =
230 [[[NSMutableParagraphStyle alloc] init] autorelease];
231 [style setLineBreakMode:NSLineBreakByTruncatingTail];
232 [style setTighteningFactorForTruncation:0.0];
233 [as addAttribute:NSParagraphStyleAttributeName value:style
234 range:NSMakeRange(0, [as length])];
235
236 return as;
237 }
238
239 // static 185 // static
240 NSMutableAttributedString* OmniboxPopupViewMac::DecorateMatchedString( 186 NSMutableAttributedString* OmniboxPopupViewMac::DecorateMatchedString(
241 const string16& match_string, 187 const string16& match_string,
242 const AutocompleteMatch::ACMatchClassifications& classifications, 188 const AutocompleteMatch::ACMatchClassifications& classifications,
243 NSColor* text_color, 189 NSColor* text_color,
244 NSColor* dim_text_color, 190 NSColor* dim_text_color,
245 gfx::Font& font) { 191 gfx::Font& font) {
246 // Cache for on-demand computation of the bold version of |font|. 192 // Cache for on-demand computation of the bold version of |font|.
247 NSFont* bold_font = nil; 193 NSFont* bold_font = nil;
248 194
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 if (0 != (i->style & ACMatchClassification::DIM)) { 240 if (0 != (i->style & ACMatchClassification::DIM)) {
295 [as addAttribute:NSForegroundColorAttributeName 241 [as addAttribute:NSForegroundColorAttributeName
296 value:dim_text_color 242 value:dim_text_color
297 range:range]; 243 range:range];
298 } 244 }
299 } 245 }
300 246
301 return as; 247 return as;
302 } 248 }
303 249
304 NSMutableAttributedString* OmniboxPopupViewMac::ElideString(
305 NSMutableAttributedString* a_string,
306 const string16& original_string,
307 const gfx::Font& font,
308 const float width) {
309 // If it already fits, nothing to be done.
310 if ([a_string size].width <= width) {
311 return a_string;
312 }
313
314 // If ElideText() decides to do nothing, nothing to be done.
315 const string16 elided =
316 ui::ElideText(original_string, font, width, ui::ELIDE_AT_END);
317 if (0 == elided.compare(original_string)) {
318 return a_string;
319 }
320
321 // If everything was elided away, clear the string.
322 if (elided.empty()) {
323 [a_string deleteCharactersInRange:NSMakeRange(0, [a_string length])];
324 return a_string;
325 }
326
327 // The ellipses should be the last character, and everything before
328 // that should match the original string.
329 const size_t i(elided.length() - 1);
330 DCHECK_NE(0, elided.compare(0, i, original_string));
331
332 // Replace the end of |aString| with the ellipses from |elided|.
333 NSString* s = base::SysUTF16ToNSString(elided.substr(i));
334 [a_string replaceCharactersInRange:NSMakeRange(i, [a_string length] - i)
335 withString:s];
336
337 return a_string;
338 }
339
340 const AutocompleteResult& OmniboxPopupViewMac::GetResult() const { 250 const AutocompleteResult& OmniboxPopupViewMac::GetResult() const {
341 return model_->result(); 251 return model_->result();
342 } 252 }
343 253
344 void OmniboxPopupViewMac::CreatePopupIfNeeded() { 254 void OmniboxPopupViewMac::CreatePopupIfNeeded() {
345 if (!popup_) { 255 if (!popup_) {
346 popup_.reset( 256 popup_.reset(
347 [[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater 257 [[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater
348 styleMask:NSBorderlessWindowMask 258 styleMask:NSBorderlessWindowMask
349 backing:NSBackingStoreBuffered 259 backing:NSBackingStoreBuffered
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 void OmniboxPopupViewMac::OpenURLForRow(size_t row, 383 void OmniboxPopupViewMac::OpenURLForRow(size_t row,
474 WindowOpenDisposition disposition) { 384 WindowOpenDisposition disposition) {
475 DCHECK_GE(row, 0u); 385 DCHECK_GE(row, 0u);
476 386
477 // OpenMatch() may close the popup, which will clear the result set and, by 387 // OpenMatch() may close the popup, which will clear the result set and, by
478 // extension, |match| and its contents. So copy the relevant match out to 388 // extension, |match| and its contents. So copy the relevant match out to
479 // make sure it stays alive until the call completes. 389 // make sure it stays alive until the call completes.
480 AutocompleteMatch match = GetResult().match_at(row); 390 AutocompleteMatch match = GetResult().match_at(row);
481 omnibox_view_->OpenMatch(match, disposition, GURL(), row); 391 omnibox_view_->OpenMatch(match, disposition, GURL(), row);
482 } 392 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698