Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: chrome/browser/ui/cocoa/gradient_button_cell.mm

Issue 1986963004: Revert of [Mac][Material Design] Update bookmarks bar to Material Design. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/ui/cocoa/gradient_button_cell.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 #include "chrome/browser/ui/cocoa/gradient_button_cell.h" 5 #include "chrome/browser/ui/cocoa/gradient_button_cell.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #import "base/mac/scoped_nsobject.h" 10 #import "base/mac/scoped_nsobject.h"
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 YES : NO; 199 YES : NO;
200 } 200 }
201 201
202 #if 1 202 #if 1
203 // If we are not continuously pulsing, perform a pulse animation to 203 // If we are not continuously pulsing, perform a pulse animation to
204 // reflect our new state. 204 // reflect our new state.
205 - (void)setMouseInside:(BOOL)flag animate:(BOOL)animated { 205 - (void)setMouseInside:(BOOL)flag animate:(BOOL)animated {
206 isMouseInside_ = flag; 206 isMouseInside_ = flag;
207 if (pulseState_ != gradient_button_cell::kPulsingContinuous) { 207 if (pulseState_ != gradient_button_cell::kPulsingContinuous) {
208 if (animated) { 208 if (animated) {
209 // In Material Design, if the button is already fully on, don't pulse it
210 // on again if the mouse is within its bounds.
211 if ([self tag] == kMaterialStandardButtonTypeWithLimitedClickFeedback &&
212 isMouseInside_ && pulseState_ == gradient_button_cell::kPulsedOn) {
213 return;
214 }
215
216 [self setPulseState:(isMouseInside_ ? gradient_button_cell::kPulsingOn : 209 [self setPulseState:(isMouseInside_ ? gradient_button_cell::kPulsingOn :
217 gradient_button_cell::kPulsingOff)]; 210 gradient_button_cell::kPulsingOff)];
218 } else { 211 } else {
219 [self setPulseState:(isMouseInside_ ? gradient_button_cell::kPulsedOn : 212 [self setPulseState:(isMouseInside_ ? gradient_button_cell::kPulsedOn :
220 gradient_button_cell::kPulsedOff)]; 213 gradient_button_cell::kPulsedOff)];
221 } 214 }
222 } 215 }
223 } 216 }
224 #else 217 #else
225 218
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 } 312 }
320 313
321 - (void)mouseExited:(NSEvent*)theEvent { 314 - (void)mouseExited:(NSEvent*)theEvent {
322 [self setMouseInside:NO animate:YES]; 315 [self setMouseInside:NO animate:YES];
323 } 316 }
324 317
325 - (BOOL)isMouseInside { 318 - (BOOL)isMouseInside {
326 return trackingArea_ && isMouseInside_; 319 return trackingArea_ && isMouseInside_;
327 } 320 }
328 321
329 - (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView {
330 if ([self tag] == kMaterialStandardButtonTypeWithLimitedClickFeedback) {
331 // The user has just clicked down in the button. In Material Design, set the
332 // pulsed (hover) state to off now so that if the user keeps the mouse held
333 // down while dragging it out of the button's bounds, the button will draw
334 // itself in its normal state. This is unrelated to dragging the button
335 // in the button bar, which takes a different path through the code.
336 [self setPulseState:gradient_button_cell::kPulsedOff];
337 }
338
339 return [super startTrackingAt:startPoint inView:controlView];
340 }
341
342 // Since we have our own drawWithFrame:, we need to also have our own 322 // Since we have our own drawWithFrame:, we need to also have our own
343 // logic for determining when the mouse is inside for honoring this 323 // logic for determining when the mouse is inside for honoring this
344 // request. 324 // request.
345 - (void)setShowsBorderOnlyWhileMouseInside:(BOOL)showOnly { 325 - (void)setShowsBorderOnlyWhileMouseInside:(BOOL)showOnly {
346 [super setShowsBorderOnlyWhileMouseInside:showOnly]; 326 [super setShowsBorderOnlyWhileMouseInside:showOnly];
347 if (showOnly) { 327 if (showOnly) {
348 [self updateTrackingAreas]; 328 [self updateTrackingAreas];
349 } else { 329 } else {
350 if (trackingArea_) { 330 if (trackingArea_) {
351 [[self controlView] removeTrackingArea:trackingArea_]; 331 [[self controlView] removeTrackingArea:trackingArea_];
352 trackingArea_.reset(nil); 332 trackingArea_.reset(nil);
353 if (isMouseInside_) { 333 if (isMouseInside_) {
354 isMouseInside_ = NO; 334 isMouseInside_ = NO;
355 [[self controlView] setNeedsDisplay:YES]; 335 [[self controlView] setNeedsDisplay:YES];
356 } 336 }
357 } 337 }
358 } 338 }
359 } 339 }
360 340
361 // TODO(viettrungluu): clean up/reorganize. 341 // TODO(viettrungluu): clean up/reorganize.
362 - (void)drawBorderAndFillForTheme:(const ui::ThemeProvider*)themeProvider 342 - (void)drawBorderAndFillForTheme:(const ui::ThemeProvider*)themeProvider
363 controlView:(NSView*)controlView 343 controlView:(NSView*)controlView
364 innerPath:(NSBezierPath*)innerPath 344 innerPath:(NSBezierPath*)innerPath
365 showClickedGradient:(BOOL)showClickedGradient 345 showClickedGradient:(BOOL)showClickedGradient
366 showHighlightGradient:(BOOL)showHighlightGradient 346 showHighlightGradient:(BOOL)showHighlightGradient
367 hoverAlpha:(CGFloat)hoverAlpha 347 hoverAlpha:(CGFloat)hoverAlpha
368 active:(BOOL)active 348 active:(BOOL)active
369 cellFrame:(NSRect)cellFrame 349 cellFrame:(NSRect)cellFrame
370 defaultGradient:(NSGradient*)defaultGradient { 350 defaultGradient:(NSGradient*)defaultGradient {
371 // For Material Design, draw a solid rounded rect behind the button, based on
372 // the hover and pressed states.
373 if ([self tag] == kMaterialStandardButtonTypeWithLimitedClickFeedback) {
374 const CGFloat kEightPercentAlpha = 0.08;
375 const CGFloat kFourPercentAlpha = 0.04;
376
377 // The alpha is always at least 8%. Default the color to black.
378 CGFloat alpha = kEightPercentAlpha;
379 CGFloat color = 0.0;
380 // If a dark theme, incrase the opacity slightly and use white.
381 if ([[controlView window] hasDarkTheme]) {
382 alpha += kFourPercentAlpha;
383 color = 1.0;
384 }
385 // If clicked or highlighted, the background is slightly more opaque. If not
386 // clicked or highlighted, adjust the alpha by the animation fade in
387 // percentage.
388 if (showClickedGradient || showHighlightGradient) {
389 alpha += kFourPercentAlpha;
390 } else {
391 alpha *= hoverAlpha;
392 }
393
394 // Fill the path.
395 [[NSColor colorWithCalibratedWhite:color alpha:alpha] set];
396 [innerPath fill];
397 return;
398 }
399
400 BOOL isFlatButton = [self showsBorderOnlyWhileMouseInside]; 351 BOOL isFlatButton = [self showsBorderOnlyWhileMouseInside];
401 352
402 // For flat (unbordered when not hovered) buttons, never use the toolbar 353 // For flat (unbordered when not hovered) buttons, never use the toolbar
403 // button background image, but the modest gradient used for themed buttons. 354 // button background image, but the modest gradient used for themed buttons.
404 // To make things even more modest, scale the hover alpha down by 40 percent 355 // To make things even more modest, scale the hover alpha down by 40 percent
405 // unless clicked. 356 // unless clicked.
406 NSColor* backgroundImageColor; 357 NSColor* backgroundImageColor;
407 BOOL useThemeGradient; 358 BOOL useThemeGradient;
408 if (isFlatButton) { 359 if (isFlatButton) {
409 backgroundImageColor = nil; 360 backgroundImageColor = nil;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 [innerPath stroke]; 454 [innerPath stroke];
504 } 455 }
505 456
506 // TODO(viettrungluu): clean this up. 457 // TODO(viettrungluu): clean this up.
507 // (Private) 458 // (Private)
508 - (void)getDrawParamsForFrame:(NSRect)cellFrame 459 - (void)getDrawParamsForFrame:(NSRect)cellFrame
509 inView:(NSView*)controlView 460 inView:(NSView*)controlView
510 innerFrame:(NSRect*)returnInnerFrame 461 innerFrame:(NSRect*)returnInnerFrame
511 innerPath:(NSBezierPath**)returnInnerPath 462 innerPath:(NSBezierPath**)returnInnerPath
512 clipPath:(NSBezierPath**)returnClipPath { 463 clipPath:(NSBezierPath**)returnClipPath {
513 const CGFloat kLineWidth = [controlView cr_lineWidth]; 464 const CGFloat lineWidth = [controlView cr_lineWidth];
514 const CGFloat kHalfLineWidth = kLineWidth / 2.0; 465 const CGFloat halfLineWidth = lineWidth / 2.0;
515 466
516 NSRect drawFrame = cellFrame; 467 // Constants from Cole. Will kConstant them once the feedback loop
517 NSRect innerFrame = NSInsetRect(cellFrame, kLineWidth, kLineWidth); 468 // is complete.
518 CGFloat cornerRadius = 2; 469 NSRect drawFrame = NSInsetRect(cellFrame, 1.5 * lineWidth, 1.5 * lineWidth);
519 if ([self tag] != kMaterialStandardButtonTypeWithLimitedClickFeedback) { 470 NSRect innerFrame = NSInsetRect(cellFrame, lineWidth, lineWidth);
520 drawFrame = NSInsetRect(cellFrame, 1.5 * kLineWidth, 1.5 * kLineWidth); 471 const CGFloat radius = 3;
521 cornerRadius = 3;
522 }
523 472
524 ButtonType type = [[(NSControl*)controlView cell] tag]; 473 ButtonType type = [[(NSControl*)controlView cell] tag];
525 switch (type) { 474 switch (type) {
526 case kMiddleButtonType: 475 case kMiddleButtonType:
527 drawFrame.size.width += 20; 476 drawFrame.size.width += 20;
528 innerFrame.size.width += 2; 477 innerFrame.size.width += 2;
529 // Fallthrough 478 // Fallthrough
530 case kRightButtonType: 479 case kRightButtonType:
531 drawFrame.origin.x -= 20; 480 drawFrame.origin.x -= 20;
532 innerFrame.origin.x -= 2; 481 innerFrame.origin.x -= 2;
533 // Fallthrough 482 // Fallthrough
534 case kLeftButtonType: 483 case kLeftButtonType:
535 case kLeftButtonWithShadowType: 484 case kLeftButtonWithShadowType:
536 drawFrame.size.width += 20; 485 drawFrame.size.width += 20;
537 innerFrame.size.width += 2; 486 innerFrame.size.width += 2;
538 default: 487 default:
539 break; 488 break;
540 } 489 }
541 if (type == kLeftButtonWithShadowType) 490 if (type == kLeftButtonWithShadowType)
542 innerFrame.size.width -= 1.0; 491 innerFrame.size.width -= 1.0;
543 492
544 // Return results if |return...| not null. 493 // Return results if |return...| not null.
545 if (returnInnerFrame) 494 if (returnInnerFrame)
546 *returnInnerFrame = innerFrame; 495 *returnInnerFrame = innerFrame;
547 if (returnInnerPath) { 496 if (returnInnerPath) {
548 DCHECK(*returnInnerPath == nil); 497 DCHECK(*returnInnerPath == nil);
549 *returnInnerPath = [NSBezierPath bezierPathWithRoundedRect:drawFrame 498 *returnInnerPath = [NSBezierPath bezierPathWithRoundedRect:drawFrame
550 xRadius:cornerRadius 499 xRadius:radius
551 yRadius:cornerRadius]; 500 yRadius:radius];
552 [*returnInnerPath setLineWidth:kLineWidth]; 501 [*returnInnerPath setLineWidth:lineWidth];
553 } 502 }
554 if (returnClipPath) { 503 if (returnClipPath) {
555 DCHECK(*returnClipPath == nil); 504 DCHECK(*returnClipPath == nil);
556 NSRect clipPathRect = 505 NSRect clipPathRect =
557 NSInsetRect(drawFrame, -kHalfLineWidth, -kHalfLineWidth); 506 NSInsetRect(drawFrame, -halfLineWidth, -halfLineWidth);
558 *returnClipPath = [NSBezierPath 507 *returnClipPath = [NSBezierPath
559 bezierPathWithRoundedRect:clipPathRect 508 bezierPathWithRoundedRect:clipPathRect
560 xRadius:cornerRadius + kHalfLineWidth 509 xRadius:radius + halfLineWidth
561 yRadius:cornerRadius + kHalfLineWidth]; 510 yRadius:radius + halfLineWidth];
562 } 511 }
563 } 512 }
564 513
565 // TODO(viettrungluu): clean this up. 514 // TODO(viettrungluu): clean this up.
566 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { 515 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
567 NSRect innerFrame; 516 NSRect innerFrame;
568 NSBezierPath* innerPath = nil; 517 NSBezierPath* innerPath = nil;
569 [self getDrawParamsForFrame:cellFrame 518 [self getDrawParamsForFrame:cellFrame
570 inView:controlView 519 inView:controlView
571 innerFrame:&innerFrame 520 innerFrame:&innerFrame
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 ThemeProperties::COLOR_TOOLBAR_BUTTON_STROKE_INACTIVE) : 558 ThemeProperties::COLOR_TOOLBAR_BUTTON_STROKE_INACTIVE) :
610 [NSColor blackColor]; 559 [NSColor blackColor];
611 560
612 [[stroke colorWithAlphaComponent:0.2] set]; 561 [[stroke colorWithAlphaComponent:0.2] set];
613 NSRectFillUsingOperation(NSInsetRect(borderRect, 0, 2), 562 NSRectFillUsingOperation(NSInsetRect(borderRect, 0, 2),
614 NSCompositeSourceOver); 563 NSCompositeSourceOver);
615 } 564 }
616 [self drawInteriorWithFrame:innerFrame inView:controlView]; 565 [self drawInteriorWithFrame:innerFrame inView:controlView];
617 } 566 }
618 567
619 - (CGFloat)textStartXOffset {
620 // 11 is the magic number needed to make this match the native
621 // NSButtonCell's label display.
622 return [[self image] size].width + 11;
623 }
624
625 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { 568 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
626 const CGFloat lineWidth = [controlView cr_lineWidth]; 569 const CGFloat lineWidth = [controlView cr_lineWidth];
627 570
628 if (shouldTheme_) { 571 if (shouldTheme_) {
629 BOOL isTemplate = [[self image] isTemplate]; 572 BOOL isTemplate = [[self image] isTemplate];
630 573
631 gfx::ScopedNSGraphicsContextSaveGState scopedGState; 574 gfx::ScopedNSGraphicsContextSaveGState scopedGState;
632 575
633 CGContextRef context = 576 CGContextRef context =
634 (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]); 577 (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
695 // get it to work with NSButtonCell. 638 // get it to work with NSButtonCell.
696 // TODO(jeremy): Move this to GTM. 639 // TODO(jeremy): Move this to GTM.
697 - (NSRect)drawTitle:(NSAttributedString*)title 640 - (NSRect)drawTitle:(NSAttributedString*)title
698 withFrame:(NSRect)cellFrame 641 withFrame:(NSRect)cellFrame
699 inView:(NSView*)controlView { 642 inView:(NSView*)controlView {
700 NSSize size = [title size]; 643 NSSize size = [title size];
701 644
702 // Empirically, Cocoa will draw an extra 2 pixels past NSWidth(cellFrame) 645 // Empirically, Cocoa will draw an extra 2 pixels past NSWidth(cellFrame)
703 // before it clips the text. 646 // before it clips the text.
704 const CGFloat kOverflowBeforeClip = 2; 647 const CGFloat kOverflowBeforeClip = 2;
705 BOOL isModeMaterial = 648 BOOL clipping = YES;
706 [self tag] == kMaterialStandardButtonTypeWithLimitedClickFeedback;
707 // For Material Design we don't want to clip the text. For all other button
708 // cell modes, we do.
709 BOOL shouldClipTheTitle = !isModeMaterial;
710 if (std::floor(size.width) <= (NSWidth(cellFrame) + kOverflowBeforeClip)) { 649 if (std::floor(size.width) <= (NSWidth(cellFrame) + kOverflowBeforeClip)) {
711 cellFrame.origin.y += ([self verticalTextOffset] - 1); 650 cellFrame.origin.y += ([self verticalTextOffset] - 1);
712 shouldClipTheTitle = NO; 651 clipping = NO;
713 } 652 }
714 653
715 // Gradient is about twice our line height long. 654 // Gradient is about twice our line height long.
716 CGFloat gradientWidth = MIN(size.height * 2, NSWidth(cellFrame) / 4); 655 CGFloat gradientWidth = MIN(size.height * 2, NSWidth(cellFrame) / 4);
717 656
718 NSRect solidPart, gradientPart; 657 NSRect solidPart, gradientPart;
719 NSDivideRect(cellFrame, &gradientPart, &solidPart, gradientWidth, NSMaxXEdge); 658 NSDivideRect(cellFrame, &gradientPart, &solidPart, gradientWidth, NSMaxXEdge);
720 659
721 // Draw non-gradient part without transparency layer, as light text on a dark 660 // Draw non-gradient part without transparency layer, as light text on a dark
722 // background looks bad with a gradient layer. 661 // background looks bad with a gradient layer.
723 NSPoint textOffset = NSZeroPoint; 662 NSPoint textOffset = NSZeroPoint;
724 { 663 {
725 gfx::ScopedNSGraphicsContextSaveGState scopedGState; 664 gfx::ScopedNSGraphicsContextSaveGState scopedGState;
726 if (shouldClipTheTitle) 665 if (clipping)
727 [NSBezierPath clipRect:solidPart]; 666 [NSBezierPath clipRect:solidPart];
728 667
729 CGFloat textLeft = [self textStartXOffset]; 668 // 11 is the magic number needed to make this match the native
669 // NSButtonCell's label display.
670 CGFloat textLeft = [[self image] size].width + 11;
730 671
731 // For some reason, the height of cellFrame as passed in is totally bogus. 672 // For some reason, the height of cellFrame as passed in is totally bogus.
732 // For vertical centering purposes, we need the bounds of the containing 673 // For vertical centering purposes, we need the bounds of the containing
733 // view. 674 // view.
734 NSRect buttonFrame = [[self controlView] frame]; 675 NSRect buttonFrame = [[self controlView] frame];
735 676
736 // Call the vertical offset to match native NSButtonCell's version. 677 // Call the vertical offset to match native NSButtonCell's version.
737 textOffset = NSMakePoint(textLeft, 678 textOffset = NSMakePoint(textLeft,
738 (NSHeight(buttonFrame) - size.height) / 2 + 679 (NSHeight(buttonFrame) - size.height) / 2 +
739 [self verticalTextOffset]); 680 [self verticalTextOffset]);
740 // WIth Material Design we want an ellipsis if the title is too long to fit, 681 [title drawAtPoint:textOffset];
741 // so have to use drawInRect: instead of drawAtPoint:.
742 if (isModeMaterial) {
743 NSRect textBounds = NSMakeRect(textOffset.x,
744 textOffset.y,
745 NSWidth(buttonFrame) - textOffset.x,
746 NSHeight(buttonFrame));
747 [title drawInRect:textBounds];
748 } else {
749 [title drawAtPoint:textOffset];
750 }
751 } 682 }
752 683
753 if (!shouldClipTheTitle) 684 if (!clipping)
754 return cellFrame; 685 return cellFrame;
755 686
756 // Draw the gradient part with a transparency layer. This makes the text look 687 // Draw the gradient part with a transparency layer. This makes the text look
757 // suboptimal, but since it fades out, that's ok. 688 // suboptimal, but since it fades out, that's ok.
758 gfx::ScopedNSGraphicsContextSaveGState scopedGState; 689 gfx::ScopedNSGraphicsContextSaveGState scopedGState;
759 [NSBezierPath clipRect:gradientPart]; 690 [NSBezierPath clipRect:gradientPart];
760 CGContextRef context = static_cast<CGContextRef>( 691 CGContextRef context = static_cast<CGContextRef>(
761 [[NSGraphicsContext currentContext] graphicsPort]); 692 [[NSGraphicsContext currentContext] graphicsPort]);
762 CGContextBeginTransparencyLayerWithRect(context, 693 CGContextBeginTransparencyLayerWithRect(context,
763 NSRectToCGRect(gradientPart), 0); 694 NSRectToCGRect(gradientPart), 0);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
828 options:options 759 options:options
829 owner:self 760 owner:self
830 userInfo:nil]); 761 userInfo:nil]);
831 if (isMouseInside_ != mouseInView) { 762 if (isMouseInside_ != mouseInView) {
832 [self setMouseInside:mouseInView animate:NO]; 763 [self setMouseInside:mouseInView animate:NO];
833 [controlView setNeedsDisplay:YES]; 764 [controlView setNeedsDisplay:YES];
834 } 765 }
835 } 766 }
836 767
837 @end 768 @end
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/gradient_button_cell.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698