From 0735266658f996210b6f43142ce7f4c55f47ae13 Mon Sep 17 00:00:00 2001 From: "avi@chromium.org" Date: Mon, 13 Jul 2009 23:22:33 +0000 Subject: Initial support for theming on Mac OS X. Patch by alcor. Original review: http://codereview.chromium.org/149204 BUG=http://crbug.com/14451 TEST=Open a theme, watch it apply. Review URL: http://codereview.chromium.org/155355 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20560 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/browser/cocoa/gradient_button_cell.mm | 161 +++++++++++++++++++++------ 1 file changed, 125 insertions(+), 36 deletions(-) (limited to 'chrome/browser/cocoa/gradient_button_cell.mm') diff --git a/chrome/browser/cocoa/gradient_button_cell.mm b/chrome/browser/cocoa/gradient_button_cell.mm index f8f6173..1ad72d4 100644 --- a/chrome/browser/cocoa/gradient_button_cell.mm +++ b/chrome/browser/cocoa/gradient_button_cell.mm @@ -3,6 +3,8 @@ // found in the LICENSE file. #include "chrome/browser/cocoa/gradient_button_cell.h" +#import "third_party/GTM/AppKit/GTMTheme.h" +#import "base/scoped_nsobject.h" @implementation GradientButtonCell @@ -11,75 +13,162 @@ NSBackgroundStyleLowered : NSBackgroundStyleRaised; } -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { // Constants from Cole. Will kConstant them once the feedback loop // is complete. NSRect drawFrame = NSInsetRect(cellFrame, 1.5, 1.5); + NSRect innerFrame = NSInsetRect(cellFrame, 2, 2); ButtonType type = [[(NSControl*)controlView cell] tag]; switch (type) { case kRightButtonType: drawFrame.origin.x -= 20; + innerFrame.origin.x -= 2; + // Fallthrough case kLeftButtonType: case kLeftButtonWithShadowType: drawFrame.size.width += 20; + innerFrame.size.width += 2; default: break; } const float radius = 3.5; - BOOL highlighted = [self isHighlighted]; + BOOL pressed = [self isHighlighted]; + NSWindow* window = [controlView window]; + BOOL active = [window isKeyWindow] || [window isMainWindow]; - // TODO(jrg): convert to GTMTheme + GTMTheme *theme = [controlView gtm_theme]; - NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:drawFrame - xRadius:radius - yRadius:radius]; - NSBezierPath *outerPath = + NSBezierPath* innerPath = + [NSBezierPath bezierPathWithRoundedRect:drawFrame + xRadius:radius + yRadius:radius]; + NSBezierPath* outerPath = [NSBezierPath bezierPathWithRoundedRect:NSInsetRect(drawFrame, -1, -1) xRadius:radius + 1 yRadius:radius + 1]; - NSGradient *gradient = nil; - - if (highlighted) { - NSColor* start = [NSColor colorWithCalibratedHue:0.6 - saturation:1.0 - brightness:0.6 - alpha:1.0]; - NSColor* end = [NSColor colorWithCalibratedHue:0.6 - saturation:1.0 - brightness:0.8 - alpha:1.0]; - gradient = [[[NSGradient alloc] initWithStartingColor:start - endingColor:end] autorelease]; - } else { - NSColor* start = [NSColor colorWithCalibratedWhite:1.0 alpha:1.0]; - NSColor* end = [NSColor colorWithCalibratedWhite:0.90 alpha:1.0]; - gradient = [[[NSGradient alloc] initWithStartingColor:start - endingColor:end] autorelease]; - } // Stroke the borders and appropriate fill gradient. If we're borderless, // the only time we want to draw the inner gradient is if we're highlighted. - [[NSColor colorWithCalibratedWhite:1.0 alpha:0.25] set]; - if ([self isBordered]) { + if ([self isBordered] || pressed) { + [[NSColor colorWithCalibratedWhite:1.0 alpha:0.25] set]; [outerPath stroke]; - [gradient drawInBezierPath:path angle:90.0]; - [[NSColor colorWithCalibratedWhite:0.0 alpha:0.15] set]; - [path stroke]; - } else { - if (highlighted) - [gradient drawInBezierPath:path angle:90.0]; + + NSImage* backgroundImage = + [theme backgroundImageForStyle:GTMThemeStyleToolBarButton state:YES]; + + if (backgroundImage) { + NSColor* patternColor = [NSColor colorWithPatternImage:backgroundImage]; + [patternColor set]; + // Set the phase to match window. + NSRect trueRect = [controlView convertRectToBase:cellFrame]; + [[NSGraphicsContext currentContext] + setPatternPhase:NSMakePoint(NSMinX(trueRect), NSMaxY(trueRect))]; + [innerPath fill]; + } else { + if (pressed) { + NSGradient* gradient = + [theme gradientForStyle:GTMThemeStyleToolBarButtonPressed + state:active]; + [gradient drawInBezierPath:innerPath angle:90.0]; + } + } + + if (!pressed) { + [NSGraphicsContext saveGraphicsState]; + [innerPath addClip]; + + // Draw the inner glow. + [innerPath setLineWidth:2]; + [[NSColor colorWithCalibratedWhite:1.0 alpha:0.9] setStroke]; + [innerPath stroke]; + + [[NSColor colorWithCalibratedWhite:1.0 alpha:0.9] setStroke]; + [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2] setFill]; + + // Draw the top inner highlight. + NSAffineTransform* highlightTransform = [NSAffineTransform transform]; + [highlightTransform translateXBy:1 yBy:1]; + scoped_nsobject highlightPath([innerPath copy]); + [highlightPath transformUsingAffineTransform:highlightTransform]; + + [highlightPath stroke]; + + NSColor* startColor = [NSColor colorWithCalibratedWhite:1.0 alpha:0.666]; + NSColor* endColor = [NSColor colorWithCalibratedWhite:1.0 alpha:0.333]; + scoped_nsobject gradient([[NSGradient alloc] + initWithColorsAndLocations:startColor, 0.33, endColor, 1.0, nil]); + + [gradient drawInBezierPath:innerPath angle:90.0]; + + [NSGraphicsContext restoreGraphicsState]; + } + + NSColor* stroke = [theme strokeColorForStyle:GTMThemeStyleToolBarButton + state:active]; + [stroke setStroke]; + + [innerPath setLineWidth:1]; + [innerPath stroke]; } + // If this is the left side of a segmented button, draw a slight shadow. if (type == kLeftButtonWithShadowType) { NSRect borderRect, contentRect; NSDivideRect(cellFrame, &borderRect, &contentRect, 1.0, NSMaxXEdge); - [[NSColor colorWithCalibratedWhite:0.0 alpha:0.15] set]; + NSColor* stroke = [theme strokeColorForStyle:GTMThemeStyleToolBarButton + state:active]; + [[stroke colorWithAlphaComponent:0.2] set]; NSRectFillUsingOperation(NSInsetRect(borderRect, 0, 2), NSCompositeSourceOver); + innerFrame.size.width -= 1.0; } + [self drawInteriorWithFrame:innerFrame inView:controlView]; +} + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { + GTMTheme* theme = [controlView gtm_theme]; + + BOOL shouldTheme = YES; + if (shouldTheme) { + BOOL isTemplate = [[self image] isTemplate]; - [self drawInteriorWithFrame:NSOffsetRect(cellFrame, 0, 1) inView:controlView]; + [NSGraphicsContext saveGraphicsState]; + + CGContextRef context = + (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]); + + if (isTemplate) { + scoped_nsobject shadow([[NSShadow alloc] init]); + [shadow setShadowColor:[NSColor whiteColor]]; + [shadow setShadowOffset:NSMakeSize(0, -1.0)]; + [shadow setShadowBlurRadius:1.0]; + [shadow set]; + } + + CGContextBeginTransparencyLayer(context, 0); + NSRect imageRect = NSZeroRect; + imageRect.size = [[self image] size]; + [[self image] setFlipped:[controlView isFlipped]]; + [[self image] drawInRect:[self imageRectForBounds:cellFrame] + fromRect:imageRect + operation:NSCompositeSourceOver + fraction:[self isEnabled] ? 1.0 : 0.5]; + if (isTemplate) { + NSColor* color = [theme iconColorForStyle:GTMThemeStyleToolBarButton + state:YES]; + [color set]; + NSRectFillUsingOperation(cellFrame,NSCompositeSourceAtop); + } + + CGContextEndTransparencyLayer(context); + [NSGraphicsContext restoreGraphicsState]; + } else { + // NSCell draws these uncentered for some reason, probably because of the + // of control in the xib + [super drawInteriorWithFrame:NSOffsetRect(cellFrame, 0, 1) + inView:controlView]; + } } @end -- cgit v1.1