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

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

Issue 165499: Updates to clean up default theme and add hover states (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 11 years, 3 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 | Annotate | Revision Log
OLDNEW
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 #import "base/scoped_nsobject.h"
5 #include "chrome/browser/cocoa/gradient_button_cell.h" 6 #include "chrome/browser/cocoa/gradient_button_cell.h"
6 #import "third_party/GTM/AppKit/GTMTheme.h" 7 #import "third_party/GTM/AppKit/GTMTheme.h"
7 #import "base/scoped_nsobject.h" 8 #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h"
8 9
9 @interface GradientButtonCell (Private) 10 @interface GradientButtonCell (Private)
10 - (void)sharedInit; 11 - (void)sharedInit;
11 - (void)drawUnderlayImageWithFrame:(NSRect)cellFrame 12 - (void)drawUnderlayImageWithFrame:(NSRect)cellFrame
12 inView:(NSView*)controlView; 13 inView:(NSView*)controlView;
13 @end 14 @end
14 15
16 static const NSTimeInterval kAnimationShowDuration = 0.2;
17 static const NSTimeInterval kAnimationHideDuration = 0.4;
15 18
16 @implementation GradientButtonCell 19 @implementation GradientButtonCell
20 @synthesize hoverAlpha = hoverAlpha_;
21
22 - (void)adjustHoverValue {
23 NSTimeInterval thisUpdate = [NSDate timeIntervalSinceReferenceDate];
24
25 NSTimeInterval elapsed = thisUpdate - lastHoverUpdate_;
26
27 CGFloat opacity = [self hoverAlpha];
28 if (isMouseInside_) {
29 opacity += elapsed / kAnimationShowDuration;
30 } else {
31 opacity -= elapsed / kAnimationHideDuration;
32 }
33
34 if (!isMouseInside_ && opacity < 0) {
35 opacity = 0;
36 } else if (isMouseInside_ && opacity > 1) {
37 opacity = 1;
38 } else {
39 [self performSelector:_cmd withObject:nil afterDelay:0.02];
40 }
41 lastHoverUpdate_ = thisUpdate;
42 [self setHoverAlpha:opacity];
43
44 [[self controlView] setNeedsDisplay:YES];
45 }
46
47 - (void)setMouseInside:(BOOL)flag animate:(BOOL)animated {
48 isMouseInside_ = flag;
49 if (animated) {
50 lastHoverUpdate_ = [NSDate timeIntervalSinceReferenceDate];
51 [self adjustHoverValue];
52 } else {
53 [NSObject cancelPreviousPerformRequestsWithTarget:self];
54 [self setHoverAlpha:flag ? 1.0 : 0.0];
55 }
56 [[self controlView] setNeedsDisplay:YES];
57 }
17 58
18 // For nib instantiations 59 // For nib instantiations
19 - (id)initWithCoder:(NSCoder*)decoder { 60 - (id)initWithCoder:(NSCoder*)decoder {
20 if ((self = [super initWithCoder:decoder])) { 61 if ((self = [super initWithCoder:decoder])) {
21 [self sharedInit]; 62 [self sharedInit];
22 } 63 }
23 return self; 64 return self;
24 } 65 }
25 66
26 // For programmatic instantiations 67 // For programmatic instantiations
27 - (id)initTextCell:(NSString*)string { 68 - (id)initTextCell:(NSString*)string {
28 if ((self = [super initTextCell:string])) { 69 if ((self = [super initTextCell:string])) {
29 [self sharedInit]; 70 [self sharedInit];
30 } 71 }
31 return self; 72 return self;
32 } 73 }
33 74
75 - (NSGradient *)gradientForHoverAlpha:(CGFloat)hoverAlpha
76 isThemed:(BOOL)themed {
77 CGFloat startAlpha = 0.6 + 0.3 * hoverAlpha;
78 CGFloat endAlpha = 0.333 * hoverAlpha;
79
80 if (themed) {
81 startAlpha = 0.2 + 0.35 * hoverAlpha;
82 endAlpha = 0.333 * hoverAlpha;
83 }
84
85 NSColor* startColor =
86 [NSColor colorWithCalibratedWhite:1.0
87 alpha:startAlpha];
88 NSColor* endColor =
89 [NSColor colorWithCalibratedWhite:1.0 - 0.15 * hoverAlpha
90 alpha:endAlpha];
91 NSGradient *gradient = [[NSGradient alloc] initWithColorsAndLocations:
92 startColor, hoverAlpha * 0.33,
93 endColor, 1.0, nil];
94
95 return [gradient autorelease];
96 }
97
34 - (void)sharedInit { 98 - (void)sharedInit {
35 shouldTheme_ = YES; 99 shouldTheme_ = YES;
36 NSColor* startColor = [NSColor colorWithCalibratedWhite:1.0 alpha:0.666]; 100 gradient_.reset([[self gradientForHoverAlpha:0.0 isThemed:NO] retain]);
37 NSColor* endColor = [NSColor colorWithCalibratedWhite:1.0 alpha:0.333];
38 gradient_.reset([[NSGradient alloc]
39 initWithColorsAndLocations:startColor, 0.33, endColor, 1.0, nil]);
40 } 101 }
41 102
42 - (void)setShouldTheme:(BOOL)shouldTheme { 103 - (void)setShouldTheme:(BOOL)shouldTheme {
43 shouldTheme_ = shouldTheme; 104 shouldTheme_ = shouldTheme;
44 } 105 }
45 106
46 - (NSImage*)underlayImage { 107 - (NSImage*)underlayImage {
47 return underlayImage_; 108 return underlayImage_;
48 } 109 }
49 110
50 - (void)setUnderlayImage:(NSImage*)image { 111 - (void)setUnderlayImage:(NSImage*)image {
51 underlayImage_.reset([image retain]); 112 underlayImage_.reset([image retain]);
52 113
53 [[self controlView] setNeedsDisplay:YES]; 114 [[self controlView] setNeedsDisplay:YES];
54 } 115 }
55 116
56 - (NSBackgroundStyle)interiorBackgroundStyle { 117 - (NSBackgroundStyle)interiorBackgroundStyle {
57 return [self isHighlighted] ? 118 return [self isHighlighted] ?
58 NSBackgroundStyleLowered : NSBackgroundStyleRaised; 119 NSBackgroundStyleLowered : NSBackgroundStyleRaised;
59 } 120 }
60 121
61 - (void)mouseEntered:(NSEvent *)theEvent { 122 - (void)mouseEntered:(NSEvent *)theEvent {
62 isMouseInside_ = YES; 123 [self setMouseInside:YES animate:YES];
63 [[self controlView] setNeedsDisplay:YES];
64 } 124 }
65 125
66 - (void)mouseExited:(NSEvent *)theEvent { 126 - (void)mouseExited:(NSEvent *)theEvent {
67 isMouseInside_ = NO; 127 [self setMouseInside:NO animate:YES];
68 [[self controlView] setNeedsDisplay:YES];
69 } 128 }
70 129
71 - (BOOL)isMouseInside { 130 - (BOOL)isMouseInside {
72 return trackingArea_ && isMouseInside_; 131 return trackingArea_ && isMouseInside_;
73 } 132 }
74 133
75 // Since we have our own drawWithFrame:, we need to also have our own 134 // Since we have our own drawWithFrame:, we need to also have our own
76 // logic for determining when the mouse is inside for honoring this 135 // logic for determining when the mouse is inside for honoring this
77 // request. 136 // request.
78 - (void)setShowsBorderOnlyWhileMouseInside:(BOOL)showOnly { 137 - (void)setShowsBorderOnlyWhileMouseInside:(BOOL)showOnly {
(...skipping 16 matching lines...) Expand all
95 trackingArea_.reset(nil); 154 trackingArea_.reset(nil);
96 isMouseInside_ = NO; 155 isMouseInside_ = NO;
97 } 156 }
98 } 157 }
99 } 158 }
100 159
101 - (void)drawBorderAndFillForTheme:(GTMTheme*)theme 160 - (void)drawBorderAndFillForTheme:(GTMTheme*)theme
102 controlView:(NSView*)controlView 161 controlView:(NSView*)controlView
103 outerPath:(NSBezierPath*)outerPath 162 outerPath:(NSBezierPath*)outerPath
104 innerPath:(NSBezierPath*)innerPath 163 innerPath:(NSBezierPath*)innerPath
164 showClickedGradient:(BOOL)showClickedGradient
105 showHighlightGradient:(BOOL)showHighlightGradient 165 showHighlightGradient:(BOOL)showHighlightGradient
106 showClickedGradient:(BOOL)showClickedGradient 166 hoverAlpha:(CGFloat)hoverAlpha
107 active:(BOOL)active 167 active:(BOOL)active
108 cellFrame:(NSRect)cellFrame { 168 cellFrame:(NSRect)cellFrame {
109 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.25] set];
110 [outerPath stroke];
111
112 NSImage* backgroundImage = 169 NSImage* backgroundImage =
113 [theme backgroundImageForStyle:GTMThemeStyleToolBarButton state:YES]; 170 [theme backgroundImageForStyle:GTMThemeStyleToolBarButton state:YES];
114 171
115 if (backgroundImage) { 172 if (backgroundImage) {
116 NSColor* patternColor = [NSColor colorWithPatternImage:backgroundImage]; 173 NSColor* patternColor = [NSColor colorWithPatternImage:backgroundImage];
117 [patternColor set]; 174 [patternColor set];
118 // Set the phase to match window. 175 // Set the phase to match window.
119 NSRect trueRect = [controlView convertRectToBase:cellFrame]; 176 NSRect trueRect = [controlView convertRectToBase:cellFrame];
120 [[NSGraphicsContext currentContext] 177 [[NSGraphicsContext currentContext]
121 setPatternPhase:NSMakePoint(NSMinX(trueRect), NSMaxY(trueRect))]; 178 setPatternPhase:NSMakePoint(NSMinX(trueRect), NSMaxY(trueRect))];
122 [innerPath fill]; 179 [innerPath fill];
123 } else { 180 } else {
124 if (showClickedGradient) { 181 if (showClickedGradient) {
125 NSGradient* gradient = 182 NSGradient* gradient =
126 [theme gradientForStyle:GTMThemeStyleToolBarButtonPressed 183 [theme gradientForStyle:GTMThemeStyleToolBarButtonPressed
127 state:active]; 184 state:active];
128 [gradient drawInBezierPath:innerPath angle:90.0]; 185 [gradient drawInBezierPath:innerPath angle:90.0];
129 } 186 }
130 } 187 }
131 188
132 if (!showClickedGradient && showHighlightGradient) { 189 BOOL isCustomTheme = backgroundImage != nil;
190
191 if (!showClickedGradient && [self isEnabled]) {
133 [NSGraphicsContext saveGraphicsState]; 192 [NSGraphicsContext saveGraphicsState];
134 [innerPath addClip]; 193 [innerPath addClip];
135 194
136 // Draw the inner glow. 195 // Draw the inner glow.
137 [innerPath setLineWidth:2]; 196 if (hoverAlpha > 0) {
138 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.9] setStroke]; 197 [innerPath setLineWidth:2];
139 [innerPath stroke]; 198 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2 * hoverAlpha] setStroke];
140 199 [innerPath stroke];
141 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.9] setStroke]; 200 }
142 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2] setFill];
143 201
144 // Draw the top inner highlight. 202 // Draw the top inner highlight.
145 NSAffineTransform* highlightTransform = [NSAffineTransform transform]; 203 NSAffineTransform* highlightTransform = [NSAffineTransform transform];
146 [highlightTransform translateXBy:1 yBy:1]; 204 [highlightTransform translateXBy:1 yBy:1];
147 scoped_nsobject<NSBezierPath> highlightPath([innerPath copy]); 205 scoped_nsobject<NSBezierPath> highlightPath([innerPath copy]);
148 [highlightPath transformUsingAffineTransform:highlightTransform]; 206 [highlightPath transformUsingAffineTransform:highlightTransform];
149 207 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2] setStroke];
150 [highlightPath stroke]; 208 [highlightPath stroke];
151 209
152 [gradient_ drawInBezierPath:innerPath angle:90.0]; 210 NSGradient *gradient = nil;
211 if (hoverAlpha == 0 && !isCustomTheme) {
212 gradient = gradient_;
213 } else {
214 gradient = [self gradientForHoverAlpha:hoverAlpha isThemed:isCustomTheme];
215 }
216 [gradient drawInBezierPath:innerPath angle:90.0];
153 217
154 [NSGraphicsContext restoreGraphicsState]; 218 [NSGraphicsContext restoreGraphicsState];
155 } 219 }
156 220
221 // Draw the outer stroke
157 NSColor* stroke = [theme strokeColorForStyle:GTMThemeStyleToolBarButton 222 NSColor* stroke = [theme strokeColorForStyle:GTMThemeStyleToolBarButton
158 state:active]; 223 state:active];
224
225 if (showClickedGradient) {
226 stroke = [NSColor colorWithCalibratedWhite:0.0 alpha:0.3];
227 }
159 [stroke setStroke]; 228 [stroke setStroke];
160 229
161 [innerPath setLineWidth:1]; 230 [innerPath setLineWidth:1];
162 [innerPath stroke]; 231 [innerPath stroke];
163 } 232 }
164 233
165
166 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { 234 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
167 // Constants from Cole. Will kConstant them once the feedback loop 235 // Constants from Cole. Will kConstant them once the feedback loop
168 // is complete. 236 // is complete.
169 NSRect drawFrame = NSInsetRect(cellFrame, 1.5, 1.5); 237 NSRect drawFrame = NSInsetRect(cellFrame, 1.5, 1.5);
170 NSRect innerFrame = NSInsetRect(cellFrame, 2, 2); 238 NSRect innerFrame = NSInsetRect(cellFrame, 2, 1);
171 ButtonType type = [[(NSControl*)controlView cell] tag]; 239 ButtonType type = [[(NSControl*)controlView cell] tag];
172 switch (type) { 240 switch (type) {
173 case kMiddleButtonType: 241 case kMiddleButtonType:
174 drawFrame.size.width += 20; 242 drawFrame.size.width += 20;
175 innerFrame.size.width += 2; 243 innerFrame.size.width += 2;
176 // Fallthrough 244 // Fallthrough
177 case kRightButtonType: 245 case kRightButtonType:
178 drawFrame.origin.x -= 20; 246 drawFrame.origin.x -= 20;
179 innerFrame.origin.x -= 2; 247 innerFrame.origin.x -= 2;
180 // Fallthrough 248 // Fallthrough
(...skipping 24 matching lines...) Expand all
205 // Stroke the borders and appropriate fill gradient. If we're borderless, 273 // Stroke the borders and appropriate fill gradient. If we're borderless,
206 // the only time we want to draw the inner gradient is if we're highlighted. 274 // the only time we want to draw the inner gradient is if we're highlighted.
207 if (([self isBordered] && ![self showsBorderOnlyWhileMouseInside]) || 275 if (([self isBordered] && ![self showsBorderOnlyWhileMouseInside]) ||
208 pressed || 276 pressed ||
209 [self isMouseInside]) { 277 [self isMouseInside]) {
210 278
211 [self drawBorderAndFillForTheme:theme 279 [self drawBorderAndFillForTheme:theme
212 controlView:controlView 280 controlView:controlView
213 outerPath:outerPath 281 outerPath:outerPath
214 innerPath:innerPath 282 innerPath:innerPath
215 showHighlightGradient:YES
216 showClickedGradient:pressed 283 showClickedGradient:pressed
284 showHighlightGradient:[self isHighlighted]
285 hoverAlpha:[self hoverAlpha]
217 active:active 286 active:active
218 cellFrame:cellFrame]; 287 cellFrame:cellFrame];
219 } 288 }
220 289
221 // If this is the left side of a segmented button, draw a slight shadow. 290 // If this is the left side of a segmented button, draw a slight shadow.
222 if (type == kLeftButtonWithShadowType) { 291 if (type == kLeftButtonWithShadowType) {
223 NSRect borderRect, contentRect; 292 NSRect borderRect, contentRect;
224 NSDivideRect(cellFrame, &borderRect, &contentRect, 1.0, NSMaxXEdge); 293 NSDivideRect(cellFrame, &borderRect, &contentRect, 1.0, NSMaxXEdge);
225 NSColor* stroke = [theme strokeColorForStyle:GTMThemeStyleToolBarButton 294 NSColor* stroke = [theme strokeColorForStyle:GTMThemeStyleToolBarButton
226 state:active]; 295 state:active];
227 [[stroke colorWithAlphaComponent:0.2] set]; 296 [[stroke colorWithAlphaComponent:0.2] set];
228 NSRectFillUsingOperation(NSInsetRect(borderRect, 0, 2), 297 NSRectFillUsingOperation(NSInsetRect(borderRect, 0, 2),
229 NSCompositeSourceOver); 298 NSCompositeSourceOver);
230 innerFrame.size.width -= 1.0; 299 innerFrame.size.width -= 1.0;
231 } 300 }
232 [self drawInteriorWithFrame:innerFrame inView:controlView]; 301 [self drawInteriorWithFrame:innerFrame inView:controlView];
233 } 302 }
234 303
235 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { 304 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
236 GTMTheme* theme = [controlView gtm_theme]; 305 GTMTheme* theme = [controlView gtm_theme];
237 306
238 if (shouldTheme_) { 307 if (shouldTheme_) {
239 BOOL isTemplate = [[self image] isTemplate]; 308 BOOL isTemplate = [[self image] isTemplate];
240 309
241 [NSGraphicsContext saveGraphicsState]; 310 [NSGraphicsContext saveGraphicsState];
242 311
243 CGContextRef context = 312 CGContextRef context =
244 (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]); 313 (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]);
245 314
315 NSColor* color = [theme iconColorForStyle:GTMThemeStyleToolBarButton
316 state:YES];
317
246 if (isTemplate) { 318 if (isTemplate) {
247 scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]); 319 scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
248 [shadow setShadowColor:[NSColor whiteColor]]; 320 NSColor *shadowColor = [color gtm_legibleTextColor];
321 shadowColor = [shadowColor colorWithAlphaComponent:0.25];
322 [shadow setShadowColor:shadowColor];
249 [shadow setShadowOffset:NSMakeSize(0, -1.0)]; 323 [shadow setShadowOffset:NSMakeSize(0, -1.0)];
250 [shadow setShadowBlurRadius:1.0]; 324 [shadow setShadowBlurRadius:1.0];
251 [shadow set]; 325 [shadow set];
252 } 326 }
253 327
254 [self drawUnderlayImageWithFrame:cellFrame inView:controlView]; 328 [self drawUnderlayImageWithFrame:cellFrame inView:controlView];
255 329
256 CGContextBeginTransparencyLayer(context, 0); 330 CGContextBeginTransparencyLayer(context, 0);
257 NSRect imageRect = NSZeroRect; 331 NSRect imageRect = NSZeroRect;
258 imageRect.size = [[self image] size]; 332 imageRect.size = [[self image] size];
333 NSRect drawRect = [self imageRectForBounds:cellFrame];
259 [[self image] setFlipped:[controlView isFlipped]]; 334 [[self image] setFlipped:[controlView isFlipped]];
260 [[self image] drawInRect:[self imageRectForBounds:cellFrame] 335 [[self image] drawInRect:drawRect
261 fromRect:imageRect 336 fromRect:imageRect
262 operation:NSCompositeSourceOver 337 operation:NSCompositeSourceOver
263 fraction:[self isEnabled] ? 1.0 : 0.5]; 338 fraction:[self isEnabled] ? 1.0 : 0.5];
264 if (isTemplate) { 339 if (isTemplate) {
265 NSColor* color = [theme iconColorForStyle:GTMThemeStyleToolBarButton
266 state:YES];
267 if (color) { 340 if (color) {
268 [color set]; 341 [color set];
269 NSRectFillUsingOperation(cellFrame, NSCompositeSourceAtop); 342 NSRectFillUsingOperation(cellFrame, NSCompositeSourceAtop);
270 } 343 }
271 } 344 }
272 345
273 CGContextEndTransparencyLayer(context); 346 CGContextEndTransparencyLayer(context);
274 [NSGraphicsContext restoreGraphicsState]; 347 [NSGraphicsContext restoreGraphicsState];
275 } else { 348 } else {
276 [self drawUnderlayImageWithFrame:cellFrame inView:controlView]; 349 [self drawUnderlayImageWithFrame:cellFrame inView:controlView];
(...skipping 12 matching lines...) Expand all
289 imageRect.size = [underlayImage_ size]; 362 imageRect.size = [underlayImage_ size];
290 [underlayImage_ setFlipped:[controlView isFlipped]]; 363 [underlayImage_ setFlipped:[controlView isFlipped]];
291 [underlayImage_ drawInRect:[self imageRectForBounds:cellFrame] 364 [underlayImage_ drawInRect:[self imageRectForBounds:cellFrame]
292 fromRect:imageRect 365 fromRect:imageRect
293 operation:NSCompositeSourceOver 366 operation:NSCompositeSourceOver
294 fraction:[self isEnabled] ? 1.0 : 0.5]; 367 fraction:[self isEnabled] ? 1.0 : 0.5];
295 } 368 }
296 } 369 }
297 370
298 @end 371 @end
OLDNEW
« no previous file with comments | « chrome/browser/cocoa/gradient_button_cell.h ('k') | chrome/browser/cocoa/gradient_button_cell_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698