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/browser/ui/cocoa/l10n_util.h" |
12 #include "chrome/grit/generated_resources.h" | 13 #include "chrome/grit/generated_resources.h" |
13 #import "components/bookmarks/browser/bookmark_model.h" | 14 #import "components/bookmarks/browser/bookmark_model.h" |
14 #include "content/public/browser/user_metrics.h" | 15 #include "content/public/browser/user_metrics.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 }; // namespace | 39 }; // namespace |
39 | 40 |
40 @interface OffTheSideButtonCell : BookmarkButtonCell | 41 @interface OffTheSideButtonCell : BookmarkButtonCell |
41 | 42 |
42 - (NSString*)accessibilityTitle; | 43 - (NSString*)accessibilityTitle; |
43 | 44 |
44 @end | 45 @end |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 | 172 |
172 - (BOOL)isOffTheSideButtonCell { | 173 - (BOOL)isOffTheSideButtonCell { |
173 return NO; | 174 return NO; |
174 } | 175 } |
175 | 176 |
176 // Perform all normal init routines specific to the BookmarkButtonCell. | 177 // Perform all normal init routines specific to the BookmarkButtonCell. |
177 - (void)configureBookmarkButtonCell { | 178 - (void)configureBookmarkButtonCell { |
178 [self setButtonType:NSMomentaryPushInButton]; | 179 [self setButtonType:NSMomentaryPushInButton]; |
179 [self setShowsBorderOnlyWhileMouseInside:YES]; | 180 [self setShowsBorderOnlyWhileMouseInside:YES]; |
180 [self setControlSize:NSSmallControlSize]; | 181 [self setControlSize:NSSmallControlSize]; |
181 [self setAlignment:NSLeftTextAlignment]; | 182 [self setAlignment:NSNaturalTextAlignment]; |
182 [self setFont:[NSFont systemFontOfSize:kDefaultFontSize]]; | 183 [self setFont:[NSFont systemFontOfSize:kDefaultFontSize]]; |
183 [self setBordered:NO]; | 184 [self setBordered:NO]; |
184 [self setBezeled:NO]; | 185 [self setBezeled:NO]; |
185 [self setWraps:NO]; | 186 [self setWraps:NO]; |
186 // NSLineBreakByTruncatingMiddle seems more common on OSX but let's | 187 // NSLineBreakByTruncatingMiddle seems more common on OSX but let's |
187 // try to match Windows for a bit to see what happens. | 188 // try to match Windows for a bit to see what happens. |
188 [self setLineBreakMode:NSLineBreakByTruncatingTail]; | 189 [self setLineBreakMode:NSLineBreakByTruncatingTail]; |
189 | 190 |
190 // The overflow button chevron bitmap is not 16 units high, so it'd be scaled | 191 // The overflow button chevron bitmap is not 16 units high, so it'd be scaled |
191 // at paint time without this. | 192 // at paint time without this. |
(...skipping 21 matching lines...) Expand all Loading... |
213 } | 214 } |
214 | 215 |
215 - (void)setBookmarkCellText:(NSString*)title | 216 - (void)setBookmarkCellText:(NSString*)title |
216 image:(NSImage*)image { | 217 image:(NSImage*)image { |
217 title = [title stringByReplacingOccurrencesOfString:@"\n" | 218 title = [title stringByReplacingOccurrencesOfString:@"\n" |
218 withString:@" "]; | 219 withString:@" "]; |
219 title = [title stringByReplacingOccurrencesOfString:@"\r" | 220 title = [title stringByReplacingOccurrencesOfString:@"\r" |
220 withString:@" "]; | 221 withString:@" "]; |
221 | 222 |
222 if ([title length]) { | 223 if ([title length]) { |
223 [self setImagePosition:NSImageLeft]; | 224 [self setImagePosition:cocoa_l10n_util::LeadingCellImagePosition()]; |
224 [self setTitle:title]; | 225 [self setTitle:title]; |
225 } else if ([self isFolderButtonCell]) { | 226 } else if ([self isFolderButtonCell]) { |
226 // Left-align icons for bookmarks within folders, regardless of whether | 227 // Left-align icons for bookmarks within folders, regardless of whether |
227 // there is a title. | 228 // there is a title. |
228 [self setImagePosition:NSImageLeft]; | 229 [self setImagePosition:cocoa_l10n_util::LeadingCellImagePosition()]; |
229 } else { | 230 } else { |
230 // For bookmarks without a title that aren't visible directly in the | 231 // For bookmarks without a title that aren't visible directly in the |
231 // bookmarks bar, squeeze things tighter by displaying only the image. | 232 // bookmarks bar, squeeze things tighter by displaying only the image. |
232 // By default, Cocoa leaves extra space in an attempt to display an | 233 // By default, Cocoa leaves extra space in an attempt to display an |
233 // empty title. | 234 // empty title. |
234 [self setImagePosition:NSImageOnly]; | 235 [self setImagePosition:NSImageOnly]; |
235 } | 236 } |
236 | 237 |
237 if (image) | 238 if (image) |
238 [self setImage:image]; | 239 [self setImage:image]; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 // See comment above mouseEntered:, above. | 297 // See comment above mouseEntered:, above. |
297 - (void)mouseExited:(NSEvent*)event { | 298 - (void)mouseExited:(NSEvent*)event { |
298 [[self controlView] mouseExited:event]; | 299 [[self controlView] mouseExited:event]; |
299 [super mouseExited:event]; | 300 [super mouseExited:event]; |
300 } | 301 } |
301 | 302 |
302 - (void)setDrawFolderArrow:(BOOL)draw { | 303 - (void)setDrawFolderArrow:(BOOL)draw { |
303 drawFolderArrow_ = draw; | 304 drawFolderArrow_ = draw; |
304 if (draw && !arrowImage_) { | 305 if (draw && !arrowImage_) { |
305 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 306 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
306 arrowImage_.reset( | 307 NSImage* image = |
307 [rb.GetNativeImageNamed(IDR_MENU_HIERARCHY_ARROW).ToNSImage() retain]); | 308 rb.GetNativeImageNamed(IDR_MENU_HIERARCHY_ARROW).ToNSImage(); |
| 309 if (cocoa_l10n_util::ShouldDoExperimentalRTLLayout()) |
| 310 image = cocoa_l10n_util::FlippedImage(image); |
| 311 arrowImage_.reset([image retain]); |
308 } | 312 } |
309 } | 313 } |
310 | 314 |
311 - (NSDictionary*)titleTextAttributes { | 315 - (NSDictionary*)titleTextAttributes { |
312 base::scoped_nsobject<NSMutableParagraphStyle> style( | 316 base::scoped_nsobject<NSMutableParagraphStyle> style( |
313 [NSMutableParagraphStyle new]); | 317 [NSMutableParagraphStyle new]); |
314 [style setAlignment:NSNaturalTextAlignment]; | 318 [style setAlignment:NSNaturalTextAlignment]; |
315 [style setLineBreakMode:NSLineBreakByTruncatingTail]; | 319 [style setLineBreakMode:NSLineBreakByTruncatingTail]; |
316 NSColor* textColor = textColor_.get(); | 320 NSColor* textColor = textColor_.get(); |
317 if (!textColor) { | 321 if (!textColor) { |
(...skipping 18 matching lines...) Expand all Loading... |
336 - (NSString*)visibleTitle { | 340 - (NSString*)visibleTitle { |
337 return [self imagePosition] != NSImageOnly ? [self title] : @""; | 341 return [self imagePosition] != NSImageOnly ? [self title] : @""; |
338 } | 342 } |
339 | 343 |
340 // Add extra size for the arrow so it doesn't overlap the text. | 344 // Add extra size for the arrow so it doesn't overlap the text. |
341 // Does not sanity check to be sure this is actually a folder node. | 345 // Does not sanity check to be sure this is actually a folder node. |
342 - (NSSize)cellSize { | 346 - (NSSize)cellSize { |
343 NSSize cellSize = NSZeroSize; | 347 NSSize cellSize = NSZeroSize; |
344 // Return the space needed to display the image and title, with a little | 348 // Return the space needed to display the image and title, with a little |
345 // distance between them. | 349 // distance between them. |
346 cellSize = NSMakeSize(kIconLeftPadding + [[self image] size].width, | 350 cellSize = NSMakeSize(kIconLeadingPadding + [[self image] size].width, |
347 bookmarks::kBookmarkButtonHeight); | 351 bookmarks::kBookmarkButtonHeight); |
348 NSString* title = [self visibleTitle]; | 352 NSString* title = [self visibleTitle]; |
349 if ([title length] > 0) { | 353 if ([title length] > 0) { |
350 CGFloat textWidth = | 354 CGFloat textWidth = |
351 [title sizeWithAttributes:[self titleTextAttributes]].width; | 355 [title sizeWithAttributes:[self titleTextAttributes]].width; |
352 cellSize.width += | 356 cellSize.width += |
353 kIconTextSpacer + std::ceil(textWidth) + kTextRightPadding; | 357 kIconTextSpacer + std::ceil(textWidth) + kTextTrailingPadding; |
354 } else { | 358 } else { |
355 // Make buttons without visible titles 20pts wide (18 plus padding). | 359 // Make buttons without visible titles 20pts wide (18 plus padding). |
356 cellSize.width += kIconLeftPadding; | 360 cellSize.width += kIconLeadingPadding; |
357 } | 361 } |
358 | 362 |
359 if (drawFolderArrow_) { | 363 if (drawFolderArrow_) { |
360 cellSize.width += [arrowImage_ size].width + | 364 cellSize.width += [arrowImage_ size].width + |
361 kHierarchyButtonLeftPadding + | 365 kHierarchyButtonLeadingPadding + |
362 kHierarchyButtonRightPadding; | 366 kHierarchyButtonTrailingPadding; |
363 } | 367 } |
| 368 cellSize.width += [self insetInView:[self controlView]] * 2; |
364 return cellSize; | 369 return cellSize; |
365 } | 370 } |
366 | 371 |
367 - (NSRect)imageRectForBounds:(NSRect)theRect { | 372 - (NSRect)imageRectForBounds:(NSRect)theRect { |
368 NSRect imageRect = [super imageRectForBounds:theRect]; | 373 NSRect imageRect = [super imageRectForBounds:theRect]; |
369 // Add a little space between the image and the button's left edge, but only | 374 const CGFloat inset = [self insetInView:[self controlView]]; |
370 // if there's a visible title. | 375 imageRect.origin.y -= inset; |
371 imageRect.origin.y -= 1; | 376 imageRect.origin.x = |
372 imageRect.origin.x = kIconLeftPadding; | 377 cocoa_l10n_util::ShouldDoExperimentalRTLLayout() |
| 378 ? NSMaxX(theRect) - kIconLeadingPadding - NSWidth(imageRect) |
| 379 : kIconLeadingPadding + inset; |
373 return imageRect; | 380 return imageRect; |
374 } | 381 } |
375 | 382 |
376 - (CGFloat)textStartXOffset { | 383 - (NSRect)titleRectForBounds:(NSRect)theRect { |
377 return kIconLeftPadding + [[self image] size].width + kIconTextSpacer; | 384 NSRect textRect = [super titleRectForBounds:theRect]; |
| 385 NSRect imageRect = [self imageRectForBounds:theRect]; |
| 386 if (cocoa_l10n_util::ShouldDoExperimentalRTLLayout()) { |
| 387 textRect.origin.x = drawFolderArrow_ |
| 388 ? [arrowImage_ size].width + |
| 389 kHierarchyButtonTrailingPadding + |
| 390 kTextTrailingPadding |
| 391 : kTextTrailingPadding; |
| 392 textRect.origin.x += [self insetInView:[self controlView]]; |
| 393 textRect.size.width = |
| 394 NSMinX(imageRect) - textRect.origin.x - kIconTextSpacer; |
| 395 } else { |
| 396 textRect.origin.x = NSMaxX(imageRect) + kIconTextSpacer; |
| 397 } |
| 398 return textRect; |
378 } | 399 } |
379 | 400 |
380 - (void)drawFocusRingMaskWithFrame:(NSRect)cellFrame | 401 - (void)drawFocusRingMaskWithFrame:(NSRect)cellFrame |
381 inView:(NSView*)controlView { | 402 inView:(NSView*)controlView { |
382 // We have to adjust the focus ring slightly for the chevron and regular | 403 // We have to adjust the focus ring slightly for the chevron and regular |
383 // bookmark icons. | 404 // bookmark icons. |
384 if ([self isOffTheSideButtonCell]) { | 405 if ([self isOffTheSideButtonCell]) { |
385 cellFrame.origin.y -= 2; | 406 cellFrame.origin.y -= 2; |
386 } else if ([self visibleTitle].length > 0) { | 407 } else if ([self visibleTitle].length > 0) { |
387 cellFrame.origin.x += 4; | 408 cellFrame.origin.x += 4; |
(...skipping 11 matching lines...) Expand all Loading... |
399 | 420 |
400 // If asked to do so, and if a folder, draw the arrow. | 421 // If asked to do so, and if a folder, draw the arrow. |
401 if (!drawFolderArrow_) | 422 if (!drawFolderArrow_) |
402 return; | 423 return; |
403 BookmarkButton* button = static_cast<BookmarkButton*>([self controlView]); | 424 BookmarkButton* button = static_cast<BookmarkButton*>([self controlView]); |
404 DCHECK([button respondsToSelector:@selector(isFolder)]); | 425 DCHECK([button respondsToSelector:@selector(isFolder)]); |
405 if ([button isFolder]) { | 426 if ([button isFolder]) { |
406 NSRect imageRect = NSZeroRect; | 427 NSRect imageRect = NSZeroRect; |
407 imageRect.size = [arrowImage_ size]; | 428 imageRect.size = [arrowImage_ size]; |
408 const CGFloat kArrowOffset = 1.0; // Required for proper centering. | 429 const CGFloat kArrowOffset = 1.0; // Required for proper centering. |
409 CGFloat dX = | 430 CGFloat dX = cocoa_l10n_util::ShouldDoExperimentalRTLLayout() |
410 NSWidth(cellFrame) - NSWidth(imageRect) - kHierarchyButtonRightPadding; | 431 ? kHierarchyButtonTrailingPadding |
| 432 : NSWidth(cellFrame) - NSWidth(imageRect) - |
| 433 kHierarchyButtonTrailingPadding; |
411 CGFloat dY = (NSHeight(cellFrame) / 2.0) - (NSHeight(imageRect) / 2.0) + | 434 CGFloat dY = (NSHeight(cellFrame) / 2.0) - (NSHeight(imageRect) / 2.0) + |
412 kArrowOffset; | 435 kArrowOffset; |
413 NSRect drawRect = NSOffsetRect(imageRect, dX, dY); | 436 NSRect drawRect = NSOffsetRect(imageRect, dX, dY); |
414 [arrowImage_ drawInRect:drawRect | 437 [arrowImage_ drawInRect:drawRect |
415 fromRect:imageRect | 438 fromRect:imageRect |
416 operation:NSCompositeSourceOver | 439 operation:NSCompositeSourceOver |
417 fraction:[self isEnabled] ? 1.0 : 0.5 | 440 fraction:[self isEnabled] ? 1.0 : 0.5 |
418 respectFlipped:YES | 441 respectFlipped:YES |
419 hints:nil]; | 442 hints:nil]; |
420 } | 443 } |
421 } | 444 } |
422 | 445 |
423 - (int)verticalTextOffset { | 446 - (int)verticalTextOffset { |
424 return -1; | 447 return -1; |
425 } | 448 } |
426 | 449 |
427 - (CGFloat)hoverBackgroundVerticalOffsetInControlView:(NSView*)controlView { | 450 - (CGFloat)hoverBackgroundVerticalOffsetInControlView:(NSView*)controlView { |
428 // In Material Design on Retina, and not in a folder menu, nudge the hover | 451 // In Material Design on Retina, and not in a folder menu, nudge the hover |
429 // background by 1px. | 452 // background by 1px. |
430 const CGFloat kLineWidth = [controlView cr_lineWidth]; | 453 const CGFloat kLineWidth = [controlView cr_lineWidth]; |
431 if ([self isMaterialDesignButtonType] && ![self isFolderButtonCell] && | 454 if ([self isMaterialDesignButtonType] && ![self isFolderButtonCell] && |
432 kLineWidth < 1) { | 455 kLineWidth < 1) { |
433 return -kLineWidth; | 456 return -kLineWidth; |
434 } | 457 } |
435 return 0.0; | 458 return 0.0; |
436 } | 459 } |
437 | 460 |
438 | 461 |
439 @end | 462 @end |
OLD | NEW |