Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/bookmarks/bookmark_button_cell.h" | 5 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/metrics/user_metrics.h" | 8 #include "base/metrics/user_metrics.h" |
| 9 #include "base/strings/sys_string_conversions.h" | 9 #include "base/strings/sys_string_conversions.h" |
| 10 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h" | 10 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h" |
| 11 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h" | 11 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h" |
| 12 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_context_menu_cocoa_controlle r.h" | 12 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_context_menu_cocoa_controlle r.h" |
| 13 #include "chrome/browser/ui/cocoa/l10n_util.h" | |
| 13 #include "chrome/grit/generated_resources.h" | 14 #include "chrome/grit/generated_resources.h" |
| 14 #import "components/bookmarks/browser/bookmark_model.h" | 15 #import "components/bookmarks/browser/bookmark_model.h" |
| 15 #import "ui/base/cocoa/nsview_additions.h" | 16 #import "ui/base/cocoa/nsview_additions.h" |
| 16 #include "ui/base/l10n/l10n_util_mac.h" | 17 #include "ui/base/l10n/l10n_util_mac.h" |
| 17 #include "ui/base/material_design/material_design_controller.h" | 18 #include "ui/base/material_design/material_design_controller.h" |
| 18 #include "ui/base/resource/resource_bundle.h" | 19 #include "ui/base/resource/resource_bundle.h" |
| 19 #include "ui/resources/grit/ui_resources.h" | 20 #include "ui/resources/grit/ui_resources.h" |
| 20 | 21 |
| 21 using base::UserMetricsAction; | 22 using base::UserMetricsAction; |
| 22 using bookmarks::BookmarkNode; | 23 using bookmarks::BookmarkNode; |
| 23 | 24 |
| 24 namespace { | 25 namespace { |
| 25 | 26 |
| 26 // Padding on the right side of the arrow icon. | 27 // Padding on the trailing side of the arrow icon. |
| 27 const int kHierarchyButtonRightPadding = 4; | 28 const int kHierarchyButtonTrailingPadding = 4; |
| 28 | 29 |
| 29 // Padding on the left side of the arrow icon. | 30 // Padding on the leading side of the arrow icon. |
| 30 const int kHierarchyButtonLeftPadding = 11; | 31 const int kHierarchyButtonLeadingPadding = 11; |
| 31 | 32 |
| 32 const int kIconTextSpacer = 4; | 33 const int kIconTextSpacer = 4; |
| 33 const int kTextRightPadding = 4; | 34 const int kTextTrailingPadding = 4; |
| 34 const int kIconLeftPadding = 4; | 35 const int kIconLeadingPadding = 4; |
| 35 | 36 |
| 36 const int kDefaultFontSize = 12; | 37 const int kDefaultFontSize = 12; |
| 37 | 38 |
| 38 // Kerning value for the title text. | 39 // Kerning value for the title text. |
| 39 const CGFloat kKernAmount = 0.2; | 40 const CGFloat kKernAmount = 0.2; |
| 40 | 41 |
| 41 }; // namespace | 42 }; // namespace |
| 42 | 43 |
| 43 // TODO(lgrey): Bake setting the chevron image into this | 44 // TODO(lgrey): Bake setting the chevron image into this |
| 44 // class instead of setting it externally. | 45 // class instead of setting it externally. |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 } | 113 } |
| 113 | 114 |
| 114 + (id)offTheSideButtonCell { | 115 + (id)offTheSideButtonCell { |
| 115 return [[[OffTheSideButtonCell alloc] init] autorelease]; | 116 return [[[OffTheSideButtonCell alloc] init] autorelease]; |
| 116 } | 117 } |
| 117 | 118 |
| 118 + (CGFloat)cellWidthForNode:(const bookmarks::BookmarkNode*)node | 119 + (CGFloat)cellWidthForNode:(const bookmarks::BookmarkNode*)node |
| 119 image:(NSImage*)image { | 120 image:(NSImage*)image { |
| 120 NSString* title = | 121 NSString* title = |
| 121 [self cleanTitle:base::SysUTF16ToNSString(node->GetTitle())]; | 122 [self cleanTitle:base::SysUTF16ToNSString(node->GetTitle())]; |
| 122 CGFloat width = kIconLeftPadding + [image size].width; | 123 CGFloat width = kIconLeadingPadding + [image size].width; |
| 123 if ([title length] > 0) { | 124 if ([title length] > 0) { |
| 124 CGSize titleSize = [title sizeWithAttributes:@{ | 125 CGSize titleSize = [title sizeWithAttributes:@{ |
| 125 NSParagraphStyleAttributeName : [self paragraphStyleForBookmarkBarCell], | 126 NSParagraphStyleAttributeName : [self paragraphStyleForBookmarkBarCell], |
| 126 NSKernAttributeName : @(kKernAmount), | 127 NSKernAttributeName : @(kKernAmount), |
| 127 NSFontAttributeName : [self fontForBookmarkBarCell], | 128 NSFontAttributeName : [self fontForBookmarkBarCell], |
| 128 }]; | 129 }]; |
| 129 width += kIconTextSpacer + std::ceil(titleSize.width) + kTextRightPadding; | 130 width += |
| 131 kIconTextSpacer + std::ceil(titleSize.width) + kTextTrailingPadding; | |
| 130 } else { | 132 } else { |
| 131 width += kIconLeftPadding; | 133 width += kIconLeadingPadding; |
|
Elly Fong-Jones
2017/05/03 17:03:14
why is this leading padding twice? shouldn't it al
lgrey
2017/05/03 21:32:48
Done.
| |
| 132 } | 134 } |
| 133 return width; | 135 return width; |
| 134 } | 136 } |
| 135 | 137 |
| 136 - (id)initForNode:(const BookmarkNode*)node | 138 - (id)initForNode:(const BookmarkNode*)node |
| 137 text:(NSString*)text | 139 text:(NSString*)text |
| 138 image:(NSImage*)image | 140 image:(NSImage*)image |
| 139 menuController:(BookmarkContextMenuCocoaController*)menuController { | 141 menuController:(BookmarkContextMenuCocoaController*)menuController { |
| 140 if ((self = [super initTextCell:text])) { | 142 if ((self = [super initTextCell:text])) { |
| 141 menuController_ = menuController; | 143 menuController_ = menuController; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 189 | 191 |
| 190 - (BOOL)isOffTheSideButtonCell { | 192 - (BOOL)isOffTheSideButtonCell { |
| 191 return NO; | 193 return NO; |
| 192 } | 194 } |
| 193 | 195 |
| 194 // Perform all normal init routines specific to the BookmarkButtonCell. | 196 // Perform all normal init routines specific to the BookmarkButtonCell. |
| 195 - (void)configureBookmarkButtonCell { | 197 - (void)configureBookmarkButtonCell { |
| 196 [self setButtonType:NSMomentaryPushInButton]; | 198 [self setButtonType:NSMomentaryPushInButton]; |
| 197 [self setShowsBorderOnlyWhileMouseInside:YES]; | 199 [self setShowsBorderOnlyWhileMouseInside:YES]; |
| 198 [self setControlSize:NSSmallControlSize]; | 200 [self setControlSize:NSSmallControlSize]; |
| 199 [self setAlignment:NSLeftTextAlignment]; | |
| 200 [self setFont:[[self class] fontForBookmarkBarCell]]; | 201 [self setFont:[[self class] fontForBookmarkBarCell]]; |
| 202 [self setAlignment:NSNaturalTextAlignment]; | |
|
Elly Fong-Jones
2017/05/03 17:03:14
why did this move? is it important that these be d
lgrey
2017/05/03 21:32:48
I think this was an accident, doesn't seem to make
| |
| 201 [self setBordered:NO]; | 203 [self setBordered:NO]; |
| 202 [self setBezeled:NO]; | 204 [self setBezeled:NO]; |
| 203 [self setWraps:NO]; | 205 [self setWraps:NO]; |
| 204 // NSLineBreakByTruncatingMiddle seems more common on OSX but let's | 206 // NSLineBreakByTruncatingMiddle seems more common on OSX but let's |
| 205 // try to match Windows for a bit to see what happens. | 207 // try to match Windows for a bit to see what happens. |
| 206 [self setLineBreakMode:NSLineBreakByTruncatingTail]; | 208 [self setLineBreakMode:NSLineBreakByTruncatingTail]; |
| 207 | 209 |
| 208 // The overflow button chevron bitmap is not 16 units high, so it'd be scaled | 210 // The overflow button chevron bitmap is not 16 units high, so it'd be scaled |
| 209 // at paint time without this. | 211 // at paint time without this. |
| 210 [self setImageScaling:NSImageScaleNone]; | 212 [self setImageScaling:NSImageScaleNone]; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 227 NSSize size = [self cellSize]; | 229 NSSize size = [self cellSize]; |
| 228 size.width = std::min(aRect.size.width, size.width); | 230 size.width = std::min(aRect.size.width, size.width); |
| 229 size.height = std::min(aRect.size.height, size.height); | 231 size.height = std::min(aRect.size.height, size.height); |
| 230 return size; | 232 return size; |
| 231 } | 233 } |
| 232 | 234 |
| 233 - (void)setBookmarkCellText:(NSString*)title | 235 - (void)setBookmarkCellText:(NSString*)title |
| 234 image:(NSImage*)image { | 236 image:(NSImage*)image { |
| 235 title = [[self class] cleanTitle:title]; | 237 title = [[self class] cleanTitle:title]; |
| 236 if ([title length] && ![self isOffTheSideButtonCell]) { | 238 if ([title length] && ![self isOffTheSideButtonCell]) { |
| 237 [self setImagePosition:NSImageLeft]; | 239 [self setImagePosition:cocoa_l10n_util::LeadingCellImagePosition()]; |
| 238 [self setTitle:title]; | 240 [self setTitle:title]; |
| 239 } else if ([self isFolderButtonCell]) { | 241 } else if ([self isFolderButtonCell]) { |
| 240 // Left-align icons for bookmarks within folders, regardless of whether | 242 // Left-align icons for bookmarks within folders, regardless of whether |
| 241 // there is a title. | 243 // there is a title. |
| 242 [self setImagePosition:NSImageLeft]; | 244 [self setImagePosition:cocoa_l10n_util::LeadingCellImagePosition()]; |
| 243 } else { | 245 } else { |
| 244 // For bookmarks without a title that aren't visible directly in the | 246 // For bookmarks without a title that aren't visible directly in the |
| 245 // bookmarks bar, squeeze things tighter by displaying only the image. | 247 // bookmarks bar, squeeze things tighter by displaying only the image. |
| 246 // By default, Cocoa leaves extra space in an attempt to display an | 248 // By default, Cocoa leaves extra space in an attempt to display an |
| 247 // empty title. | 249 // empty title. |
| 248 [self setImagePosition:NSImageOnly]; | 250 [self setImagePosition:NSImageOnly]; |
| 249 } | 251 } |
| 250 | 252 |
| 251 if (image) | 253 if (image) |
| 252 [self setImage:image]; | 254 [self setImage:image]; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 322 // See comment above mouseEntered:, above. | 324 // See comment above mouseEntered:, above. |
| 323 - (void)mouseExited:(NSEvent*)event { | 325 - (void)mouseExited:(NSEvent*)event { |
| 324 [[self controlView] mouseExited:event]; | 326 [[self controlView] mouseExited:event]; |
| 325 [super mouseExited:event]; | 327 [super mouseExited:event]; |
| 326 } | 328 } |
| 327 | 329 |
| 328 - (void)setDrawFolderArrow:(BOOL)draw { | 330 - (void)setDrawFolderArrow:(BOOL)draw { |
| 329 drawFolderArrow_ = draw; | 331 drawFolderArrow_ = draw; |
| 330 if (draw && !arrowImage_) { | 332 if (draw && !arrowImage_) { |
| 331 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 333 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 332 arrowImage_.reset( | 334 NSImage* image = |
| 333 [rb.GetNativeImageNamed(IDR_MENU_HIERARCHY_ARROW).ToNSImage() retain]); | 335 rb.GetNativeImageNamed(IDR_MENU_HIERARCHY_ARROW).ToNSImage(); |
| 336 if (cocoa_l10n_util::ShouldDoExperimentalRTLLayout()) | |
| 337 image = cocoa_l10n_util::FlippedImage(image); | |
| 338 arrowImage_.reset([image retain]); | |
| 334 } | 339 } |
| 335 } | 340 } |
| 336 | 341 |
| 337 - (NSDictionary*)titleTextAttributes { | 342 - (NSDictionary*)titleTextAttributes { |
| 338 NSParagraphStyle* style = [[self class] paragraphStyleForBookmarkBarCell]; | 343 NSParagraphStyle* style = [[self class] paragraphStyleForBookmarkBarCell]; |
| 339 NSColor* textColor = textColor_.get(); | 344 NSColor* textColor = textColor_.get(); |
| 340 if (!textColor) { | 345 if (!textColor) { |
| 341 textColor = [NSColor blackColor]; | 346 textColor = [NSColor blackColor]; |
| 342 } | 347 } |
| 343 if (![self isEnabled]) { | 348 if (![self isEnabled]) { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 359 - (NSString*)visibleTitle { | 364 - (NSString*)visibleTitle { |
| 360 return [self imagePosition] != NSImageOnly ? [self title] : @""; | 365 return [self imagePosition] != NSImageOnly ? [self title] : @""; |
| 361 } | 366 } |
| 362 | 367 |
| 363 // Add extra size for the arrow so it doesn't overlap the text. | 368 // Add extra size for the arrow so it doesn't overlap the text. |
| 364 // Does not sanity check to be sure this is actually a folder node. | 369 // Does not sanity check to be sure this is actually a folder node. |
| 365 - (NSSize)cellSize { | 370 - (NSSize)cellSize { |
| 366 NSSize cellSize = NSZeroSize; | 371 NSSize cellSize = NSZeroSize; |
| 367 // Return the space needed to display the image and title, with a little | 372 // Return the space needed to display the image and title, with a little |
| 368 // distance between them. | 373 // distance between them. |
| 369 cellSize = NSMakeSize(kIconLeftPadding + [[self image] size].width, | 374 cellSize = NSMakeSize(kIconLeadingPadding + [[self image] size].width, |
| 370 bookmarks::kBookmarkButtonHeight); | 375 bookmarks::kBookmarkButtonHeight); |
| 371 NSString* title = [self visibleTitle]; | 376 NSString* title = [self visibleTitle]; |
| 372 if ([title length] > 0) { | 377 if ([title length] > 0) { |
| 373 CGFloat textWidth = | 378 CGFloat textWidth = |
| 374 [title sizeWithAttributes:[self titleTextAttributes]].width; | 379 [title sizeWithAttributes:[self titleTextAttributes]].width; |
| 375 cellSize.width += | 380 cellSize.width += |
| 376 kIconTextSpacer + std::ceil(textWidth) + kTextRightPadding; | 381 kIconTextSpacer + std::ceil(textWidth) + kTextTrailingPadding; |
| 377 } else { | 382 } else { |
| 378 // Make buttons without visible titles 20pts wide (18 plus padding). | 383 // Make buttons without visible titles 20pts wide (18 plus padding). |
|
Elly Fong-Jones
2017/05/03 17:03:14
please delete this comment! comments that duplicat
lgrey
2017/05/03 21:32:48
Done.
| |
| 379 cellSize.width += kIconLeftPadding; | 384 cellSize.width += kIconLeadingPadding; |
| 380 } | 385 } |
| 381 | 386 |
| 382 if (drawFolderArrow_) { | 387 if (drawFolderArrow_) { |
| 383 cellSize.width += [arrowImage_ size].width + | 388 cellSize.width += [arrowImage_ size].width + |
| 384 kHierarchyButtonLeftPadding + | 389 kHierarchyButtonLeadingPadding + |
| 385 kHierarchyButtonRightPadding; | 390 kHierarchyButtonTrailingPadding; |
| 386 } | 391 } |
| 387 return cellSize; | 392 return cellSize; |
| 388 } | 393 } |
| 389 | 394 |
| 390 - (NSRect)imageRectForBounds:(NSRect)theRect { | 395 - (NSRect)imageRectForBounds:(NSRect)theRect { |
| 391 NSRect imageRect = [super imageRectForBounds:theRect]; | 396 NSRect imageRect = [super imageRectForBounds:theRect]; |
| 392 // Add a little space between the image and the button's left edge, but only | 397 const CGFloat inset = [self insetInView:[self controlView]]; |
| 393 // if there's a visible title. | |
| 394 imageRect.origin.y -= 1; | 398 imageRect.origin.y -= 1; |
| 395 imageRect.origin.x = kIconLeftPadding; | 399 imageRect.origin.x = |
| 400 cocoa_l10n_util::ShouldDoExperimentalRTLLayout() | |
| 401 ? NSMaxX(theRect) - kIconLeadingPadding - NSWidth(imageRect) + inset | |
| 402 : kIconLeadingPadding; | |
| 396 return imageRect; | 403 return imageRect; |
| 397 } | 404 } |
| 398 | 405 |
| 399 - (CGFloat)textStartXOffset { | 406 - (NSRect)titleRectForBounds:(NSRect)theRect { |
| 400 return kIconLeftPadding + [[self image] size].width + kIconTextSpacer; | 407 NSRect textRect = [super titleRectForBounds:theRect]; |
| 408 NSRect imageRect = [self imageRectForBounds:theRect]; | |
| 409 if (cocoa_l10n_util::ShouldDoExperimentalRTLLayout()) { | |
| 410 textRect.origin.x = drawFolderArrow_ ? [arrowImage_ size].width + | |
| 411 kHierarchyButtonTrailingPadding + | |
| 412 kTextTrailingPadding | |
| 413 : kTextTrailingPadding; | |
| 414 textRect.size.width = | |
| 415 NSMinX(imageRect) - textRect.origin.x - kIconTextSpacer; | |
| 416 } else { | |
| 417 textRect.origin.x = NSMaxX(imageRect) + kIconTextSpacer; | |
| 418 } | |
| 419 return textRect; | |
| 401 } | 420 } |
| 402 | 421 |
| 403 - (void)drawFocusRingMaskWithFrame:(NSRect)cellFrame | 422 - (void)drawFocusRingMaskWithFrame:(NSRect)cellFrame |
| 404 inView:(NSView*)controlView { | 423 inView:(NSView*)controlView { |
| 405 // We have to adjust the focus ring slightly for the chevron and regular | 424 // We have to adjust the focus ring slightly for the chevron and regular |
| 406 // bookmark icons. | 425 // bookmark icons. |
| 407 if ([self isOffTheSideButtonCell]) { | 426 if ([self isOffTheSideButtonCell]) { |
| 408 cellFrame.origin.y -= 2; | 427 cellFrame.origin.y -= 2; |
| 409 } else if ([self visibleTitle].length > 0) { | 428 } else if ([self visibleTitle].length > 0) { |
| 410 cellFrame.origin.x += 4; | 429 cellFrame.origin.x += 4; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 422 | 441 |
| 423 // If asked to do so, and if a folder, draw the arrow. | 442 // If asked to do so, and if a folder, draw the arrow. |
| 424 if (!drawFolderArrow_) | 443 if (!drawFolderArrow_) |
| 425 return; | 444 return; |
| 426 BookmarkButton* button = static_cast<BookmarkButton*>([self controlView]); | 445 BookmarkButton* button = static_cast<BookmarkButton*>([self controlView]); |
| 427 DCHECK([button respondsToSelector:@selector(isFolder)]); | 446 DCHECK([button respondsToSelector:@selector(isFolder)]); |
| 428 if ([button isFolder]) { | 447 if ([button isFolder]) { |
| 429 NSRect imageRect = NSZeroRect; | 448 NSRect imageRect = NSZeroRect; |
| 430 imageRect.size = [arrowImage_ size]; | 449 imageRect.size = [arrowImage_ size]; |
| 431 const CGFloat kArrowOffset = 1.0; // Required for proper centering. | 450 const CGFloat kArrowOffset = 1.0; // Required for proper centering. |
| 432 CGFloat dX = | 451 CGFloat dX = cocoa_l10n_util::ShouldDoExperimentalRTLLayout() |
| 433 NSWidth(cellFrame) - NSWidth(imageRect) - kHierarchyButtonRightPadding; | 452 ? kHierarchyButtonTrailingPadding |
| 453 : NSWidth(cellFrame) - NSWidth(imageRect) - | |
| 454 kHierarchyButtonTrailingPadding; | |
| 434 CGFloat dY = (NSHeight(cellFrame) / 2.0) - (NSHeight(imageRect) / 2.0) + | 455 CGFloat dY = (NSHeight(cellFrame) / 2.0) - (NSHeight(imageRect) / 2.0) + |
| 435 kArrowOffset; | 456 kArrowOffset; |
| 436 NSRect drawRect = NSOffsetRect(imageRect, dX, dY); | 457 NSRect drawRect = NSOffsetRect(imageRect, dX, dY); |
| 437 [arrowImage_ drawInRect:drawRect | 458 [arrowImage_ drawInRect:drawRect |
| 438 fromRect:imageRect | 459 fromRect:imageRect |
| 439 operation:NSCompositeSourceOver | 460 operation:NSCompositeSourceOver |
| 440 fraction:[self isEnabled] ? 1.0 : 0.5 | 461 fraction:[self isEnabled] ? 1.0 : 0.5 |
| 441 respectFlipped:YES | 462 respectFlipped:YES |
| 442 hints:nil]; | 463 hints:nil]; |
| 443 } | 464 } |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 471 | 492 |
| 472 // Returns |title| with newlines and line feeds replaced with | 493 // Returns |title| with newlines and line feeds replaced with |
| 473 // spaces. | 494 // spaces. |
| 474 + (NSString*)cleanTitle:(NSString*)title { | 495 + (NSString*)cleanTitle:(NSString*)title { |
| 475 title = [title stringByReplacingOccurrencesOfString:@"\n" withString:@" "]; | 496 title = [title stringByReplacingOccurrencesOfString:@"\n" withString:@" "]; |
| 476 title = [title stringByReplacingOccurrencesOfString:@"\r" withString:@" "]; | 497 title = [title stringByReplacingOccurrencesOfString:@"\r" withString:@" "]; |
| 477 return title; | 498 return title; |
| 478 } | 499 } |
| 479 | 500 |
| 480 @end | 501 @end |
| OLD | NEW |