| 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/strings/sys_string_conversions.h" | 8 #include "base/strings/sys_string_conversions.h" |
| 9 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h" | 9 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h" |
| 10 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h" | 10 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h" |
| 11 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_context_menu_cocoa_controlle
r.h" | 11 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_context_menu_cocoa_controlle
r.h" |
| 12 #include "chrome/grit/generated_resources.h" | 12 #include "chrome/grit/generated_resources.h" |
| 13 #import "components/bookmarks/browser/bookmark_model.h" | 13 #import "components/bookmarks/browser/bookmark_model.h" |
| 14 #include "content/public/browser/user_metrics.h" | 14 #include "content/public/browser/user_metrics.h" |
| 15 #import "ui/base/cocoa/nsview_additions.h" | 15 #import "ui/base/cocoa/nsview_additions.h" |
| 16 #include "ui/base/l10n/l10n_util_mac.h" | 16 #include "ui/base/l10n/l10n_util_mac.h" |
| 17 #include "ui/base/material_design/material_design_controller.h" | 17 #include "ui/base/material_design/material_design_controller.h" |
| 18 #include "ui/base/resource/resource_bundle.h" | 18 #include "ui/base/resource/resource_bundle.h" |
| 19 #include "ui/resources/grit/ui_resources.h" | 19 #include "ui/resources/grit/ui_resources.h" |
| 20 | 20 |
| 21 using base::UserMetricsAction; | 21 using base::UserMetricsAction; |
| 22 using bookmarks::BookmarkNode; | 22 using bookmarks::BookmarkNode; |
| 23 | 23 |
| 24 namespace { | 24 namespace { |
| 25 | 25 |
| 26 // Padding on the right side of the arrow icon. | 26 // Padding on the right side of the arrow icon. |
| 27 const int kHierarchyButtonRightPadding = 4; | 27 const int kHierarchyButtonRightPadding = 4; |
| 28 | 28 |
| 29 // Padding on the left side of the arrow icon. | 29 // Padding on the left side of the arrow icon. |
| 30 int HierarchyButtonLeftPadding() { | 30 const int kHierarchyButtonLeftPadding = 11; |
| 31 return ui::MaterialDesignController::IsModeMaterial() ? 11 : 2; | |
| 32 } | |
| 33 | 31 |
| 34 const int kIconTextSpacer = 4; | 32 const int kIconTextSpacer = 4; |
| 35 const int kTextRightPadding = 4; | 33 const int kTextRightPadding = 4; |
| 36 const int kIconLeftPadding = 4; | 34 const int kIconLeftPadding = 4; |
| 37 | 35 |
| 38 const int kDefaultFontSize = 12; | 36 const int kDefaultFontSize = 12; |
| 39 | 37 |
| 40 }; // namespace | 38 }; // namespace |
| 41 | 39 |
| 42 @interface OffTheSideButtonCell : BookmarkButtonCell | 40 @interface OffTheSideButtonCell : BookmarkButtonCell |
| 43 | 41 |
| 44 - (NSString*)accessibilityTitle; | 42 - (NSString*)accessibilityTitle; |
| 45 | 43 |
| 46 @end | 44 @end |
| 47 @implementation OffTheSideButtonCell | 45 @implementation OffTheSideButtonCell |
| 48 | 46 |
| 49 - (BOOL)isOffTheSideButtonCell { | 47 - (BOOL)isOffTheSideButtonCell { |
| 50 return YES; | 48 return YES; |
| 51 } | 49 } |
| 52 | 50 |
| 53 - (NSString*)accessibilityTitle { | 51 - (NSString*)accessibilityTitle { |
| 54 return l10n_util::GetNSString(IDS_ACCNAME_BOOKMARKS_CHEVRON); | 52 return l10n_util::GetNSString(IDS_ACCNAME_BOOKMARKS_CHEVRON); |
| 55 } | 53 } |
| 56 | 54 |
| 57 - (NSRect)imageRectForBounds:(NSRect)theRect { | 55 - (NSRect)imageRectForBounds:(NSRect)theRect { |
| 58 NSRect imageRect = [super imageRectForBounds:theRect]; | 56 NSRect imageRect = [super imageRectForBounds:theRect]; |
| 59 if (ui::MaterialDesignController::IsModeMaterial()) { | 57 // Make sure the chevron icon stays centered. Normally a bookmark bar item |
| 60 // Make sure the chevron icon stays centered. Normally a bookmark bar item | 58 // with no label has its icon placed at a fixed x-position. |
| 61 // with no label has its icon placed at a fixed x-position. | 59 CGFloat totalWidth = NSMaxX(theRect); |
| 62 CGFloat totalWidth = NSMaxX(theRect); | 60 imageRect.origin.x = (totalWidth - [self image].size.width) / 2; |
| 63 imageRect.origin.x = (totalWidth - [self image].size.width) / 2; | |
| 64 } | |
| 65 return imageRect; | 61 return imageRect; |
| 66 } | 62 } |
| 67 | 63 |
| 68 @end | 64 @end |
| 69 | 65 |
| 70 @interface BookmarkButtonCell(Private) | 66 @interface BookmarkButtonCell(Private) |
| 71 // Returns YES if the cell is the offTheSide button cell. | 67 // Returns YES if the cell is the offTheSide button cell. |
| 72 - (BOOL)isOffTheSideButtonCell; | 68 - (BOOL)isOffTheSideButtonCell; |
| 73 - (void)configureBookmarkButtonCell; | 69 - (void)configureBookmarkButtonCell; |
| 74 - (void)applyTextColor; | 70 - (void)applyTextColor; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 - (BOOL)isOffTheSideButtonCell { | 172 - (BOOL)isOffTheSideButtonCell { |
| 177 return NO; | 173 return NO; |
| 178 } | 174 } |
| 179 | 175 |
| 180 // Perform all normal init routines specific to the BookmarkButtonCell. | 176 // Perform all normal init routines specific to the BookmarkButtonCell. |
| 181 - (void)configureBookmarkButtonCell { | 177 - (void)configureBookmarkButtonCell { |
| 182 [self setButtonType:NSMomentaryPushInButton]; | 178 [self setButtonType:NSMomentaryPushInButton]; |
| 183 [self setShowsBorderOnlyWhileMouseInside:YES]; | 179 [self setShowsBorderOnlyWhileMouseInside:YES]; |
| 184 [self setControlSize:NSSmallControlSize]; | 180 [self setControlSize:NSSmallControlSize]; |
| 185 [self setAlignment:NSLeftTextAlignment]; | 181 [self setAlignment:NSLeftTextAlignment]; |
| 186 if (!ui::MaterialDesignController::IsModeMaterial()) { | 182 [self setFont:[NSFont systemFontOfSize:kDefaultFontSize]]; |
| 187 [self setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; | 183 [self setBordered:NO]; |
| 188 [self setBezelStyle:NSShadowlessSquareBezelStyle]; | 184 [self setBezeled:NO]; |
| 189 } else { | |
| 190 [self setFont:[NSFont systemFontOfSize:kDefaultFontSize]]; | |
| 191 [self setBordered:NO]; | |
| 192 [self setBezeled:NO]; | |
| 193 } | |
| 194 [self setWraps:NO]; | 185 [self setWraps:NO]; |
| 195 // NSLineBreakByTruncatingMiddle seems more common on OSX but let's | 186 // NSLineBreakByTruncatingMiddle seems more common on OSX but let's |
| 196 // try to match Windows for a bit to see what happens. | 187 // try to match Windows for a bit to see what happens. |
| 197 [self setLineBreakMode:NSLineBreakByTruncatingTail]; | 188 [self setLineBreakMode:NSLineBreakByTruncatingTail]; |
| 198 | 189 |
| 199 // The overflow button chevron bitmap is not 16 units high, so it'd be scaled | 190 // The overflow button chevron bitmap is not 16 units high, so it'd be scaled |
| 200 // at paint time without this. | 191 // at paint time without this. |
| 201 [self setImageScaling:NSImageScaleNone]; | 192 [self setImageScaling:NSImageScaleNone]; |
| 202 | 193 |
| 203 // Theming doesn't work for bookmark buttons yet (cell text is chucked). | 194 // Theming doesn't work for bookmark buttons yet (cell text is chucked). |
| 204 [super setShouldTheme:NO]; | 195 [super setShouldTheme:NO]; |
| 205 } | 196 } |
| 206 | 197 |
| 207 - (BOOL)empty { | 198 - (BOOL)empty { |
| 208 return empty_; | 199 return empty_; |
| 209 } | 200 } |
| 210 | 201 |
| 211 - (void)setEmpty:(BOOL)empty { | 202 - (void)setEmpty:(BOOL)empty { |
| 212 empty_ = empty; | 203 empty_ = empty; |
| 213 [self setShowsBorderOnlyWhileMouseInside:!empty]; | 204 [self setShowsBorderOnlyWhileMouseInside:!empty]; |
| 214 } | 205 } |
| 215 | 206 |
| 216 - (NSSize)cellSizeForBounds:(NSRect)aRect { | 207 - (NSSize)cellSizeForBounds:(NSRect)aRect { |
| 217 // There's no bezel or border in Material Design so return cellSize. | 208 // There's no bezel or border so return cellSize. |
| 218 if (ui::MaterialDesignController::IsModeMaterial()) { | 209 NSSize size = [self cellSize]; |
| 219 NSSize size = [self cellSize]; | 210 size.width = std::min(aRect.size.width, size.width); |
| 220 size.width = std::min(aRect.size.width, size.width); | 211 size.height = std::min(aRect.size.height, size.height); |
| 221 size.height = std::min(aRect.size.height, size.height); | |
| 222 return size; | |
| 223 } | |
| 224 NSSize size = [super cellSizeForBounds:aRect]; | |
| 225 // Cocoa seems to slightly underestimate how much space we need, so we | |
| 226 // compensate here to avoid a clipped rendering. | |
| 227 size.width += 2; | |
| 228 size.height += 4; | |
| 229 return size; | 212 return size; |
| 230 } | 213 } |
| 231 | 214 |
| 232 - (void)setBookmarkCellText:(NSString*)title | 215 - (void)setBookmarkCellText:(NSString*)title |
| 233 image:(NSImage*)image { | 216 image:(NSImage*)image { |
| 234 title = [title stringByReplacingOccurrencesOfString:@"\n" | 217 title = [title stringByReplacingOccurrencesOfString:@"\n" |
| 235 withString:@" "]; | 218 withString:@" "]; |
| 236 title = [title stringByReplacingOccurrencesOfString:@"\r" | 219 title = [title stringByReplacingOccurrencesOfString:@"\r" |
| 237 withString:@" "]; | 220 withString:@" "]; |
| 238 | 221 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 } | 334 } |
| 352 | 335 |
| 353 - (NSString*)visibleTitle { | 336 - (NSString*)visibleTitle { |
| 354 return [self imagePosition] != NSImageOnly ? [self title] : @""; | 337 return [self imagePosition] != NSImageOnly ? [self title] : @""; |
| 355 } | 338 } |
| 356 | 339 |
| 357 // Add extra size for the arrow so it doesn't overlap the text. | 340 // Add extra size for the arrow so it doesn't overlap the text. |
| 358 // Does not sanity check to be sure this is actually a folder node. | 341 // Does not sanity check to be sure this is actually a folder node. |
| 359 - (NSSize)cellSize { | 342 - (NSSize)cellSize { |
| 360 NSSize cellSize = NSZeroSize; | 343 NSSize cellSize = NSZeroSize; |
| 361 if (!ui::MaterialDesignController::IsModeMaterial()) { | 344 // Return the space needed to display the image and title, with a little |
| 362 cellSize = [super cellSize]; | 345 // distance between them. |
| 346 cellSize = NSMakeSize(kIconLeftPadding + [[self image] size].width, |
| 347 bookmarks::kBookmarkButtonHeight); |
| 348 NSString* title = [self visibleTitle]; |
| 349 if ([title length] > 0) { |
| 350 CGFloat textWidth = |
| 351 [title sizeWithAttributes:[self titleTextAttributes]].width; |
| 352 cellSize.width += |
| 353 kIconTextSpacer + std::ceil(textWidth) + kTextRightPadding; |
| 363 } else { | 354 } else { |
| 364 // Return the space needed to display the image and title, with a little | 355 // Make buttons without visible titles 20pts wide (18 plus padding). |
| 365 // distance between them. | 356 cellSize.width += kIconLeftPadding; |
| 366 cellSize = NSMakeSize(kIconLeftPadding + [[self image] size].width, | |
| 367 bookmarks::kBookmarkButtonHeight); | |
| 368 NSString* title = [self visibleTitle]; | |
| 369 if ([title length] > 0) { | |
| 370 CGFloat textWidth = | |
| 371 [title sizeWithAttributes:[self titleTextAttributes]].width; | |
| 372 cellSize.width += | |
| 373 kIconTextSpacer + std::ceil(textWidth) + kTextRightPadding; | |
| 374 } else { | |
| 375 // Make buttons without visible titles 20pts wide (18 plus padding). | |
| 376 cellSize.width += kIconLeftPadding; | |
| 377 } | |
| 378 } | 357 } |
| 379 | 358 |
| 380 if (drawFolderArrow_) { | 359 if (drawFolderArrow_) { |
| 381 cellSize.width += [arrowImage_ size].width + | 360 cellSize.width += [arrowImage_ size].width + |
| 382 HierarchyButtonLeftPadding() + | 361 kHierarchyButtonLeftPadding + |
| 383 kHierarchyButtonRightPadding; | 362 kHierarchyButtonRightPadding; |
| 384 } | 363 } |
| 385 return cellSize; | 364 return cellSize; |
| 386 } | 365 } |
| 387 | 366 |
| 388 - (NSRect)imageRectForBounds:(NSRect)theRect { | 367 - (NSRect)imageRectForBounds:(NSRect)theRect { |
| 389 NSRect imageRect = [super imageRectForBounds:theRect]; | 368 NSRect imageRect = [super imageRectForBounds:theRect]; |
| 390 // In Material Design, add a little space between the image and the button's | 369 // Add a little space between the image and the button's left edge, but only |
| 391 // left edge, but only if there's a visible title. | 370 // if there's a visible title. |
| 392 if (ui::MaterialDesignController::IsModeMaterial()) { | 371 imageRect.origin.y -= 1; |
| 393 imageRect.origin.y -= 1; | 372 imageRect.origin.x = kIconLeftPadding; |
| 394 imageRect.origin.x = kIconLeftPadding; | |
| 395 } | |
| 396 return imageRect; | 373 return imageRect; |
| 397 } | 374 } |
| 398 | 375 |
| 399 - (CGFloat)textStartXOffset { | 376 - (CGFloat)textStartXOffset { |
| 400 if (!ui::MaterialDesignController::IsModeMaterial()) { | |
| 401 return [super textStartXOffset]; | |
| 402 } | |
| 403 return kIconLeftPadding + [[self image] size].width + kIconTextSpacer; | 377 return kIconLeftPadding + [[self image] size].width + kIconTextSpacer; |
| 404 } | 378 } |
| 405 | 379 |
| 406 - (void)drawFocusRingMaskWithFrame:(NSRect)cellFrame | 380 - (void)drawFocusRingMaskWithFrame:(NSRect)cellFrame |
| 407 inView:(NSView*)controlView { | 381 inView:(NSView*)controlView { |
| 408 if (ui::MaterialDesignController::IsModeMaterial()) { | 382 // We have to adjust the focus ring slightly for the chevron and regular |
| 409 // In Material Design we have to adjust the focus ring slightly for the | 383 // bookmark icons. |
| 410 // chevron and regular bookmark icons. | 384 if ([self isOffTheSideButtonCell]) { |
| 411 if ([self isOffTheSideButtonCell]) { | 385 cellFrame.origin.y -= 2; |
| 412 cellFrame.origin.y -= 2; | 386 } else if ([self visibleTitle].length > 0) { |
| 413 } else if ([self visibleTitle].length > 0) { | 387 cellFrame.origin.x += 4; |
| 414 cellFrame.origin.x += 4; | 388 } |
| 415 } | 389 if ([controlView cr_lineWidth] < 1) { |
| 416 if ([controlView cr_lineWidth] < 1) { | 390 cellFrame.origin.y -= 0.5; |
| 417 cellFrame.origin.y -= 0.5; | |
| 418 } | |
| 419 } | 391 } |
| 420 [super drawFocusRingMaskWithFrame:cellFrame inView:controlView]; | 392 [super drawFocusRingMaskWithFrame:cellFrame inView:controlView]; |
| 421 } | 393 } |
| 422 | 394 |
| 423 // Override cell drawing to add a submenu arrow like a real menu. | 395 // Override cell drawing to add a submenu arrow like a real menu. |
| 424 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { | 396 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { |
| 425 // First draw "everything else". | 397 // First draw "everything else". |
| 426 [super drawInteriorWithFrame:cellFrame inView:controlView]; | 398 [super drawInteriorWithFrame:cellFrame inView:controlView]; |
| 427 | 399 |
| 428 // If asked to do so, and if a folder, draw the arrow. | 400 // If asked to do so, and if a folder, draw the arrow. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 442 [arrowImage_ drawInRect:drawRect | 414 [arrowImage_ drawInRect:drawRect |
| 443 fromRect:imageRect | 415 fromRect:imageRect |
| 444 operation:NSCompositeSourceOver | 416 operation:NSCompositeSourceOver |
| 445 fraction:[self isEnabled] ? 1.0 : 0.5 | 417 fraction:[self isEnabled] ? 1.0 : 0.5 |
| 446 respectFlipped:YES | 418 respectFlipped:YES |
| 447 hints:nil]; | 419 hints:nil]; |
| 448 } | 420 } |
| 449 } | 421 } |
| 450 | 422 |
| 451 - (int)verticalTextOffset { | 423 - (int)verticalTextOffset { |
| 452 if (!ui::MaterialDesignController::IsModeMaterial()) { | |
| 453 return 0; | |
| 454 } | |
| 455 return -1; | 424 return -1; |
| 456 } | 425 } |
| 457 | 426 |
| 458 - (CGFloat)hoverBackgroundVerticalOffsetInControlView:(NSView*)controlView { | 427 - (CGFloat)hoverBackgroundVerticalOffsetInControlView:(NSView*)controlView { |
| 459 // In Material Design on Retina, and not in a folder menu, nudge the hover | 428 // In Material Design on Retina, and not in a folder menu, nudge the hover |
| 460 // background by 1px. | 429 // background by 1px. |
| 461 const CGFloat kLineWidth = [controlView cr_lineWidth]; | 430 const CGFloat kLineWidth = [controlView cr_lineWidth]; |
| 462 if ([self isMaterialDesignButtonType] && ![self isFolderButtonCell] && | 431 if ([self isMaterialDesignButtonType] && ![self isFolderButtonCell] && |
| 463 kLineWidth < 1) { | 432 kLineWidth < 1) { |
| 464 return -kLineWidth; | 433 return -kLineWidth; |
| 465 } | 434 } |
| 466 return 0.0; | 435 return 0.0; |
| 467 } | 436 } |
| 468 | 437 |
| 469 | 438 |
| 470 @end | 439 @end |
| OLD | NEW |