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 |