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

Side by Side Diff: chrome/browser/cocoa/autocomplete_text_field_cell.mm

Issue 1566004: [Mac] Rearrange SSL status icon/label in omnibox. (Closed)
Patch Set: Rohit's points. Created 10 years, 8 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 (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/cocoa/autocomplete_text_field_cell.h" 5 #import "chrome/browser/cocoa/autocomplete_text_field_cell.h"
6 6
7 #include "app/resource_bundle.h" 7 #include "app/resource_bundle.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "gfx/font.h" 9 #include "gfx/font.h"
10 10
(...skipping 21 matching lines...) Expand all
32 // TODO(shess): The keyword hint image wants to sit on the baseline. 32 // TODO(shess): The keyword hint image wants to sit on the baseline.
33 // This moves it down so that there is approximately as much image 33 // This moves it down so that there is approximately as much image
34 // above the lowercase ascender as below the baseline. A better 34 // above the lowercase ascender as below the baseline. A better
35 // technique would be nice to have, though. 35 // technique would be nice to have, though.
36 const NSInteger kKeywordHintImageBaseline = -6; 36 const NSInteger kKeywordHintImageBaseline = -6;
37 37
38 // The amount of padding on either side reserved for drawing an icon. 38 // The amount of padding on either side reserved for drawing an icon.
39 const NSInteger kIconHorizontalPad = 3; 39 const NSInteger kIconHorizontalPad = 3;
40 40
41 // How far to shift bounding box of hint icon label down from top of field. 41 // How far to shift bounding box of hint icon label down from top of field.
42 const NSInteger kIconLabelYOffset = 5; 42 const NSInteger kIconLabelYOffset = 7;
43 43
44 // How far the editor insets itself, for purposes of determining if 44 // How far the editor insets itself, for purposes of determining if
45 // decorations need to be trimmed. 45 // decorations need to be trimmed.
46 const CGFloat kEditorHorizontalInset = 3.0; 46 const CGFloat kEditorHorizontalInset = 3.0;
47 47
48 const CGFloat kLocationIconXOffset = 3.0;
49
48 // Conveniences to centralize width+offset calculations. 50 // Conveniences to centralize width+offset calculations.
49 CGFloat WidthForHint(NSAttributedString* hintString) { 51 CGFloat WidthForHint(NSAttributedString* hintString) {
50 return kHintXOffset + ceil([hintString size].width); 52 return kHintXOffset + ceil([hintString size].width);
51 } 53 }
52 CGFloat WidthForKeyword(NSAttributedString* keywordString) { 54 CGFloat WidthForKeyword(NSAttributedString* keywordString) {
53 return kKeywordXOffset + ceil([keywordString size].width) + 55 return kKeywordXOffset + ceil([keywordString size].width) +
54 2 * kKeywordTokenInset; 56 2 * kKeywordTokenInset;
55 } 57 }
56 58
59 // Convenience to draw |image| in the |rect| portion of |view|.
60 void DrawImageInRect(NSImage* image, NSView* view, const NSRect& rect) {
61 DCHECK(NSEqualSizes([image size], rect.size));
62 [image setFlipped:[view isFlipped]];
63 [image drawInRect:rect
64 fromRect:NSZeroRect // Entire image
65 operation:NSCompositeSourceOver
66 fraction:1.0];
67 }
68
57 } // namespace 69 } // namespace
58 70
59 @implementation AutocompleteTextFieldIcon 71 @implementation AutocompleteTextFieldIcon
60 72
61 @synthesize rect = rect_; 73 @synthesize rect = rect_;
62 @synthesize view = view_; 74 @synthesize view = view_;
63 75
64 + (AutocompleteTextFieldIcon*) 76 // Private helper.
65 iconWithRect:(NSRect)rect 77 - (id)initWithView:(LocationBarViewMac::LocationBarImageView*)view
66 view:(LocationBarViewMac::LocationBarImageView*)view { 78 isLabel:(BOOL)isLabel {
67 AutocompleteTextFieldIcon* result = [[AutocompleteTextFieldIcon alloc] init]; 79 self = [super init];
68 [result setRect:rect]; 80 if (self) {
69 [result setView:view]; 81 isLabel_ = isLabel;
70 return [result autorelease]; 82 view_ = view;
83 rect_ = NSZeroRect;
84 }
85 return self;
86 }
87
88 - (id)initImageWithView:(LocationBarViewMac::LocationBarImageView*)view {
89 return [self initWithView:view isLabel:NO];
90 }
91
92 - (id)initLabelWithView:(LocationBarViewMac::LocationBarImageView*)view {
93 return [self initWithView:view isLabel:YES];
94 }
95
96 - (void)positionInFrame:(NSRect)frame {
97 if (isLabel_) {
98 NSAttributedString* label = view_->GetLabel();
99 DCHECK(label);
100 const CGFloat labelWidth = ceil([label size].width);
101 rect_ = NSMakeRect(NSMaxX(frame) - labelWidth,
102 NSMinY(frame) + kIconLabelYOffset,
103 labelWidth, NSHeight(frame) - kIconLabelYOffset);
104 } else {
105 const NSSize imageSize = view_->GetImageSize();
106 const CGFloat yOffset = floor((NSHeight(frame) - imageSize.height) / 2);
107 rect_ = NSMakeRect(NSMaxX(frame) - imageSize.width,
108 NSMinY(frame) + yOffset,
109 imageSize.width, imageSize.height);
110 }
111 }
112
113 - (void)drawInView:(NSView*)controlView {
114 // Make sure someone called |-positionInFrame:|.
115 DCHECK(!NSIsEmptyRect(rect_));
116 if (isLabel_) {
117 NSAttributedString* label = view_->GetLabel();
118 [label drawInRect:rect_];
119 } else {
120 DrawImageInRect(view_->GetImage(), controlView, rect_);
121 }
71 } 122 }
72 123
73 @end 124 @end
74 125
75 @implementation AutocompleteTextFieldCell 126 @implementation AutocompleteTextFieldCell
76 127
77 // @synthesize doesn't seem to compile for this transition. 128 // @synthesize doesn't seem to compile for this transition.
78 - (NSAttributedString*)keywordString { 129 - (NSAttributedString*)keywordString {
79 return keywordString_.get(); 130 return keywordString_.get();
80 } 131 }
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 - (void)clearKeywordAndHint { 258 - (void)clearKeywordAndHint {
208 keywordString_.reset(); 259 keywordString_.reset();
209 hintString_.reset(); 260 hintString_.reset();
210 } 261 }
211 262
212 - (void)setPageActionViewList:(LocationBarViewMac::PageActionViewList*)list { 263 - (void)setPageActionViewList:(LocationBarViewMac::PageActionViewList*)list {
213 page_action_views_ = list; 264 page_action_views_ = list;
214 } 265 }
215 266
216 - (void)setLocationIconView:(LocationBarViewMac::LocationIconView*)view { 267 - (void)setLocationIconView:(LocationBarViewMac::LocationIconView*)view {
217 location_icon_view_ = view; 268 locationIconView_ = view;
269 }
270
271 - (void)setSecurityLabelView:(LocationBarViewMac::LocationBarImageView*)view {
272 securityLabelView_ = view;
218 } 273 }
219 274
220 - (void)setContentSettingViewsList: 275 - (void)setContentSettingViewsList:
221 (LocationBarViewMac::ContentSettingViews*)views { 276 (LocationBarViewMac::ContentSettingViews*)views {
222 content_setting_views_ = views; 277 content_setting_views_ = views;
223 } 278 }
224 279
225 // Overriden to account for the hint strings and hint icons. 280 // Overriden to account for the hint strings and hint icons.
226 - (NSRect)textFrameForFrame:(NSRect)cellFrame { 281 - (NSRect)textFrameForFrame:(NSRect)cellFrame {
227 NSRect textFrame([super textFrameForFrame:cellFrame]); 282 NSRect textFrame([super textFrameForFrame:cellFrame]);
228 283
284 // TODO(shess): Check the set of exclusions in |LocationBarViewMac|.
285 // If |keywordString_| takes precedence over other cases, then this
286 // code could be made simpler.
287 if (!keywordString_ && locationIconView_ && locationIconView_->IsVisible()) {
288 const NSSize imageSize = locationIconView_->GetImageSize();
289 textFrame.origin.x += imageSize.width;
290 textFrame.size.width -= imageSize.width;
291 }
292
229 if (hintString_) { 293 if (hintString_) {
230 DCHECK(!keywordString_); 294 DCHECK(!keywordString_);
231 const CGFloat hintWidth(WidthForHint(hintString_)); 295 const CGFloat hintWidth(WidthForHint(hintString_));
232 296
233 // TODO(shess): This could be better. Show the hint until the 297 // TODO(shess): This could be better. Show the hint until the
234 // non-hint text bumps against it? 298 // non-hint text bumps against it?
235 if (hintWidth < NSWidth(cellFrame)) { 299 if (hintWidth < NSWidth(textFrame)) {
236 textFrame.size.width -= hintWidth; 300 textFrame.size.width -= hintWidth;
237 } 301 }
238 } else if (keywordString_) { 302 } else if (keywordString_) {
239 DCHECK(!hintString_); 303 DCHECK(!hintString_);
240 const CGFloat keywordWidth(WidthForKeyword(keywordString_)); 304 const CGFloat keywordWidth(WidthForKeyword(keywordString_));
241 305
242 // TODO(shess): This could be better. There's support for a 306 if (keywordWidth < NSWidth(textFrame)) {
243 // "short" version of the keyword string, work that in in a
244 // follow-on pass.
245 if (keywordWidth < NSWidth(cellFrame)) {
246 textFrame.origin.x += keywordWidth; 307 textFrame.origin.x += keywordWidth;
247 textFrame.size.width = NSMaxX(cellFrame) - NSMinX(textFrame); 308 textFrame.size.width -= keywordWidth;
248 } 309 }
249 } else { 310 } else {
250 // Leave room for images on the right (lock icon etc). 311 // Leave room for items on the right (SSL label, page actions,
312 // etc). Icons are laid out in |cellFrame| rather than
313 // |textFrame| for consistency with drawing code.
251 NSArray* iconFrames = [self layedOutIcons:cellFrame]; 314 NSArray* iconFrames = [self layedOutIcons:cellFrame];
252 CGFloat width = 0; 315 if ([iconFrames count]) {
253 if ([iconFrames count] > 0) 316 const CGFloat minX = NSMinX([[iconFrames objectAtIndex:0] rect]);
254 width = NSMaxX(cellFrame) - NSMinX([[iconFrames lastObject] rect]); 317 if (minX >= NSMinX(textFrame)) {
255 if (width > 0) 318 textFrame.size.width = minX - NSMinX(textFrame);
256 width += kIconHorizontalPad; 319 }
257 if (width < NSWidth(cellFrame)) 320 }
258 textFrame.size.width -= width;
259 } 321 }
260 322
261 return textFrame; 323 return textFrame;
262 } 324 }
263 325
264 // Returns a rect of size |imageSize| centered vertically and right-justified in 326 - (NSRect)locationIconFrameForFrame:(NSRect)cellFrame {
265 // the |box|, with its top left corner |margin| pixels from the right end of the 327 if (!locationIconView_ || !locationIconView_->IsVisible())
266 // box. (The image thus occupies part of the |margin|.) 328 return NSZeroRect;
267 - (NSRect)rightJustifyImage:(NSSize)imageSize
268 inRect:(NSRect)box
269 withMargin:(CGFloat)margin {
270 box.origin.x += box.size.width - margin;
271 box.origin.y += floor((box.size.height - imageSize.height) / 2);
272 box.size = imageSize;
273 return box;
274 }
275 329
276 - (NSRect)locationIconFrameForFrame:(NSRect)cellFrame { 330 const NSSize imageSize = locationIconView_->GetImageSize();
277 if (!location_icon_view_ || !location_icon_view_->IsVisible()) { 331 const CGFloat yOffset = floor((NSHeight(cellFrame) - imageSize.height) / 2);
278 return NSZeroRect; 332 return NSMakeRect(NSMinX(cellFrame) + kLocationIconXOffset,
279 } 333 NSMinY(cellFrame) + yOffset,
280 334 imageSize.width, imageSize.height);
281 // Calculate the total width occupied by the image, label, and padding.
282 NSSize imageSize = [location_icon_view_->GetImage() size];
283 CGFloat widthUsed = imageSize.width + kIconHorizontalPad;
284 NSAttributedString* label = location_icon_view_->GetLabel();
285 if (label) {
286 widthUsed += ceil([label size].width) + kHintXOffset;
287 }
288
289 return [self rightJustifyImage:imageSize
290 inRect:cellFrame
291 withMargin:widthUsed];
292 } 335 }
293 336
294 - (size_t)pageActionCount { 337 - (size_t)pageActionCount {
295 // page_action_views_ may be NULL during testing, or if the 338 // page_action_views_ may be NULL during testing, or if the
296 // containing LocationViewMac object has already been destructed 339 // containing LocationViewMac object has already been destructed
297 // (happens sometimes during window shutdown). 340 // (happens sometimes during window shutdown).
298 if (!page_action_views_) 341 if (!page_action_views_)
299 return 0; 342 return 0;
300 return page_action_views_->Count(); 343 return page_action_views_->Count();
301 } 344 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 [[[NSColor keyboardFocusIndicatorColor] colorWithAlphaComponent:0.5] set]; 395 [[[NSColor keyboardFocusIndicatorColor] colorWithAlphaComponent:0.5] set];
353 [path setLineWidth:1.0]; 396 [path setLineWidth:1.0];
354 [path stroke]; 397 [path stroke];
355 398
356 // Draw text w/in the rectangle. 399 // Draw text w/in the rectangle.
357 infoFrame.origin.x += 4.0; 400 infoFrame.origin.x += 4.0;
358 infoFrame.origin.y += 1.0; 401 infoFrame.origin.y += 1.0;
359 [keywordString_.get() drawInRect:infoFrame]; 402 [keywordString_.get() drawInRect:infoFrame];
360 } 403 }
361 404
362 - (void)drawImageView:(LocationBarViewMac::LocationBarImageView*)imageView 405 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
363 inFrame:(NSRect)imageFrame 406 if (!keywordString_ && locationIconView_ && locationIconView_->IsVisible()) {
364 inView:(NSView*)controlView { 407 DrawImageInRect(locationIconView_->GetImage(), controlView,
365 // If there's a label, draw it to the right of the icon. The caller must have 408 [self locationIconFrameForFrame:cellFrame]);
366 // left sufficient space.
367 NSAttributedString* label = imageView->GetLabel();
368 if (label) {
369 CGFloat labelWidth = ceil([label size].width) + kHintXOffset;
370 NSRect textFrame(NSMakeRect(NSMaxX(imageFrame) + kIconHorizontalPad,
371 imageFrame.origin.y + kIconLabelYOffset,
372 labelWidth,
373 imageFrame.size.height - kIconLabelYOffset));
374 [label drawInRect:textFrame];
375 } 409 }
376 410
377 // Draw the entire image.
378 NSRect imageRect = NSZeroRect;
379 NSImage* image = imageView->GetImage();
380 image.size = [image size];
381 [image setFlipped:[controlView isFlipped]];
382 [image drawInRect:imageFrame
383 fromRect:imageRect
384 operation:NSCompositeSourceOver
385 fraction:1.0];
386 }
387
388 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
389 if (hintString_) { 411 if (hintString_) {
390 [self drawHintWithFrame:cellFrame inView:controlView]; 412 [self drawHintWithFrame:cellFrame inView:controlView];
391 } else if (keywordString_) { 413 } else if (keywordString_) {
392 [self drawKeywordWithFrame:cellFrame inView:controlView]; 414 [self drawKeywordWithFrame:cellFrame inView:controlView];
393 } else { 415 } else {
394 for (AutocompleteTextFieldIcon* icon in [self layedOutIcons:cellFrame]) { 416 for (AutocompleteTextFieldIcon* icon in [self layedOutIcons:cellFrame]) {
395 [self drawImageView:[icon view] 417 [icon drawInView:controlView];
396 inFrame:[icon rect]
397 inView:controlView];
398 } 418 }
399 } 419 }
400 420
401 [super drawInteriorWithFrame:cellFrame inView:controlView]; 421 [super drawInteriorWithFrame:cellFrame inView:controlView];
402 } 422 }
403 423
404 - (NSArray*)layedOutIcons:(NSRect)cellFrame { 424 - (NSArray*)layedOutIcons:(NSRect)cellFrame {
405 NSMutableArray* result = [NSMutableArray arrayWithCapacity:0]; 425 // The set of views to display right-justified in the cell, from
406 NSRect iconFrame = cellFrame; 426 // left to right.
407 if (location_icon_view_ && location_icon_view_->IsVisible()) { 427 NSMutableArray* result = [NSMutableArray array];
408 NSRect locationIconFrame = [self locationIconFrameForFrame:iconFrame]; 428
409 [result addObject: 429 // Security label floats to left of page actions.
410 [AutocompleteTextFieldIcon iconWithRect:locationIconFrame 430 if (securityLabelView_ && securityLabelView_->IsVisible() &&
411 view:location_icon_view_]]; 431 securityLabelView_->GetLabel()) {
412 iconFrame.size.width -= NSMaxX(iconFrame) - NSMinX(locationIconFrame); 432 scoped_nsobject<AutocompleteTextFieldIcon> icon(
433 [[AutocompleteTextFieldIcon alloc]
434 initLabelWithView:securityLabelView_]);
435 [result addObject:icon];
413 } 436 }
414 437
415 const size_t pageActionCount = [self pageActionCount]; 438 // Collect the image views for bulk processing.
416 for (size_t i = 0; i < pageActionCount; ++i) { 439 // TODO(shess): Refactor with LocationBarViewMac to make the
417 LocationBarViewMac::PageActionImageView* view = 440 // different types of items more consistent.
418 page_action_views_->ViewAt(i); 441 std::vector<LocationBarViewMac::LocationBarImageView*> views;
419 if (view->IsVisible()) { 442
420 // If this function is called right after a page action icon has been 443 if (content_setting_views_) {
421 // created, the images for all views will still be loading; in this case, 444 views.insert(views.end(),
422 // each visible view will give us its default size. 445 content_setting_views_->begin(),
423 NSSize iconSize = view->GetPreferredImageSize(); 446 content_setting_views_->end());
424 NSRect pageActionFrame = 447 }
425 [self rightJustifyImage:iconSize 448
426 inRect:iconFrame 449 // TODO(shess): Previous implementation of this method made a
427 withMargin:kIconHorizontalPad + iconSize.width]; 450 // right-to-left array, so add the page-action items in that order.
428 [result addObject: 451 // As part of the refactor mentioned above, lay everything out
429 [AutocompleteTextFieldIcon iconWithRect:pageActionFrame view:view]]; 452 // nicely left-to-right.
430 iconFrame.size.width -= NSMaxX(iconFrame) - NSMinX(pageActionFrame); 453 for (size_t i = [self pageActionCount]; i-- > 0;) {
454 views.push_back(page_action_views_->ViewAt(i));
455 }
456
457 // Load the visible views into |result|.
458 for (std::vector<LocationBarViewMac::LocationBarImageView*>::const_iterator
459 iter = views.begin(); iter != views.end(); ++iter) {
460 if ((*iter)->IsVisible()) {
461 scoped_nsobject<AutocompleteTextFieldIcon> icon(
462 [[AutocompleteTextFieldIcon alloc] initImageWithView:*iter]);
463 [result addObject:icon];
431 } 464 }
432 } 465 }
433 466
434 if (content_setting_views_) { 467 // Leave a boundary at RHS of field.
435 // We use a reverse_iterator here because we're laying out the views from 468 cellFrame.size.width -= kHintXOffset;
436 // right to left but in the vector they're ordered left to right. 469
437 for (LocationBarViewMac::ContentSettingViews::const_reverse_iterator 470 // Position each view within the frame from right to left.
438 it(content_setting_views_->rbegin()); 471 for (AutocompleteTextFieldIcon* icon in [result reverseObjectEnumerator]) {
439 it != const_cast<const LocationBarViewMac::ContentSettingViews*>( 472 [icon positionInFrame:cellFrame];
440 content_setting_views_)->rend(); 473
441 ++it) { 474 // Trim the icon's space from the frame.
442 if ((*it)->IsVisible()) { 475 cellFrame.size.width = NSMinX([icon rect]) - kIconHorizontalPad;
443 NSImage* image = (*it)->GetImage();
444 NSRect blockedContentFrame =
445 [self rightJustifyImage:[image size]
446 inRect:iconFrame
447 withMargin:[image size].width + kIconHorizontalPad];
448 [result addObject:
449 [AutocompleteTextFieldIcon iconWithRect:blockedContentFrame
450 view:*it]];
451 iconFrame.size.width -= NSMaxX(iconFrame) - NSMinX(blockedContentFrame);
452 }
453 }
454 } 476 }
455 return result; 477 return result;
456 } 478 }
457 479
458 - (NSMenu*)actionMenuForEvent:(NSEvent*)event 480 - (AutocompleteTextFieldIcon*)iconForEvent:(NSEvent*)theEvent
459 inRect:(NSRect)cellFrame 481 inRect:(NSRect)cellFrame
460 ofView:(NSView*)aView { 482 ofView:(AutocompleteTextField*)controlView {
461 NSPoint location = [aView convertPoint:[event locationInWindow] fromView:nil]; 483 const BOOL flipped = [controlView isFlipped];
484 const NSPoint location =
485 [controlView convertPoint:[theEvent locationInWindow] fromView:nil];
462 486
463 const BOOL flipped = [aView isFlipped]; 487 // Special check for location image, it is not in |-layedOutIcons:|.
488 const NSRect locationIconFrame = [self locationIconFrameForFrame:cellFrame];
489 if (NSMouseInRect(location, locationIconFrame, flipped)) {
490 // Make up an icon to return.
491 AutocompleteTextFieldIcon* icon =
492 [[[AutocompleteTextFieldIcon alloc]
493 initImageWithView:locationIconView_] autorelease];
494 [icon setRect:locationIconFrame];
495 return icon;
496 }
497
464 for (AutocompleteTextFieldIcon* icon in [self layedOutIcons:cellFrame]) { 498 for (AutocompleteTextFieldIcon* icon in [self layedOutIcons:cellFrame]) {
465 if (NSMouseInRect(location, [icon rect], flipped)) { 499 if (NSMouseInRect(location, [icon rect], flipped))
466 return [icon view]->GetMenu(); 500 return icon;
467 }
468 } 501 }
502
469 return nil; 503 return nil;
470 } 504 }
471 505
506 - (NSMenu*)actionMenuForEvent:(NSEvent*)theEvent
507 inRect:(NSRect)cellFrame
508 ofView:(AutocompleteTextField*)controlView {
509 AutocompleteTextFieldIcon*
510 icon = [self iconForEvent:theEvent inRect:cellFrame ofView:controlView];
511 if (icon)
512 return [icon view]->GetMenu();
513 return nil;
514 }
515
516 - (BOOL)mouseDown:(NSEvent*)theEvent
517 inRect:(NSRect)cellFrame
518 ofView:(AutocompleteTextField*)controlView {
519 AutocompleteTextFieldIcon*
520 icon = [self iconForEvent:theEvent inRect:cellFrame ofView:controlView];
521 if (icon) {
522 [icon view]->OnMousePressed([icon rect]);
523 return YES;
524 }
525
526 return NO;
527 }
528
472 @end 529 @end
OLDNEW
« no previous file with comments | « chrome/browser/cocoa/autocomplete_text_field_cell.h ('k') | chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698