| OLD | NEW |
| 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 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 | 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. | 210 // on again if the mouse is within its bounds. |
| 211 if ([self tag] == kMaterialStandardButtonTypeWithLimitedClickFeedback && | 211 if ([self tag] == [self isMaterialDesignButtonType] && |
| 212 isMouseInside_ && pulseState_ == gradient_button_cell::kPulsedOn) { | 212 isMouseInside_ && pulseState_ == gradient_button_cell::kPulsedOn) { |
| 213 return; | 213 return; |
| 214 } | 214 } |
| 215 | 215 |
| 216 [self setPulseState:(isMouseInside_ ? gradient_button_cell::kPulsingOn : | 216 [self setPulseState:(isMouseInside_ ? gradient_button_cell::kPulsingOn : |
| 217 gradient_button_cell::kPulsingOff)]; | 217 gradient_button_cell::kPulsingOff)]; |
| 218 } else { | 218 } else { |
| 219 [self setPulseState:(isMouseInside_ ? gradient_button_cell::kPulsedOn : | 219 [self setPulseState:(isMouseInside_ ? gradient_button_cell::kPulsedOn : |
| 220 gradient_button_cell::kPulsedOff)]; | 220 gradient_button_cell::kPulsedOff)]; |
| 221 } | 221 } |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 | 320 |
| 321 - (void)mouseExited:(NSEvent*)theEvent { | 321 - (void)mouseExited:(NSEvent*)theEvent { |
| 322 [self setMouseInside:NO animate:YES]; | 322 [self setMouseInside:NO animate:YES]; |
| 323 } | 323 } |
| 324 | 324 |
| 325 - (BOOL)isMouseInside { | 325 - (BOOL)isMouseInside { |
| 326 return trackingArea_ && isMouseInside_; | 326 return trackingArea_ && isMouseInside_; |
| 327 } | 327 } |
| 328 | 328 |
| 329 - (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView { | 329 - (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView { |
| 330 if ([self tag] == kMaterialStandardButtonTypeWithLimitedClickFeedback) { | 330 if ([self isMaterialDesignButtonType]) { |
| 331 // The user has just clicked down in the button. In Material Design, set the | 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 | 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 | 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 | 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. | 335 // in the button bar, which takes a different path through the code. |
| 336 [self setPulseState:gradient_button_cell::kPulsedOff]; | 336 [self setPulseState:gradient_button_cell::kPulsedOff]; |
| 337 } | 337 } |
| 338 | 338 |
| 339 return [super startTrackingAt:startPoint inView:controlView]; | 339 return [super startTrackingAt:startPoint inView:controlView]; |
| 340 } | 340 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 363 controlView:(NSView*)controlView | 363 controlView:(NSView*)controlView |
| 364 innerPath:(NSBezierPath*)innerPath | 364 innerPath:(NSBezierPath*)innerPath |
| 365 showClickedGradient:(BOOL)showClickedGradient | 365 showClickedGradient:(BOOL)showClickedGradient |
| 366 showHighlightGradient:(BOOL)showHighlightGradient | 366 showHighlightGradient:(BOOL)showHighlightGradient |
| 367 hoverAlpha:(CGFloat)hoverAlpha | 367 hoverAlpha:(CGFloat)hoverAlpha |
| 368 active:(BOOL)active | 368 active:(BOOL)active |
| 369 cellFrame:(NSRect)cellFrame | 369 cellFrame:(NSRect)cellFrame |
| 370 defaultGradient:(NSGradient*)defaultGradient { | 370 defaultGradient:(NSGradient*)defaultGradient { |
| 371 // For Material Design, draw a solid rounded rect behind the button, based on | 371 // For Material Design, draw a solid rounded rect behind the button, based on |
| 372 // the hover and pressed states. | 372 // the hover and pressed states. |
| 373 if ([self tag] == kMaterialStandardButtonTypeWithLimitedClickFeedback) { | 373 if ([self isMaterialDesignButtonType]) { |
| 374 const CGFloat kEightPercentAlpha = 0.08; | 374 const CGFloat kEightPercentAlpha = 0.08; |
| 375 const CGFloat kFourPercentAlpha = 0.04; | 375 const CGFloat kFourPercentAlpha = 0.04; |
| 376 | 376 |
| 377 // The alpha is always at least 8%. Default the color to black. | 377 // The alpha is always at least 8%. Default the color to black. |
| 378 CGFloat alpha = kEightPercentAlpha; | 378 CGFloat alpha = kEightPercentAlpha; |
| 379 CGFloat color = 0.0; | 379 CGFloat color = 0.0; |
| 380 | 380 |
| 381 // If a dark theme, increase the opacity slightly and use white. | 381 // If a dark theme, increase the opacity slightly and use white. |
| 382 if ([[controlView window] hasDarkTheme]) { | 382 if ([[controlView window] hasDarkTheme]) { |
| 383 alpha += kFourPercentAlpha; | 383 alpha += kFourPercentAlpha; |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 inView:(NSView*)controlView | 510 inView:(NSView*)controlView |
| 511 innerFrame:(NSRect*)returnInnerFrame | 511 innerFrame:(NSRect*)returnInnerFrame |
| 512 innerPath:(NSBezierPath**)returnInnerPath | 512 innerPath:(NSBezierPath**)returnInnerPath |
| 513 clipPath:(NSBezierPath**)returnClipPath { | 513 clipPath:(NSBezierPath**)returnClipPath { |
| 514 const CGFloat kLineWidth = [controlView cr_lineWidth]; | 514 const CGFloat kLineWidth = [controlView cr_lineWidth]; |
| 515 const CGFloat kHalfLineWidth = kLineWidth / 2.0; | 515 const CGFloat kHalfLineWidth = kLineWidth / 2.0; |
| 516 | 516 |
| 517 NSRect drawFrame = NSZeroRect; | 517 NSRect drawFrame = NSZeroRect; |
| 518 NSRect innerFrame = NSZeroRect; | 518 NSRect innerFrame = NSZeroRect; |
| 519 CGFloat cornerRadius = 2; | 519 CGFloat cornerRadius = 2; |
| 520 if ([self tag] != kMaterialStandardButtonTypeWithLimitedClickFeedback) { | 520 if (![self isMaterialDesignButtonType]) { |
| 521 drawFrame = NSInsetRect(cellFrame, 1.5 * kLineWidth, 1.5 * kLineWidth); | 521 drawFrame = NSInsetRect(cellFrame, 1.5 * kLineWidth, 1.5 * kLineWidth); |
| 522 innerFrame = NSInsetRect(cellFrame, kLineWidth, kLineWidth); | 522 innerFrame = NSInsetRect(cellFrame, kLineWidth, kLineWidth); |
| 523 cornerRadius = 3; | 523 cornerRadius = 3; |
| 524 } else { | 524 } else { |
| 525 drawFrame = cellFrame; | 525 drawFrame = cellFrame; |
| 526 // Hover and click paths are always 20pt tall, regardless of the button's | 526 // Hover and click paths are always 20pt tall, regardless of the button's |
| 527 // height. | 527 // height. |
| 528 drawFrame.size.height = 20; | 528 drawFrame.size.height = 20; |
| 529 innerFrame = NSInsetRect(drawFrame, kLineWidth, kLineWidth); | 529 innerFrame = NSInsetRect(drawFrame, kLineWidth, kLineWidth); |
| 530 } | 530 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 550 innerFrame.size.width -= 1.0; | 550 innerFrame.size.width -= 1.0; |
| 551 | 551 |
| 552 // Return results if |return...| not null. | 552 // Return results if |return...| not null. |
| 553 if (returnInnerFrame) | 553 if (returnInnerFrame) |
| 554 *returnInnerFrame = innerFrame; | 554 *returnInnerFrame = innerFrame; |
| 555 if (returnInnerPath) { | 555 if (returnInnerPath) { |
| 556 DCHECK(*returnInnerPath == nil); | 556 DCHECK(*returnInnerPath == nil); |
| 557 drawFrame.origin.y += | 557 drawFrame.origin.y += |
| 558 [self hoverBackgroundVerticalOffsetInControlView:controlView]; | 558 [self hoverBackgroundVerticalOffsetInControlView:controlView]; |
| 559 | 559 |
| 560 *returnInnerPath = [NSBezierPath bezierPathWithRoundedRect:drawFrame | 560 if ([self tag] == kMaterialMenuButtonTypeWithLimitedClickFeedback) { |
| 561 xRadius:cornerRadius | 561 *returnInnerPath = [NSBezierPath bezierPathWithRect:drawFrame]; |
| 562 yRadius:cornerRadius]; | 562 } else { |
| 563 *returnInnerPath = [NSBezierPath bezierPathWithRoundedRect:drawFrame |
| 564 xRadius:cornerRadius |
| 565 yRadius:cornerRadius]; |
| 566 } |
| 563 [*returnInnerPath setLineWidth:kLineWidth]; | 567 [*returnInnerPath setLineWidth:kLineWidth]; |
| 564 } | 568 } |
| 565 if (returnClipPath) { | 569 if (returnClipPath) { |
| 566 DCHECK(*returnClipPath == nil); | 570 DCHECK(*returnClipPath == nil); |
| 567 NSRect clipPathRect = | 571 NSRect clipPathRect = |
| 568 NSInsetRect(drawFrame, -kHalfLineWidth, -kHalfLineWidth); | 572 NSInsetRect(drawFrame, -kHalfLineWidth, -kHalfLineWidth); |
| 569 *returnClipPath = [NSBezierPath | 573 *returnClipPath = [NSBezierPath |
| 570 bezierPathWithRoundedRect:clipPathRect | 574 bezierPathWithRoundedRect:clipPathRect |
| 571 xRadius:cornerRadius + kHalfLineWidth | 575 xRadius:cornerRadius + kHalfLineWidth |
| 572 yRadius:cornerRadius + kHalfLineWidth]; | 576 yRadius:cornerRadius + kHalfLineWidth]; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 588 NSWindow* window = [controlView window]; | 592 NSWindow* window = [controlView window]; |
| 589 const ui::ThemeProvider* themeProvider = [window themeProvider]; | 593 const ui::ThemeProvider* themeProvider = [window themeProvider]; |
| 590 BOOL active = [window isKeyWindow] || [window isMainWindow]; | 594 BOOL active = [window isKeyWindow] || [window isMainWindow]; |
| 591 | 595 |
| 592 // Stroke the borders and appropriate fill gradient. If we're borderless, the | 596 // Stroke the borders and appropriate fill gradient. If we're borderless, the |
| 593 // only time we want to draw the inner gradient is if we're highlighted or if | 597 // only time we want to draw the inner gradient is if we're highlighted or if |
| 594 // we're drawing the focus ring manually. In Material Design, the "border" is | 598 // we're drawing the focus ring manually. In Material Design, the "border" is |
| 595 // actually a highlight, which should be drawn if | 599 // actually a highlight, which should be drawn if |
| 596 // |showsBorderOnlyWhileMouseInside| is true. | 600 // |showsBorderOnlyWhileMouseInside| is true. |
| 597 BOOL hasMaterialHighlight = | 601 BOOL hasMaterialHighlight = |
| 598 [self tag] == kMaterialStandardButtonTypeWithLimitedClickFeedback && | 602 [self isMaterialDesignButtonType] && |
| 599 ![self showsBorderOnlyWhileMouseInside] && | 603 ![self showsBorderOnlyWhileMouseInside] && |
| 600 enabled; | 604 enabled; |
| 601 if (([self isBordered] && ![self showsBorderOnlyWhileMouseInside]) || | 605 if (([self isBordered] && ![self showsBorderOnlyWhileMouseInside]) || |
| 602 pressed || [self isMouseInside] || [self isContinuousPulsing] || | 606 pressed || [self isMouseInside] || [self isContinuousPulsing] || |
| 603 hasMaterialHighlight) { | 607 hasMaterialHighlight) { |
| 604 // When pulsing we want the bookmark to stand out a little more. | 608 // When pulsing we want the bookmark to stand out a little more. |
| 605 BOOL showClickedGradient = pressed || | 609 BOOL showClickedGradient = pressed || |
| 606 (pulseState_ == gradient_button_cell::kPulsingContinuous); | 610 (pulseState_ == gradient_button_cell::kPulsingContinuous); |
| 607 BOOL showHighlightGradient = [self isHighlighted] || hasMaterialHighlight; | 611 BOOL showHighlightGradient = [self isHighlighted] || hasMaterialHighlight; |
| 608 | 612 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 } | 706 } |
| 703 | 707 |
| 704 - (int)verticalTextOffset { | 708 - (int)verticalTextOffset { |
| 705 return 1; | 709 return 1; |
| 706 } | 710 } |
| 707 | 711 |
| 708 - (CGFloat)hoverBackgroundVerticalOffsetInControlView:(NSView*)controlView { | 712 - (CGFloat)hoverBackgroundVerticalOffsetInControlView:(NSView*)controlView { |
| 709 return 0.0; | 713 return 0.0; |
| 710 } | 714 } |
| 711 | 715 |
| 716 - (BOOL)isMaterialDesignButtonType { |
| 717 return [self tag] == kMaterialStandardButtonTypeWithLimitedClickFeedback || |
| 718 [self tag] == kMaterialMenuButtonTypeWithLimitedClickFeedback; |
| 719 } |
| 720 |
| 712 // Overriden from NSButtonCell so we can display a nice fadeout effect for | 721 // Overriden from NSButtonCell so we can display a nice fadeout effect for |
| 713 // button titles that overflow. | 722 // button titles that overflow. |
| 714 // This method is copied in the most part from GTMFadeTruncatingTextFieldCell, | 723 // This method is copied in the most part from GTMFadeTruncatingTextFieldCell, |
| 715 // the only difference is that here we draw the text ourselves rather than | 724 // the only difference is that here we draw the text ourselves rather than |
| 716 // calling the super to do the work. | 725 // calling the super to do the work. |
| 717 // We can't use GTMFadeTruncatingTextFieldCell because there's no easy way to | 726 // We can't use GTMFadeTruncatingTextFieldCell because there's no easy way to |
| 718 // get it to work with NSButtonCell. | 727 // get it to work with NSButtonCell. |
| 719 // TODO(jeremy): Move this to GTM. | 728 // TODO(jeremy): Move this to GTM. |
| 720 - (NSRect)drawTitle:(NSAttributedString*)title | 729 - (NSRect)drawTitle:(NSAttributedString*)title |
| 721 withFrame:(NSRect)cellFrame | 730 withFrame:(NSRect)cellFrame |
| 722 inView:(NSView*)controlView { | 731 inView:(NSView*)controlView { |
| 723 NSSize size = [title size]; | 732 NSSize size = [title size]; |
| 724 | 733 |
| 725 // Empirically, Cocoa will draw an extra 2 pixels past NSWidth(cellFrame) | 734 // Empirically, Cocoa will draw an extra 2 pixels past NSWidth(cellFrame) |
| 726 // before it clips the text. | 735 // before it clips the text. |
| 727 const CGFloat kOverflowBeforeClip = 2; | 736 const CGFloat kOverflowBeforeClip = 2; |
| 728 BOOL isModeMaterial = | 737 BOOL isModeMaterial = [self isMaterialDesignButtonType]; |
| 729 [self tag] == kMaterialStandardButtonTypeWithLimitedClickFeedback; | |
| 730 // For Material Design we don't want to clip the text. For all other button | 738 // For Material Design we don't want to clip the text. For all other button |
| 731 // cell modes, we do. | 739 // cell modes, we do. |
| 732 BOOL shouldClipTheTitle = !isModeMaterial; | 740 BOOL shouldClipTheTitle = !isModeMaterial; |
| 733 if (std::floor(size.width) <= (NSWidth(cellFrame) + kOverflowBeforeClip)) { | 741 if (std::floor(size.width) <= (NSWidth(cellFrame) + kOverflowBeforeClip)) { |
| 734 cellFrame.origin.y += ([self verticalTextOffset] - 1); | 742 cellFrame.origin.y += ([self verticalTextOffset] - 1); |
| 735 shouldClipTheTitle = NO; | 743 shouldClipTheTitle = NO; |
| 736 } | 744 } |
| 737 | 745 |
| 738 // Gradient is about twice our line height long. | 746 // Gradient is about twice our line height long. |
| 739 CGFloat gradientWidth = MIN(size.height * 2, NSWidth(cellFrame) / 4); | 747 CGFloat gradientWidth = MIN(size.height * 2, NSWidth(cellFrame) / 4); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 851 options:options | 859 options:options |
| 852 owner:self | 860 owner:self |
| 853 userInfo:nil]); | 861 userInfo:nil]); |
| 854 if (isMouseInside_ != mouseInView) { | 862 if (isMouseInside_ != mouseInView) { |
| 855 [self setMouseInside:mouseInView animate:NO]; | 863 [self setMouseInside:mouseInView animate:NO]; |
| 856 [controlView setNeedsDisplay:YES]; | 864 [controlView setNeedsDisplay:YES]; |
| 857 } | 865 } |
| 858 } | 866 } |
| 859 | 867 |
| 860 @end | 868 @end |
| OLD | NEW |