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" |
(...skipping 19 matching lines...) Expand all Loading... | |
30 const int kHierarchyButtonLeftPadding = 11; | 30 const int kHierarchyButtonLeftPadding = 11; |
31 | 31 |
32 const int kIconTextSpacer = 4; | 32 const int kIconTextSpacer = 4; |
33 const int kTextRightPadding = 4; | 33 const int kTextRightPadding = 4; |
34 const int kIconLeftPadding = 4; | 34 const int kIconLeftPadding = 4; |
35 | 35 |
36 const int kDefaultFontSize = 12; | 36 const int kDefaultFontSize = 12; |
37 | 37 |
38 }; // namespace | 38 }; // namespace |
39 | 39 |
40 @interface BookmarkButtonCell (Private) | |
41 // Returns YES if the cell is the offTheSide button cell. | |
42 - (BOOL)isOffTheSideButtonCell; | |
43 - (void)configureBookmarkButtonCell; | |
44 - (void)applyTextColor; | |
45 // Returns the title the button cell displays. Note that a button cell can | |
46 // have a title string assigned but it won't be visible if its image position | |
47 // is NSImageOnly. | |
48 - (NSString*)visibleTitle; | |
49 // Returns the dictionary of attributes to associate with the button title. | |
50 - (NSDictionary*)titleTextAttributes; | |
51 @end | |
52 | |
40 // TODO(lgrey): Bake setting the chevron image into this | 53 // TODO(lgrey): Bake setting the chevron image into this |
41 // class instead of setting it externally. | 54 // class instead of setting it externally. |
42 @interface OffTheSideButtonCell : BookmarkButtonCell | 55 @interface OffTheSideButtonCell : BookmarkButtonCell |
43 | 56 |
44 - (NSString*)accessibilityTitle; | 57 - (NSString*)accessibilityTitle; |
45 | 58 |
46 @end | 59 @end |
47 @implementation OffTheSideButtonCell | 60 @implementation OffTheSideButtonCell |
48 | 61 |
49 - (BOOL)isOffTheSideButtonCell { | 62 - (BOOL)isOffTheSideButtonCell { |
50 return YES; | 63 return YES; |
51 } | 64 } |
52 | 65 |
53 - (NSString*)accessibilityTitle { | 66 - (NSString*)accessibilityTitle { |
54 return l10n_util::GetNSString(IDS_ACCNAME_BOOKMARKS_CHEVRON); | 67 return l10n_util::GetNSString(IDS_ACCNAME_BOOKMARKS_CHEVRON); |
55 } | 68 } |
56 | 69 |
57 - (NSRect)imageRectForBounds:(NSRect)theRect { | 70 - (NSRect)imageRectForBounds:(NSRect)theRect { |
58 NSRect imageRect = [super imageRectForBounds:theRect]; | 71 NSRect imageRect = [super imageRectForBounds:theRect]; |
59 // Make sure the chevron icon stays centered. Normally a bookmark bar item | 72 // Make sure the chevron icon stays centered. Normally a bookmark bar item |
60 // with no label has its icon placed at a fixed x-position. | 73 // with no label has its icon placed at a fixed x-position. |
61 CGFloat totalWidth = NSMaxX(theRect); | 74 CGFloat totalWidth = NSMaxX(theRect); |
62 imageRect.origin.x = (totalWidth - [self image].size.width) / 2; | 75 imageRect.origin.x = (totalWidth - [self image].size.width) / 2; |
63 return imageRect; | 76 return imageRect; |
64 } | 77 } |
65 | 78 |
66 @end | 79 @end |
67 | 80 |
68 @interface BookmarkButtonCell(Private) | |
69 // Returns YES if the cell is the offTheSide button cell. | |
70 - (BOOL)isOffTheSideButtonCell; | |
71 - (void)configureBookmarkButtonCell; | |
72 - (void)applyTextColor; | |
73 // Returns the title the button cell displays. Note that a button cell can | |
74 // have a title string assigned but it won't be visible if its image position | |
75 // is NSImageOnly. | |
76 - (NSString*)visibleTitle; | |
77 // Returns the dictionary of attributes to associate with the button title. | |
78 - (NSDictionary*)titleTextAttributes; | |
79 @end | |
80 | |
81 | 81 |
82 @implementation BookmarkButtonCell | 82 @implementation BookmarkButtonCell |
83 | 83 |
84 @synthesize startingChildIndex = startingChildIndex_; | 84 @synthesize startingChildIndex = startingChildIndex_; |
85 @synthesize drawFolderArrow = drawFolderArrow_; | 85 @synthesize drawFolderArrow = drawFolderArrow_; |
86 | 86 |
87 + (id)buttonCellForNode:(const BookmarkNode*)node | 87 + (id)buttonCellForNode:(const BookmarkNode*)node |
88 text:(NSString*)text | 88 text:(NSString*)text |
89 image:(NSImage*)image | 89 image:(NSImage*)image |
90 menuController:(BookmarkContextMenuCocoaController*)menuController { | 90 menuController:(BookmarkContextMenuCocoaController*)menuController { |
(...skipping 14 matching lines...) Expand all Loading... | |
105 image:image | 105 image:image |
106 menuController:menuController] | 106 menuController:menuController] |
107 autorelease]; | 107 autorelease]; |
108 return buttonCell; | 108 return buttonCell; |
109 } | 109 } |
110 | 110 |
111 + (id)offTheSideButtonCell { | 111 + (id)offTheSideButtonCell { |
112 return [[[OffTheSideButtonCell alloc] init] autorelease]; | 112 return [[[OffTheSideButtonCell alloc] init] autorelease]; |
113 } | 113 } |
114 | 114 |
115 + (CGFloat)cellWidthForNode:(const bookmarks::BookmarkNode*)node | |
116 image:(NSImage*)image { | |
117 NSString* title = | |
118 [self cleanTitle:base::SysUTF16ToNSString(node->GetTitle())]; | |
119 CGFloat width = kIconLeftPadding + [image size].width; | |
120 if ([title length] > 0) { | |
121 CGSize titleSize = [title sizeWithAttributes:@{ | |
122 NSParagraphStyleAttributeName : [self paragraphStyleForBookmarkBarCell] | |
123 }]; | |
124 width += kIconTextSpacer + std::ceil(titleSize.width) + kTextRightPadding; | |
125 } else { | |
126 width += kIconLeftPadding; | |
127 } | |
128 return width; | |
129 } | |
130 | |
115 - (id)initForNode:(const BookmarkNode*)node | 131 - (id)initForNode:(const BookmarkNode*)node |
116 text:(NSString*)text | 132 text:(NSString*)text |
117 image:(NSImage*)image | 133 image:(NSImage*)image |
118 menuController:(BookmarkContextMenuCocoaController*)menuController { | 134 menuController:(BookmarkContextMenuCocoaController*)menuController { |
119 if ((self = [super initTextCell:text])) { | 135 if ((self = [super initTextCell:text])) { |
120 menuController_ = menuController; | 136 menuController_ = menuController; |
121 [self configureBookmarkButtonCell]; | 137 [self configureBookmarkButtonCell]; |
122 [self setTextColor:[NSColor blackColor]]; | 138 [self setTextColor:[NSColor blackColor]]; |
123 [self setBookmarkNode:node]; | 139 [self setBookmarkNode:node image:image]; |
124 // When opening a bookmark folder, the default behavior is that the | 140 // When opening a bookmark folder, the default behavior is that the |
125 // favicon is greyed when menu item is hovered with the mouse cursor. | 141 // favicon is greyed when menu item is hovered with the mouse cursor. |
126 // When using NSNoCellMask, the favicon won't be greyed when menu item | 142 // When using NSNoCellMask, the favicon won't be greyed when menu item |
127 // is hovered. | 143 // is hovered. |
128 // In the bookmark bar, the favicon is not greyed when the bookmark is | 144 // In the bookmark bar, the favicon is not greyed when the bookmark is |
129 // hovered with the mouse cursor. | 145 // hovered with the mouse cursor. |
130 // It makes the behavior of the bookmark folder consistent with hovering | 146 // It makes the behavior of the bookmark folder consistent with hovering |
131 // on the bookmark bar. | 147 // on the bookmark bar. |
132 [self setHighlightsBy:NSNoCellMask]; | 148 [self setHighlightsBy:NSNoCellMask]; |
133 | |
134 if (node) { | |
135 NSString* title = base::SysUTF16ToNSString(node->GetTitle()); | |
136 [self setBookmarkCellText:title image:image]; | |
137 } else { | |
138 [self setEmpty:YES]; | |
139 [self setBookmarkCellText:l10n_util::GetNSString(IDS_MENU_EMPTY_SUBMENU) | |
140 image:nil]; | |
141 } | |
142 } | 149 } |
143 | 150 |
144 return self; | 151 return self; |
145 } | 152 } |
146 | 153 |
147 - (id)initWithText:(NSString*)text | 154 - (id)initWithText:(NSString*)text |
148 image:(NSImage*)image | 155 image:(NSImage*)image |
149 menuController:(BookmarkContextMenuCocoaController*)menuController { | 156 menuController:(BookmarkContextMenuCocoaController*)menuController { |
150 if ((self = [super initTextCell:text])) { | 157 if ((self = [super initTextCell:text])) { |
151 menuController_ = menuController; | 158 menuController_ = menuController; |
(...skipping 26 matching lines...) Expand all Loading... | |
178 - (BOOL)isOffTheSideButtonCell { | 185 - (BOOL)isOffTheSideButtonCell { |
179 return NO; | 186 return NO; |
180 } | 187 } |
181 | 188 |
182 // Perform all normal init routines specific to the BookmarkButtonCell. | 189 // Perform all normal init routines specific to the BookmarkButtonCell. |
183 - (void)configureBookmarkButtonCell { | 190 - (void)configureBookmarkButtonCell { |
184 [self setButtonType:NSMomentaryPushInButton]; | 191 [self setButtonType:NSMomentaryPushInButton]; |
185 [self setShowsBorderOnlyWhileMouseInside:YES]; | 192 [self setShowsBorderOnlyWhileMouseInside:YES]; |
186 [self setControlSize:NSSmallControlSize]; | 193 [self setControlSize:NSSmallControlSize]; |
187 [self setAlignment:NSLeftTextAlignment]; | 194 [self setAlignment:NSLeftTextAlignment]; |
188 [self setFont:[NSFont systemFontOfSize:kDefaultFontSize]]; | 195 [self setFont:[[self class] fontForBookmarkBarCell]]; |
189 [self setBordered:NO]; | 196 [self setBordered:NO]; |
190 [self setBezeled:NO]; | 197 [self setBezeled:NO]; |
191 [self setWraps:NO]; | 198 [self setWraps:NO]; |
192 // NSLineBreakByTruncatingMiddle seems more common on OSX but let's | 199 // NSLineBreakByTruncatingMiddle seems more common on OSX but let's |
193 // try to match Windows for a bit to see what happens. | 200 // try to match Windows for a bit to see what happens. |
194 [self setLineBreakMode:NSLineBreakByTruncatingTail]; | 201 [self setLineBreakMode:NSLineBreakByTruncatingTail]; |
195 | 202 |
196 // The overflow button chevron bitmap is not 16 units high, so it'd be scaled | 203 // The overflow button chevron bitmap is not 16 units high, so it'd be scaled |
197 // at paint time without this. | 204 // at paint time without this. |
198 [self setImageScaling:NSImageScaleNone]; | 205 [self setImageScaling:NSImageScaleNone]; |
(...skipping 14 matching lines...) Expand all Loading... | |
213 - (NSSize)cellSizeForBounds:(NSRect)aRect { | 220 - (NSSize)cellSizeForBounds:(NSRect)aRect { |
214 // There's no bezel or border so return cellSize. | 221 // There's no bezel or border so return cellSize. |
215 NSSize size = [self cellSize]; | 222 NSSize size = [self cellSize]; |
216 size.width = std::min(aRect.size.width, size.width); | 223 size.width = std::min(aRect.size.width, size.width); |
217 size.height = std::min(aRect.size.height, size.height); | 224 size.height = std::min(aRect.size.height, size.height); |
218 return size; | 225 return size; |
219 } | 226 } |
220 | 227 |
221 - (void)setBookmarkCellText:(NSString*)title | 228 - (void)setBookmarkCellText:(NSString*)title |
222 image:(NSImage*)image { | 229 image:(NSImage*)image { |
223 title = [title stringByReplacingOccurrencesOfString:@"\n" | 230 title = [[self class] cleanTitle:title]; |
224 withString:@" "]; | 231 if ([title length] && ![self isOffTheSideButtonCell]) { |
225 title = [title stringByReplacingOccurrencesOfString:@"\r" | |
226 withString:@" "]; | |
227 | |
228 if ([title length]) { | |
229 [self setImagePosition:NSImageLeft]; | 232 [self setImagePosition:NSImageLeft]; |
230 [self setTitle:title]; | 233 [self setTitle:title]; |
231 } else if ([self isFolderButtonCell]) { | 234 } else if ([self isFolderButtonCell]) { |
232 // Left-align icons for bookmarks within folders, regardless of whether | 235 // Left-align icons for bookmarks within folders, regardless of whether |
233 // there is a title. | 236 // there is a title. |
234 [self setImagePosition:NSImageLeft]; | 237 [self setImagePosition:NSImageLeft]; |
235 } else { | 238 } else { |
236 // For bookmarks without a title that aren't visible directly in the | 239 // For bookmarks without a title that aren't visible directly in the |
237 // bookmarks bar, squeeze things tighter by displaying only the image. | 240 // bookmarks bar, squeeze things tighter by displaying only the image. |
238 // By default, Cocoa leaves extra space in an attempt to display an | 241 // By default, Cocoa leaves extra space in an attempt to display an |
239 // empty title. | 242 // empty title. |
240 [self setImagePosition:NSImageOnly]; | 243 [self setImagePosition:NSImageOnly]; |
241 } | 244 } |
242 | 245 |
243 if (image) | 246 if (image) |
244 [self setImage:image]; | 247 [self setImage:image]; |
245 } | 248 } |
246 | 249 |
247 - (void)setBookmarkNode:(const BookmarkNode*)node { | 250 - (void)setBookmarkNode:(const BookmarkNode*)node { |
251 [self setBookmarkNode:node image:nil]; | |
252 } | |
253 | |
254 - (void)setBookmarkNode:(const BookmarkNode*)node image:(NSImage*)image { | |
248 [self setRepresentedObject:[NSValue valueWithPointer:node]]; | 255 [self setRepresentedObject:[NSValue valueWithPointer:node]]; |
256 if (node) { | |
257 NSString* title = base::SysUTF16ToNSString(node->GetTitle()); | |
258 [self setBookmarkCellText:title image:image]; | |
259 } else { | |
260 [self setEmpty:YES]; | |
261 [self setBookmarkCellText:l10n_util::GetNSString(IDS_MENU_EMPTY_SUBMENU) | |
262 image:nil]; | |
263 } | |
249 } | 264 } |
250 | 265 |
251 - (const BookmarkNode*)bookmarkNode { | 266 - (const BookmarkNode*)bookmarkNode { |
252 return static_cast<const BookmarkNode*>([[self representedObject] | 267 return static_cast<const BookmarkNode*>([[self representedObject] |
253 pointerValue]); | 268 pointerValue]); |
254 } | 269 } |
255 | 270 |
256 - (NSMenu*)menu { | 271 - (NSMenu*)menu { |
257 // If node is NULL, this is a custom button, the menu does not represent | 272 // If node is NULL, this is a custom button, the menu does not represent |
258 // anything. | 273 // anything. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
308 - (void)setDrawFolderArrow:(BOOL)draw { | 323 - (void)setDrawFolderArrow:(BOOL)draw { |
309 drawFolderArrow_ = draw; | 324 drawFolderArrow_ = draw; |
310 if (draw && !arrowImage_) { | 325 if (draw && !arrowImage_) { |
311 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 326 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
312 arrowImage_.reset( | 327 arrowImage_.reset( |
313 [rb.GetNativeImageNamed(IDR_MENU_HIERARCHY_ARROW).ToNSImage() retain]); | 328 [rb.GetNativeImageNamed(IDR_MENU_HIERARCHY_ARROW).ToNSImage() retain]); |
314 } | 329 } |
315 } | 330 } |
316 | 331 |
317 - (NSDictionary*)titleTextAttributes { | 332 - (NSDictionary*)titleTextAttributes { |
318 base::scoped_nsobject<NSMutableParagraphStyle> style( | 333 NSParagraphStyle* style = [[self class] paragraphStyleForBookmarkBarCell]; |
319 [NSMutableParagraphStyle new]); | |
320 [style setAlignment:NSNaturalTextAlignment]; | |
321 [style setLineBreakMode:NSLineBreakByTruncatingTail]; | |
322 NSColor* textColor = textColor_.get(); | 334 NSColor* textColor = textColor_.get(); |
323 if (!textColor) { | 335 if (!textColor) { |
324 textColor = [NSColor blackColor]; | 336 textColor = [NSColor blackColor]; |
325 } | 337 } |
326 if (![self isEnabled]) { | 338 if (![self isEnabled]) { |
327 textColor = [textColor colorWithAlphaComponent:0.5]; | 339 textColor = [textColor colorWithAlphaComponent:0.5]; |
328 } | 340 } |
329 NSFont* theFont = [self font]; | 341 NSFont* theFont = [self font]; |
330 if (!theFont) { | 342 if (!theFont) { |
331 theFont = [NSFont systemFontOfSize:kDefaultFontSize]; | 343 theFont = [NSFont systemFontOfSize:kDefaultFontSize]; |
332 } | 344 } |
333 | 345 |
334 return @{ | 346 return @{ |
335 NSFontAttributeName : theFont, | 347 NSFontAttributeName : theFont, |
336 NSForegroundColorAttributeName : textColor, | 348 NSForegroundColorAttributeName : textColor, |
337 NSParagraphStyleAttributeName : style.get(), | 349 NSParagraphStyleAttributeName : style, |
338 NSKernAttributeName : [NSNumber numberWithFloat:0.2] | 350 NSKernAttributeName : [NSNumber numberWithFloat:0.2] |
339 }; | 351 }; |
340 } | 352 } |
341 | 353 |
342 - (NSString*)visibleTitle { | 354 - (NSString*)visibleTitle { |
343 return [self imagePosition] != NSImageOnly ? [self title] : @""; | 355 return [self imagePosition] != NSImageOnly ? [self title] : @""; |
344 } | 356 } |
345 | 357 |
346 // Add extra size for the arrow so it doesn't overlap the text. | 358 // Add extra size for the arrow so it doesn't overlap the text. |
347 // Does not sanity check to be sure this is actually a folder node. | 359 // Does not sanity check to be sure this is actually a folder node. |
348 - (NSSize)cellSize { | 360 - (NSSize)cellSize { |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
434 // In Material Design on Retina, and not in a folder menu, nudge the hover | 446 // In Material Design on Retina, and not in a folder menu, nudge the hover |
435 // background by 1px. | 447 // background by 1px. |
436 const CGFloat kLineWidth = [controlView cr_lineWidth]; | 448 const CGFloat kLineWidth = [controlView cr_lineWidth]; |
437 if ([self isMaterialDesignButtonType] && ![self isFolderButtonCell] && | 449 if ([self isMaterialDesignButtonType] && ![self isFolderButtonCell] && |
438 kLineWidth < 1) { | 450 kLineWidth < 1) { |
439 return -kLineWidth; | 451 return -kLineWidth; |
440 } | 452 } |
441 return 0.0; | 453 return 0.0; |
442 } | 454 } |
443 | 455 |
456 + (NSFont*)fontForBookmarkBarCell { | |
Elly Fong-Jones
2017/03/23 15:40:22
I like this pattern of breaking sorta-constants ou
| |
457 return [NSFont systemFontOfSize:kDefaultFontSize]; | |
458 } | |
459 | |
460 + (NSParagraphStyle*)paragraphStyleForBookmarkBarCell { | |
461 NSMutableParagraphStyle* style = [[NSMutableParagraphStyle alloc] init]; | |
462 [style setAlignment:NSNaturalTextAlignment]; | |
463 [style setLineBreakMode:NSLineBreakByTruncatingTail]; | |
464 return [style autorelease]; | |
465 } | |
466 | |
467 // Returns |title| with newlines and line feeds replaced with | |
468 // spaces. | |
469 + (NSString*)cleanTitle:(NSString*)title { | |
470 title = [title stringByReplacingOccurrencesOfString:@"\n" withString:@" "]; | |
471 title = [title stringByReplacingOccurrencesOfString:@"\r" withString:@" "]; | |
472 return title; | |
473 } | |
444 | 474 |
445 @end | 475 @end |
OLD | NEW |