| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "base/logging.h" | 5 #include "base/logging.h" |
| 6 #import "base/scoped_nsobject.h" | 6 #import "base/scoped_nsobject.h" |
| 7 #include "chrome/browser/cocoa/gradient_button_cell.h" | 7 #include "chrome/browser/cocoa/gradient_button_cell.h" |
| 8 #import "third_party/GTM/AppKit/GTMTheme.h" | 8 #import "third_party/GTM/AppKit/GTMTheme.h" |
| 9 #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h" | 9 #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h" |
| 10 | 10 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 } | 80 } |
| 81 | 81 |
| 82 // For programmatic instantiations | 82 // For programmatic instantiations |
| 83 - (id)initTextCell:(NSString*)string { | 83 - (id)initTextCell:(NSString*)string { |
| 84 if ((self = [super initTextCell:string])) { | 84 if ((self = [super initTextCell:string])) { |
| 85 [self sharedInit]; | 85 [self sharedInit]; |
| 86 } | 86 } |
| 87 return self; | 87 return self; |
| 88 } | 88 } |
| 89 | 89 |
| 90 - (NSGradient *)gradientForHoverAlpha:(CGFloat)hoverAlpha | 90 - (NSGradient*)gradientForHoverAlpha:(CGFloat)hoverAlpha |
| 91 isThemed:(BOOL)themed { | 91 isThemed:(BOOL)themed { |
| 92 CGFloat startAlpha = 0.6 + 0.3 * hoverAlpha; | 92 CGFloat startAlpha = 0.6 + 0.3 * hoverAlpha; |
| 93 CGFloat endAlpha = 0.333 * hoverAlpha; | 93 CGFloat endAlpha = 0.333 * hoverAlpha; |
| 94 | 94 |
| 95 if (themed) { | 95 if (themed) { |
| 96 startAlpha = 0.2 + 0.35 * hoverAlpha; | 96 startAlpha = 0.2 + 0.35 * hoverAlpha; |
| 97 endAlpha = 0.333 * hoverAlpha; | 97 endAlpha = 0.333 * hoverAlpha; |
| 98 } | 98 } |
| 99 | 99 |
| 100 NSColor* startColor = | 100 NSColor* startColor = |
| 101 [NSColor colorWithCalibratedWhite:1.0 | 101 [NSColor colorWithCalibratedWhite:1.0 |
| 102 alpha:startAlpha]; | 102 alpha:startAlpha]; |
| 103 NSColor* endColor = | 103 NSColor* endColor = |
| 104 [NSColor colorWithCalibratedWhite:1.0 - 0.15 * hoverAlpha | 104 [NSColor colorWithCalibratedWhite:1.0 - 0.15 * hoverAlpha |
| 105 alpha:endAlpha]; | 105 alpha:endAlpha]; |
| 106 NSGradient *gradient = [[NSGradient alloc] initWithColorsAndLocations: | 106 NSGradient* gradient = [[NSGradient alloc] initWithColorsAndLocations: |
| 107 startColor, hoverAlpha * 0.33, | 107 startColor, hoverAlpha * 0.33, |
| 108 endColor, 1.0, nil]; | 108 endColor, 1.0, nil]; |
| 109 | 109 |
| 110 return [gradient autorelease]; | 110 return [gradient autorelease]; |
| 111 } | 111 } |
| 112 | 112 |
| 113 - (void)sharedInit { | 113 - (void)sharedInit { |
| 114 shouldTheme_ = YES; | 114 shouldTheme_ = YES; |
| 115 gradient_.reset([[self gradientForHoverAlpha:0.0 isThemed:NO] retain]); | 115 gradient_.reset([[self gradientForHoverAlpha:0.0 isThemed:NO] retain]); |
| 116 } | 116 } |
| 117 | 117 |
| 118 - (void)setShouldTheme:(BOOL)shouldTheme { | 118 - (void)setShouldTheme:(BOOL)shouldTheme { |
| 119 shouldTheme_ = shouldTheme; | 119 shouldTheme_ = shouldTheme; |
| 120 } | 120 } |
| 121 | 121 |
| 122 - (NSImage*)underlayImage { | 122 - (NSImage*)underlayImage { |
| 123 return underlayImage_; | 123 return underlayImage_; |
| 124 } | 124 } |
| 125 | 125 |
| 126 - (void)setUnderlayImage:(NSImage*)image { | 126 - (void)setUnderlayImage:(NSImage*)image { |
| 127 underlayImage_.reset([image retain]); | 127 underlayImage_.reset([image retain]); |
| 128 | 128 |
| 129 [[self controlView] setNeedsDisplay:YES]; | 129 [[self controlView] setNeedsDisplay:YES]; |
| 130 } | 130 } |
| 131 | 131 |
| 132 - (NSBackgroundStyle)interiorBackgroundStyle { | 132 - (NSBackgroundStyle)interiorBackgroundStyle { |
| 133 return [self isHighlighted] ? | 133 // Never lower the interior, since that just leads to a weird shadow which can |
| 134 NSBackgroundStyleLowered : NSBackgroundStyleRaised; | 134 // often interact badly with the theme. |
| 135 return NSBackgroundStyleRaised; |
| 135 } | 136 } |
| 136 | 137 |
| 137 - (void)mouseEntered:(NSEvent *)theEvent { | 138 - (void)mouseEntered:(NSEvent*)theEvent { |
| 138 [self setMouseInside:YES animate:YES]; | 139 [self setMouseInside:YES animate:YES]; |
| 139 } | 140 } |
| 140 | 141 |
| 141 - (void)mouseExited:(NSEvent *)theEvent { | 142 - (void)mouseExited:(NSEvent*)theEvent { |
| 142 [self setMouseInside:NO animate:YES]; | 143 [self setMouseInside:NO animate:YES]; |
| 143 } | 144 } |
| 144 | 145 |
| 145 - (BOOL)isMouseInside { | 146 - (BOOL)isMouseInside { |
| 146 return trackingArea_ && isMouseInside_; | 147 return trackingArea_ && isMouseInside_; |
| 147 } | 148 } |
| 148 | 149 |
| 149 // Since we have our own drawWithFrame:, we need to also have our own | 150 // Since we have our own drawWithFrame:, we need to also have our own |
| 150 // logic for determining when the mouse is inside for honoring this | 151 // logic for determining when the mouse is inside for honoring this |
| 151 // request. | 152 // request. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 165 [[self controlView] addTrackingArea:trackingArea_]; | 166 [[self controlView] addTrackingArea:trackingArea_]; |
| 166 } else { | 167 } else { |
| 167 if (trackingArea_) { | 168 if (trackingArea_) { |
| 168 [[self controlView] removeTrackingArea:trackingArea_]; | 169 [[self controlView] removeTrackingArea:trackingArea_]; |
| 169 trackingArea_.reset(nil); | 170 trackingArea_.reset(nil); |
| 170 isMouseInside_ = NO; | 171 isMouseInside_ = NO; |
| 171 } | 172 } |
| 172 } | 173 } |
| 173 } | 174 } |
| 174 | 175 |
| 176 // TODO(viettrungluu): clean up/reorganize. |
| 175 - (void)drawBorderAndFillForTheme:(GTMTheme*)theme | 177 - (void)drawBorderAndFillForTheme:(GTMTheme*)theme |
| 176 controlView:(NSView*)controlView | 178 controlView:(NSView*)controlView |
| 177 outerPath:(NSBezierPath*)outerPath | 179 outerPath:(NSBezierPath*)outerPath |
| 178 innerPath:(NSBezierPath*)innerPath | 180 innerPath:(NSBezierPath*)innerPath |
| 179 showClickedGradient:(BOOL)showClickedGradient | 181 showClickedGradient:(BOOL)showClickedGradient |
| 180 showHighlightGradient:(BOOL)showHighlightGradient | 182 showHighlightGradient:(BOOL)showHighlightGradient |
| 181 hoverAlpha:(CGFloat)hoverAlpha | 183 hoverAlpha:(CGFloat)hoverAlpha |
| 182 active:(BOOL)active | 184 active:(BOOL)active |
| 183 cellFrame:(NSRect)cellFrame | 185 cellFrame:(NSRect)cellFrame |
| 184 defaultGradient:(NSGradient*)defaultGradient { | 186 defaultGradient:(NSGradient*)defaultGradient { |
| 185 NSImage* backgroundImage = | 187 BOOL isFlatButton = [self showsBorderOnlyWhileMouseInside]; |
| 186 [theme backgroundImageForStyle:GTMThemeStyleToolBarButton state:YES]; | |
| 187 | 188 |
| 188 if (!defaultGradient) | 189 // For flat (unbordered when not hovered) buttons, never use the toolbar |
| 189 defaultGradient = gradient_; | 190 // button background image, but the modest gradient used for themed buttons. |
| 191 // To make things even more modest, scale the hover alpha down by 40 percent |
| 192 // unless clicked. |
| 193 NSImage* backgroundImage; |
| 194 BOOL useThemeGradient; |
| 195 if (isFlatButton) { |
| 196 backgroundImage = nil; |
| 197 useThemeGradient = YES; |
| 198 if (!showClickedGradient) |
| 199 hoverAlpha *= 0.6; |
| 200 } else { |
| 201 backgroundImage = [theme backgroundImageForStyle:GTMThemeStyleToolBarButton |
| 202 state:YES]; |
| 203 useThemeGradient = backgroundImage ? YES : NO; |
| 204 } |
| 190 | 205 |
| 206 // The basic gradient shown inside; see above. |
| 207 NSGradient* gradient; |
| 208 if (hoverAlpha == 0 && !useThemeGradient) { |
| 209 gradient = defaultGradient ? defaultGradient |
| 210 : gradient_; |
| 211 } else { |
| 212 gradient = [self gradientForHoverAlpha:hoverAlpha |
| 213 isThemed:useThemeGradient]; |
| 214 } |
| 215 |
| 216 // If we're drawing a background image, show that; else possibly show the |
| 217 // clicked gradient. |
| 191 if (backgroundImage) { | 218 if (backgroundImage) { |
| 192 NSColor* patternColor = [NSColor colorWithPatternImage:backgroundImage]; | 219 NSColor* patternColor = [NSColor colorWithPatternImage:backgroundImage]; |
| 193 [patternColor set]; | 220 [patternColor set]; |
| 194 // Set the phase to match window. | 221 // Set the phase to match window. |
| 195 NSRect trueRect = [controlView convertRectToBase:cellFrame]; | 222 NSRect trueRect = [controlView convertRectToBase:cellFrame]; |
| 196 [[NSGraphicsContext currentContext] | 223 [[NSGraphicsContext currentContext] |
| 197 setPatternPhase:NSMakePoint(NSMinX(trueRect), NSMaxY(trueRect))]; | 224 setPatternPhase:NSMakePoint(NSMinX(trueRect), NSMaxY(trueRect))]; |
| 198 [innerPath fill]; | 225 [innerPath fill]; |
| 199 } else { | 226 } else { |
| 200 if (showClickedGradient) { | 227 if (showClickedGradient) { |
| 201 NSGradient* gradient = | 228 NSGradient* clickedGradient; |
| 202 [theme gradientForStyle:GTMThemeStyleToolBarButtonPressed | 229 if (isFlatButton) { |
| 203 state:active]; | 230 clickedGradient = gradient; |
| 204 [gradient drawInBezierPath:innerPath angle:90.0]; | 231 } else { |
| 232 clickedGradient = |
| 233 [theme gradientForStyle:GTMThemeStyleToolBarButtonPressed |
| 234 state:active]; |
| 235 } |
| 236 [clickedGradient drawInBezierPath:innerPath angle:90.0]; |
| 205 } | 237 } |
| 206 } | 238 } |
| 207 | 239 |
| 208 BOOL isCustomTheme = backgroundImage != nil; | 240 // Visually indicate unclicked, enabled buttons. |
| 209 | |
| 210 if (!showClickedGradient && [self isEnabled]) { | 241 if (!showClickedGradient && [self isEnabled]) { |
| 211 [NSGraphicsContext saveGraphicsState]; | 242 [NSGraphicsContext saveGraphicsState]; |
| 212 [innerPath addClip]; | 243 [innerPath addClip]; |
| 213 | 244 |
| 214 // Draw the inner glow. | 245 // Draw the inner glow. |
| 215 if (hoverAlpha > 0) { | 246 if (hoverAlpha > 0) { |
| 216 [innerPath setLineWidth:2]; | 247 [innerPath setLineWidth:2]; |
| 217 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2 * hoverAlpha] setStroke]; | 248 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2 * hoverAlpha] setStroke]; |
| 218 [innerPath stroke]; | 249 [innerPath stroke]; |
| 219 } | 250 } |
| 220 | 251 |
| 221 // Draw the top inner highlight. | 252 // Draw the top inner highlight. |
| 222 NSAffineTransform* highlightTransform = [NSAffineTransform transform]; | 253 NSAffineTransform* highlightTransform = [NSAffineTransform transform]; |
| 223 [highlightTransform translateXBy:1 yBy:1]; | 254 [highlightTransform translateXBy:1 yBy:1]; |
| 224 scoped_nsobject<NSBezierPath> highlightPath([innerPath copy]); | 255 scoped_nsobject<NSBezierPath> highlightPath([innerPath copy]); |
| 225 [highlightPath transformUsingAffineTransform:highlightTransform]; | 256 [highlightPath transformUsingAffineTransform:highlightTransform]; |
| 226 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2] setStroke]; | 257 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2] setStroke]; |
| 227 [highlightPath stroke]; | 258 [highlightPath stroke]; |
| 228 | 259 |
| 229 NSGradient *gradient = nil; | 260 // Draw the gradient inside. |
| 230 if (hoverAlpha == 0 && !isCustomTheme) { | |
| 231 gradient = defaultGradient; | |
| 232 } else { | |
| 233 gradient = [self gradientForHoverAlpha:hoverAlpha isThemed:isCustomTheme]; | |
| 234 } | |
| 235 [gradient drawInBezierPath:innerPath angle:90.0]; | 261 [gradient drawInBezierPath:innerPath angle:90.0]; |
| 236 | 262 |
| 237 [NSGraphicsContext restoreGraphicsState]; | 263 [NSGraphicsContext restoreGraphicsState]; |
| 238 } | 264 } |
| 239 | 265 |
| 240 // Draw the outer stroke | 266 // Draw the outer stroke. |
| 241 NSColor* stroke = [theme strokeColorForStyle:GTMThemeStyleToolBarButton | 267 NSColor* strokeColor = showClickedGradient ? |
| 242 state:active]; | 268 [NSColor colorWithCalibratedWhite:0.0 alpha:0.3] : |
| 243 | 269 [theme strokeColorForStyle:GTMThemeStyleToolBarButton state:active]; |
| 244 if (showClickedGradient) { | 270 [strokeColor setStroke]; |
| 245 stroke = [NSColor colorWithCalibratedWhite:0.0 alpha:0.3]; | |
| 246 } | |
| 247 [stroke setStroke]; | |
| 248 | 271 |
| 249 [innerPath setLineWidth:1]; | 272 [innerPath setLineWidth:1]; |
| 250 [innerPath stroke]; | 273 [innerPath stroke]; |
| 251 } | 274 } |
| 252 | 275 |
| 253 // TODO(viettrungluu): clean this up. | 276 // TODO(viettrungluu): clean this up. |
| 254 // (Private) | 277 // (Private) |
| 255 - (void)getDrawParamsForFrame:(NSRect)cellFrame | 278 - (void)getDrawParamsForFrame:(NSRect)cellFrame |
| 256 inView:(NSView*)controlView | 279 inView:(NSView*)controlView |
| 257 innerFrame:(NSRect*)returnInnerFrame | 280 innerFrame:(NSRect*)returnInnerFrame |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 inView:controlView | 341 inView:controlView |
| 319 innerFrame:&innerFrame | 342 innerFrame:&innerFrame |
| 320 innerPath:&innerPath | 343 innerPath:&innerPath |
| 321 outerPath:&outerPath | 344 outerPath:&outerPath |
| 322 clipPath:NULL]; | 345 clipPath:NULL]; |
| 323 | 346 |
| 324 BOOL pressed = [self isHighlighted]; | 347 BOOL pressed = [self isHighlighted]; |
| 325 NSWindow* window = [controlView window]; | 348 NSWindow* window = [controlView window]; |
| 326 BOOL active = [window isKeyWindow] || [window isMainWindow]; | 349 BOOL active = [window isKeyWindow] || [window isMainWindow]; |
| 327 | 350 |
| 328 GTMTheme *theme = [controlView gtm_theme]; | 351 GTMTheme* theme = [controlView gtm_theme]; |
| 329 | 352 |
| 330 // Stroke the borders and appropriate fill gradient. If we're borderless, | 353 // Stroke the borders and appropriate fill gradient. If we're borderless, |
| 331 // the only time we want to draw the inner gradient is if we're highlighted. | 354 // the only time we want to draw the inner gradient is if we're highlighted. |
| 332 if (([self isBordered] && ![self showsBorderOnlyWhileMouseInside]) || | 355 if (([self isBordered] && ![self showsBorderOnlyWhileMouseInside]) || |
| 333 pressed || | 356 pressed || |
| 334 [self isMouseInside]) { | 357 [self isMouseInside]) { |
| 335 | 358 |
| 336 [self drawBorderAndFillForTheme:theme | 359 [self drawBorderAndFillForTheme:theme |
| 337 controlView:controlView | 360 controlView:controlView |
| 338 outerPath:outerPath | 361 outerPath:outerPath |
| (...skipping 29 matching lines...) Expand all Loading... |
| 368 [NSGraphicsContext saveGraphicsState]; | 391 [NSGraphicsContext saveGraphicsState]; |
| 369 | 392 |
| 370 CGContextRef context = | 393 CGContextRef context = |
| 371 (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]); | 394 (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]); |
| 372 | 395 |
| 373 NSColor* color = [theme iconColorForStyle:GTMThemeStyleToolBarButton | 396 NSColor* color = [theme iconColorForStyle:GTMThemeStyleToolBarButton |
| 374 state:YES]; | 397 state:YES]; |
| 375 | 398 |
| 376 if (isTemplate) { | 399 if (isTemplate) { |
| 377 scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]); | 400 scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]); |
| 378 NSColor *shadowColor = [color gtm_legibleTextColor]; | 401 NSColor* shadowColor = [color gtm_legibleTextColor]; |
| 379 shadowColor = [shadowColor colorWithAlphaComponent:0.25]; | 402 shadowColor = [shadowColor colorWithAlphaComponent:0.25]; |
| 380 [shadow.get() setShadowColor:shadowColor]; | 403 [shadow.get() setShadowColor:shadowColor]; |
| 381 [shadow.get() setShadowOffset:NSMakeSize(0, -1.0)]; | 404 [shadow.get() setShadowOffset:NSMakeSize(0, -1.0)]; |
| 382 [shadow setShadowBlurRadius:1.0]; | 405 [shadow setShadowBlurRadius:1.0]; |
| 383 [shadow set]; | 406 [shadow set]; |
| 384 } | 407 } |
| 385 | 408 |
| 386 [self drawUnderlayImageWithFrame:cellFrame inView:controlView]; | 409 [self drawUnderlayImageWithFrame:cellFrame inView:controlView]; |
| 387 | 410 |
| 388 CGContextBeginTransparencyLayer(context, 0); | 411 CGContextBeginTransparencyLayer(context, 0); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 [self getDrawParamsForFrame:cellFrame | 455 [self getDrawParamsForFrame:cellFrame |
| 433 inView:controlView | 456 inView:controlView |
| 434 innerFrame:NULL | 457 innerFrame:NULL |
| 435 innerPath:NULL | 458 innerPath:NULL |
| 436 outerPath:NULL | 459 outerPath:NULL |
| 437 clipPath:&boundingPath]; | 460 clipPath:&boundingPath]; |
| 438 return boundingPath; | 461 return boundingPath; |
| 439 } | 462 } |
| 440 | 463 |
| 441 @end | 464 @end |
| OLD | NEW |