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 #include "chrome/browser/ui/cocoa/gradient_button_cell.h" | 5 #include "chrome/browser/ui/cocoa/gradient_button_cell.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #import "base/memory/scoped_nsobject.h" | 8 #import "base/memory/scoped_nsobject.h" |
9 #import "chrome/browser/themes/theme_service.h" | 9 #import "chrome/browser/themes/theme_service.h" |
10 #import "chrome/browser/ui/cocoa/image_utils.h" | 10 #import "chrome/browser/ui/cocoa/image_utils.h" |
11 #import "chrome/browser/ui/cocoa/nsview_additions.h" | 11 #import "chrome/browser/ui/cocoa/nsview_additions.h" |
12 #import "chrome/browser/ui/cocoa/themed_window.h" | 12 #import "chrome/browser/ui/cocoa/themed_window.h" |
13 #include "grit/theme_resources.h" | 13 #include "grit/theme_resources.h" |
14 #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h" | 14 #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h" |
| 15 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" |
15 | 16 |
16 @interface GradientButtonCell (Private) | 17 @interface GradientButtonCell (Private) |
17 - (void)sharedInit; | 18 - (void)sharedInit; |
18 | 19 |
19 // Get drawing parameters for a given cell frame in a given view. The inner | 20 // Get drawing parameters for a given cell frame in a given view. The inner |
20 // frame is the one required by |-drawInteriorWithFrame:inView:|. The inner and | 21 // frame is the one required by |-drawInteriorWithFrame:inView:|. The inner and |
21 // outer paths are the ones required by |-drawBorderAndFillForTheme:...|. The | 22 // outer paths are the ones required by |-drawBorderAndFillForTheme:...|. The |
22 // outer path also gives the area in which to clip. Any of the |return...| | 23 // outer path also gives the area in which to clip. Any of the |return...| |
23 // arguments may be NULL (in which case the given parameter won't be returned). | 24 // arguments may be NULL (in which case the given parameter won't be returned). |
24 // If |returnInnerPath| or |returnOuterPath|, |*returnInnerPath| or | 25 // If |returnInnerPath| or |returnOuterPath|, |*returnInnerPath| or |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 ThemeService::GRADIENT_TOOLBAR_BUTTON_PRESSED : | 397 ThemeService::GRADIENT_TOOLBAR_BUTTON_PRESSED : |
397 ThemeService::GRADIENT_TOOLBAR_BUTTON_PRESSED_INACTIVE) : | 398 ThemeService::GRADIENT_TOOLBAR_BUTTON_PRESSED_INACTIVE) : |
398 nil; | 399 nil; |
399 } | 400 } |
400 [clickedGradient drawInBezierPath:innerPath angle:90.0]; | 401 [clickedGradient drawInBezierPath:innerPath angle:90.0]; |
401 } | 402 } |
402 } | 403 } |
403 | 404 |
404 // Visually indicate unclicked, enabled buttons. | 405 // Visually indicate unclicked, enabled buttons. |
405 if (!showClickedGradient && [self isEnabled]) { | 406 if (!showClickedGradient && [self isEnabled]) { |
406 [NSGraphicsContext saveGraphicsState]; | 407 gfx::ScopedNSGraphicsContextSaveGState scopedGState; |
407 [innerPath addClip]; | 408 [innerPath addClip]; |
408 | 409 |
409 // Draw the inner glow. | 410 // Draw the inner glow. |
410 if (hoverAlpha > 0) { | 411 if (hoverAlpha > 0) { |
411 [innerPath setLineWidth:2]; | 412 [innerPath setLineWidth:2]; |
412 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2 * hoverAlpha] setStroke]; | 413 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2 * hoverAlpha] setStroke]; |
413 [innerPath stroke]; | 414 [innerPath stroke]; |
414 } | 415 } |
415 | 416 |
416 // Draw the top inner highlight. | 417 // Draw the top inner highlight. |
417 NSAffineTransform* highlightTransform = [NSAffineTransform transform]; | 418 NSAffineTransform* highlightTransform = [NSAffineTransform transform]; |
418 [highlightTransform translateXBy:1 yBy:1]; | 419 [highlightTransform translateXBy:1 yBy:1]; |
419 scoped_nsobject<NSBezierPath> highlightPath([innerPath copy]); | 420 scoped_nsobject<NSBezierPath> highlightPath([innerPath copy]); |
420 [highlightPath transformUsingAffineTransform:highlightTransform]; | 421 [highlightPath transformUsingAffineTransform:highlightTransform]; |
421 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2] setStroke]; | 422 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2] setStroke]; |
422 [highlightPath stroke]; | 423 [highlightPath stroke]; |
423 | 424 |
424 // Draw the gradient inside. | 425 // Draw the gradient inside. |
425 [gradient drawInBezierPath:innerPath angle:90.0]; | 426 [gradient drawInBezierPath:innerPath angle:90.0]; |
426 | |
427 [NSGraphicsContext restoreGraphicsState]; | |
428 } | 427 } |
429 | 428 |
430 // Don't draw anything else for disabled flat buttons. | 429 // Don't draw anything else for disabled flat buttons. |
431 if (isFlatButton && ![self isEnabled]) | 430 if (isFlatButton && ![self isEnabled]) |
432 return; | 431 return; |
433 | 432 |
434 // Draw the outer stroke. | 433 // Draw the outer stroke. |
435 NSColor* strokeColor = nil; | 434 NSColor* strokeColor = nil; |
436 if (showClickedGradient) { | 435 if (showClickedGradient) { |
437 strokeColor = [NSColor | 436 strokeColor = [NSColor |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 } | 568 } |
570 [self drawInteriorWithFrame:innerFrame inView:controlView]; | 569 [self drawInteriorWithFrame:innerFrame inView:controlView]; |
571 } | 570 } |
572 | 571 |
573 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { | 572 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { |
574 const CGFloat lineWidth = [controlView cr_lineWidth]; | 573 const CGFloat lineWidth = [controlView cr_lineWidth]; |
575 | 574 |
576 if (shouldTheme_) { | 575 if (shouldTheme_) { |
577 BOOL isTemplate = [[self image] isTemplate]; | 576 BOOL isTemplate = [[self image] isTemplate]; |
578 | 577 |
579 [NSGraphicsContext saveGraphicsState]; | 578 gfx::ScopedNSGraphicsContextSaveGState scopedGState; |
580 | 579 |
581 CGContextRef context = | 580 CGContextRef context = |
582 (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]); | 581 (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]); |
583 | 582 |
584 ThemeService* themeProvider = static_cast<ThemeService*>( | 583 ThemeService* themeProvider = static_cast<ThemeService*>( |
585 [[controlView window] themeProvider]); | 584 [[controlView window] themeProvider]); |
586 NSColor* color = themeProvider ? | 585 NSColor* color = themeProvider ? |
587 themeProvider->GetNSColorTint(ThemeService::TINT_BUTTONS, | 586 themeProvider->GetNSColorTint(ThemeService::TINT_BUTTONS, |
588 true) : | 587 true) : |
589 [NSColor blackColor]; | 588 [NSColor blackColor]; |
(...skipping 14 matching lines...) Expand all Loading... |
604 [[self image] drawInRect:drawRect | 603 [[self image] drawInRect:drawRect |
605 fromRect:imageRect | 604 fromRect:imageRect |
606 operation:NSCompositeSourceOver | 605 operation:NSCompositeSourceOver |
607 fraction:[self isEnabled] ? 1.0 : 0.5 | 606 fraction:[self isEnabled] ? 1.0 : 0.5 |
608 neverFlipped:YES]; | 607 neverFlipped:YES]; |
609 if (isTemplate && color) { | 608 if (isTemplate && color) { |
610 [color set]; | 609 [color set]; |
611 NSRectFillUsingOperation(cellFrame, NSCompositeSourceAtop); | 610 NSRectFillUsingOperation(cellFrame, NSCompositeSourceAtop); |
612 } | 611 } |
613 CGContextEndTransparencyLayer(context); | 612 CGContextEndTransparencyLayer(context); |
614 | |
615 [NSGraphicsContext restoreGraphicsState]; | |
616 } else { | 613 } else { |
617 // NSCell draws these off-center for some reason, probably because of the | 614 // NSCell draws these off-center for some reason, probably because of the |
618 // positioning of the control in the xib. | 615 // positioning of the control in the xib. |
619 [super drawInteriorWithFrame:NSOffsetRect(cellFrame, 0, lineWidth) | 616 [super drawInteriorWithFrame:NSOffsetRect(cellFrame, 0, lineWidth) |
620 inView:controlView]; | 617 inView:controlView]; |
621 } | 618 } |
622 | 619 |
623 if (overlayImage_) { | 620 if (overlayImage_) { |
624 NSRect imageRect = NSZeroRect; | 621 NSRect imageRect = NSZeroRect; |
625 imageRect.size = [overlayImage_ size]; | 622 imageRect.size = [overlayImage_ size]; |
(...skipping 27 matching lines...) Expand all Loading... |
653 } | 650 } |
654 | 651 |
655 // Gradient is about twice our line height long. | 652 // Gradient is about twice our line height long. |
656 CGFloat gradientWidth = MIN(size.height * 2, NSWidth(cellFrame) / 4); | 653 CGFloat gradientWidth = MIN(size.height * 2, NSWidth(cellFrame) / 4); |
657 | 654 |
658 NSRect solidPart, gradientPart; | 655 NSRect solidPart, gradientPart; |
659 NSDivideRect(cellFrame, &gradientPart, &solidPart, gradientWidth, NSMaxXEdge); | 656 NSDivideRect(cellFrame, &gradientPart, &solidPart, gradientWidth, NSMaxXEdge); |
660 | 657 |
661 // Draw non-gradient part without transparency layer, as light text on a dark | 658 // Draw non-gradient part without transparency layer, as light text on a dark |
662 // background looks bad with a gradient layer. | 659 // background looks bad with a gradient layer. |
663 [[NSGraphicsContext currentContext] saveGraphicsState]; | 660 NSPoint textOffset = NSZeroPoint; |
664 [NSBezierPath clipRect:solidPart]; | 661 { |
| 662 gfx::ScopedNSGraphicsContextSaveGState scopedGState; |
| 663 [NSBezierPath clipRect:solidPart]; |
665 | 664 |
666 // 11 is the magic number needed to make this match the native NSButtonCell's | 665 // 11 is the magic number needed to make this match the native |
667 // label display. | 666 // NSButtonCell's label display. |
668 CGFloat textLeft = [[self image] size].width + 11; | 667 CGFloat textLeft = [[self image] size].width + 11; |
669 | 668 |
670 // For some reason, the height of cellFrame as passed in is totally bogus. | 669 // For some reason, the height of cellFrame as passed in is totally bogus. |
671 // For vertical centering purposes, we need the bounds of the containing | 670 // For vertical centering purposes, we need the bounds of the containing |
672 // view. | 671 // view. |
673 NSRect buttonFrame = [[self controlView] frame]; | 672 NSRect buttonFrame = [[self controlView] frame]; |
674 | 673 |
675 // Off-by-one to match native NSButtonCell's version. | 674 // Off-by-one to match native NSButtonCell's version. |
676 NSPoint textOffset = NSMakePoint(textLeft, | 675 textOffset = NSMakePoint(textLeft, |
677 (NSHeight(buttonFrame) - size.height)/2 + 1); | 676 (NSHeight(buttonFrame) - size.height)/2 + 1); |
678 [title drawAtPoint:textOffset]; | 677 [title drawAtPoint:textOffset]; |
679 [[NSGraphicsContext currentContext] restoreGraphicsState]; | 678 } |
680 | 679 |
681 // Draw the gradient part with a transparency layer. This makes the text look | 680 // Draw the gradient part with a transparency layer. This makes the text look |
682 // suboptimal, but since it fades out, that's ok. | 681 // suboptimal, but since it fades out, that's ok. |
683 [[NSGraphicsContext currentContext] saveGraphicsState]; | 682 gfx::ScopedNSGraphicsContextSaveGState scopedGState; |
684 [NSBezierPath clipRect:gradientPart]; | 683 [NSBezierPath clipRect:gradientPart]; |
685 CGContextRef context = static_cast<CGContextRef>( | 684 CGContextRef context = static_cast<CGContextRef>( |
686 [[NSGraphicsContext currentContext] graphicsPort]); | 685 [[NSGraphicsContext currentContext] graphicsPort]); |
687 CGContextBeginTransparencyLayerWithRect(context, | 686 CGContextBeginTransparencyLayerWithRect(context, |
688 NSRectToCGRect(gradientPart), 0); | 687 NSRectToCGRect(gradientPart), 0); |
689 [title drawAtPoint:textOffset]; | 688 [title drawAtPoint:textOffset]; |
690 | 689 |
691 // TODO(alcor): switch this to GTMLinearRGBShading if we ever need on 10.4 | 690 // TODO(alcor): switch this to GTMLinearRGBShading if we ever need on 10.4 |
692 NSColor *color = [NSColor textColor]; //[self textColor]; | 691 NSColor *color = [NSColor textColor]; //[self textColor]; |
693 NSColor *alphaColor = [color colorWithAlphaComponent:0.0]; | 692 NSColor *alphaColor = [color colorWithAlphaComponent:0.0]; |
694 NSGradient *mask = [[NSGradient alloc] initWithStartingColor:color | 693 NSGradient *mask = [[NSGradient alloc] initWithStartingColor:color |
695 endingColor:alphaColor]; | 694 endingColor:alphaColor]; |
696 | 695 |
697 // Draw the gradient mask | 696 // Draw the gradient mask |
698 CGContextSetBlendMode(context, kCGBlendModeDestinationIn); | 697 CGContextSetBlendMode(context, kCGBlendModeDestinationIn); |
699 [mask drawFromPoint:NSMakePoint(NSMaxX(cellFrame) - gradientWidth, | 698 [mask drawFromPoint:NSMakePoint(NSMaxX(cellFrame) - gradientWidth, |
700 NSMinY(cellFrame)) | 699 NSMinY(cellFrame)) |
701 toPoint:NSMakePoint(NSMaxX(cellFrame), | 700 toPoint:NSMakePoint(NSMaxX(cellFrame), |
702 NSMinY(cellFrame)) | 701 NSMinY(cellFrame)) |
703 options:NSGradientDrawsBeforeStartingLocation]; | 702 options:NSGradientDrawsBeforeStartingLocation]; |
704 [mask release]; | 703 [mask release]; |
705 CGContextEndTransparencyLayer(context); | 704 CGContextEndTransparencyLayer(context); |
706 [[NSGraphicsContext currentContext] restoreGraphicsState]; | |
707 | 705 |
708 return cellFrame; | 706 return cellFrame; |
709 } | 707 } |
710 | 708 |
711 - (NSBezierPath*)clipPathForFrame:(NSRect)cellFrame | 709 - (NSBezierPath*)clipPathForFrame:(NSRect)cellFrame |
712 inView:(NSView*)controlView { | 710 inView:(NSView*)controlView { |
713 NSBezierPath* boundingPath = nil; | 711 NSBezierPath* boundingPath = nil; |
714 [self getDrawParamsForFrame:cellFrame | 712 [self getDrawParamsForFrame:cellFrame |
715 inView:controlView | 713 inView:controlView |
716 innerFrame:NULL | 714 innerFrame:NULL |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
755 options:options | 753 options:options |
756 owner:self | 754 owner:self |
757 userInfo:nil]); | 755 userInfo:nil]); |
758 if (isMouseInside_ != mouseInView) { | 756 if (isMouseInside_ != mouseInView) { |
759 [self setMouseInside:mouseInView animate:NO]; | 757 [self setMouseInside:mouseInView animate:NO]; |
760 [controlView setNeedsDisplay:YES]; | 758 [controlView setNeedsDisplay:YES]; |
761 } | 759 } |
762 } | 760 } |
763 | 761 |
764 @end | 762 @end |
OLD | NEW |