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

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

Issue 440001: Mac: improve hover/clicked state appearance of bookmark bar buttons. (Closed)
Patch Set: Changes per reviews, added TODO, a few drive-by style fixes. Created 11 years, 1 month 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #import "base/scoped_nsobject.h"
6 #include "chrome/browser/cocoa/gradient_button_cell.h" 6 #include "chrome/browser/cocoa/gradient_button_cell.h"
7 #import "third_party/GTM/AppKit/GTMTheme.h" 7 #import "third_party/GTM/AppKit/GTMTheme.h"
8 #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h" 8 #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h"
9 9
10 @interface GradientButtonCell (Private) 10 @interface GradientButtonCell (Private)
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 } 65 }
66 66
67 // For programmatic instantiations 67 // For programmatic instantiations
68 - (id)initTextCell:(NSString*)string { 68 - (id)initTextCell:(NSString*)string {
69 if ((self = [super initTextCell:string])) { 69 if ((self = [super initTextCell:string])) {
70 [self sharedInit]; 70 [self sharedInit];
71 } 71 }
72 return self; 72 return self;
73 } 73 }
74 74
75 - (NSGradient *)gradientForHoverAlpha:(CGFloat)hoverAlpha 75 - (NSGradient*)gradientForHoverAlpha:(CGFloat)hoverAlpha
76 isThemed:(BOOL)themed { 76 isThemed:(BOOL)themed {
77 CGFloat startAlpha = 0.6 + 0.3 * hoverAlpha; 77 CGFloat startAlpha = 0.6 + 0.3 * hoverAlpha;
78 CGFloat endAlpha = 0.333 * hoverAlpha; 78 CGFloat endAlpha = 0.333 * hoverAlpha;
79 79
80 if (themed) { 80 if (themed) {
81 startAlpha = 0.2 + 0.35 * hoverAlpha; 81 startAlpha = 0.2 + 0.35 * hoverAlpha;
82 endAlpha = 0.333 * hoverAlpha; 82 endAlpha = 0.333 * hoverAlpha;
83 } 83 }
84 84
85 NSColor* startColor = 85 NSColor* startColor =
86 [NSColor colorWithCalibratedWhite:1.0 86 [NSColor colorWithCalibratedWhite:1.0
87 alpha:startAlpha]; 87 alpha:startAlpha];
88 NSColor* endColor = 88 NSColor* endColor =
89 [NSColor colorWithCalibratedWhite:1.0 - 0.15 * hoverAlpha 89 [NSColor colorWithCalibratedWhite:1.0 - 0.15 * hoverAlpha
90 alpha:endAlpha]; 90 alpha:endAlpha];
91 NSGradient *gradient = [[NSGradient alloc] initWithColorsAndLocations: 91 NSGradient* gradient = [[NSGradient alloc] initWithColorsAndLocations:
92 startColor, hoverAlpha * 0.33, 92 startColor, hoverAlpha * 0.33,
93 endColor, 1.0, nil]; 93 endColor, 1.0, nil];
94 94
95 return [gradient autorelease]; 95 return [gradient autorelease];
96 } 96 }
97 97
98 - (void)sharedInit { 98 - (void)sharedInit {
99 shouldTheme_ = YES; 99 shouldTheme_ = YES;
100 gradient_.reset([[self gradientForHoverAlpha:0.0 isThemed:NO] retain]); 100 gradient_.reset([[self gradientForHoverAlpha:0.0 isThemed:NO] retain]);
101 } 101 }
102 102
103 - (void)setShouldTheme:(BOOL)shouldTheme { 103 - (void)setShouldTheme:(BOOL)shouldTheme {
104 shouldTheme_ = shouldTheme; 104 shouldTheme_ = shouldTheme;
105 } 105 }
106 106
107 - (NSImage*)underlayImage { 107 - (NSImage*)underlayImage {
108 return underlayImage_; 108 return underlayImage_;
109 } 109 }
110 110
111 - (void)setUnderlayImage:(NSImage*)image { 111 - (void)setUnderlayImage:(NSImage*)image {
112 underlayImage_.reset([image retain]); 112 underlayImage_.reset([image retain]);
113 113
114 [[self controlView] setNeedsDisplay:YES]; 114 [[self controlView] setNeedsDisplay:YES];
115 } 115 }
116 116
117 - (NSBackgroundStyle)interiorBackgroundStyle { 117 - (NSBackgroundStyle)interiorBackgroundStyle {
118 return [self isHighlighted] ? 118 // Never lower the interior, since that just leads to a weird shadow which can
119 NSBackgroundStyleLowered : NSBackgroundStyleRaised; 119 // often interact badly with the theme.
120 return NSBackgroundStyleRaised;
120 } 121 }
121 122
122 - (void)mouseEntered:(NSEvent *)theEvent { 123 - (void)mouseEntered:(NSEvent*)theEvent {
123 [self setMouseInside:YES animate:YES]; 124 [self setMouseInside:YES animate:YES];
124 } 125 }
125 126
126 - (void)mouseExited:(NSEvent *)theEvent { 127 - (void)mouseExited:(NSEvent*)theEvent {
127 [self setMouseInside:NO animate:YES]; 128 [self setMouseInside:NO animate:YES];
128 } 129 }
129 130
130 - (BOOL)isMouseInside { 131 - (BOOL)isMouseInside {
131 return trackingArea_ && isMouseInside_; 132 return trackingArea_ && isMouseInside_;
132 } 133 }
133 134
134 // Since we have our own drawWithFrame:, we need to also have our own 135 // Since we have our own drawWithFrame:, we need to also have our own
135 // logic for determining when the mouse is inside for honoring this 136 // logic for determining when the mouse is inside for honoring this
136 // request. 137 // request.
(...skipping 13 matching lines...) Expand all
150 [[self controlView] addTrackingArea:trackingArea_]; 151 [[self controlView] addTrackingArea:trackingArea_];
151 } else { 152 } else {
152 if (trackingArea_) { 153 if (trackingArea_) {
153 [[self controlView] removeTrackingArea:trackingArea_]; 154 [[self controlView] removeTrackingArea:trackingArea_];
154 trackingArea_.reset(nil); 155 trackingArea_.reset(nil);
155 isMouseInside_ = NO; 156 isMouseInside_ = NO;
156 } 157 }
157 } 158 }
158 } 159 }
159 160
161 // TODO(viettrungluu): clean up/reorganize.
160 - (void)drawBorderAndFillForTheme:(GTMTheme*)theme 162 - (void)drawBorderAndFillForTheme:(GTMTheme*)theme
161 controlView:(NSView*)controlView 163 controlView:(NSView*)controlView
162 outerPath:(NSBezierPath*)outerPath 164 outerPath:(NSBezierPath*)outerPath
163 innerPath:(NSBezierPath*)innerPath 165 innerPath:(NSBezierPath*)innerPath
164 showClickedGradient:(BOOL)showClickedGradient 166 showClickedGradient:(BOOL)showClickedGradient
165 showHighlightGradient:(BOOL)showHighlightGradient 167 showHighlightGradient:(BOOL)showHighlightGradient
166 hoverAlpha:(CGFloat)hoverAlpha 168 hoverAlpha:(CGFloat)hoverAlpha
167 active:(BOOL)active 169 active:(BOOL)active
168 cellFrame:(NSRect)cellFrame 170 cellFrame:(NSRect)cellFrame
169 defaultGradient:(NSGradient*)defaultGradient { 171 defaultGradient:(NSGradient*)defaultGradient {
170 NSImage* backgroundImage = 172 BOOL isFlatButton = [self showsBorderOnlyWhileMouseInside];
171 [theme backgroundImageForStyle:GTMThemeStyleToolBarButton state:YES];
172 173
173 if (!defaultGradient) 174 // For flat (unbordered when not hovered) buttons, never use the toolbar
174 defaultGradient = gradient_; 175 // button background image, but the modest gradient used for themed buttons.
176 // To make things even more modest, scale the hover alpha down by 40 percent
177 // unless clicked.
178 NSImage* backgroundImage;
179 BOOL useThemeGradient;
180 if (isFlatButton) {
181 backgroundImage = nil;
182 useThemeGradient = YES;
183 if (!showClickedGradient)
184 hoverAlpha *= 0.6;
185 } else {
186 backgroundImage = [theme backgroundImageForStyle:GTMThemeStyleToolBarButton
187 state:YES];
188 useThemeGradient = backgroundImage ? YES : NO;
189 }
175 190
191 // The basic gradient shown inside; see above.
192 NSGradient* gradient;
193 if (hoverAlpha == 0 && !useThemeGradient) {
194 gradient = defaultGradient ? defaultGradient
195 : gradient_;
196 } else {
197 gradient = [self gradientForHoverAlpha:hoverAlpha
198 isThemed:useThemeGradient];
199 }
200
201 // If we're drawing a background image, show that; else possibly show the
202 // clicked gradient.
176 if (backgroundImage) { 203 if (backgroundImage) {
177 NSColor* patternColor = [NSColor colorWithPatternImage:backgroundImage]; 204 NSColor* patternColor = [NSColor colorWithPatternImage:backgroundImage];
178 [patternColor set]; 205 [patternColor set];
179 // Set the phase to match window. 206 // Set the phase to match window.
180 NSRect trueRect = [controlView convertRectToBase:cellFrame]; 207 NSRect trueRect = [controlView convertRectToBase:cellFrame];
181 [[NSGraphicsContext currentContext] 208 [[NSGraphicsContext currentContext]
182 setPatternPhase:NSMakePoint(NSMinX(trueRect), NSMaxY(trueRect))]; 209 setPatternPhase:NSMakePoint(NSMinX(trueRect), NSMaxY(trueRect))];
183 [innerPath fill]; 210 [innerPath fill];
184 } else { 211 } else {
185 if (showClickedGradient) { 212 if (showClickedGradient) {
186 NSGradient* gradient = 213 NSGradient* clickedGradient;
187 [theme gradientForStyle:GTMThemeStyleToolBarButtonPressed 214 if (isFlatButton) {
188 state:active]; 215 clickedGradient = gradient;
189 [gradient drawInBezierPath:innerPath angle:90.0]; 216 } else {
217 clickedGradient =
218 [theme gradientForStyle:GTMThemeStyleToolBarButtonPressed
219 state:active];
220 }
221 [clickedGradient drawInBezierPath:innerPath angle:90.0];
190 } 222 }
191 } 223 }
192 224
193 BOOL isCustomTheme = backgroundImage != nil; 225 // Visually indicate unclicked, enabled buttons.
194
195 if (!showClickedGradient && [self isEnabled]) { 226 if (!showClickedGradient && [self isEnabled]) {
196 [NSGraphicsContext saveGraphicsState]; 227 [NSGraphicsContext saveGraphicsState];
197 [innerPath addClip]; 228 [innerPath addClip];
198 229
199 // Draw the inner glow. 230 // Draw the inner glow.
200 if (hoverAlpha > 0) { 231 if (hoverAlpha > 0) {
201 [innerPath setLineWidth:2]; 232 [innerPath setLineWidth:2];
202 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2 * hoverAlpha] setStroke]; 233 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2 * hoverAlpha] setStroke];
203 [innerPath stroke]; 234 [innerPath stroke];
204 } 235 }
205 236
206 // Draw the top inner highlight. 237 // Draw the top inner highlight.
207 NSAffineTransform* highlightTransform = [NSAffineTransform transform]; 238 NSAffineTransform* highlightTransform = [NSAffineTransform transform];
208 [highlightTransform translateXBy:1 yBy:1]; 239 [highlightTransform translateXBy:1 yBy:1];
209 scoped_nsobject<NSBezierPath> highlightPath([innerPath copy]); 240 scoped_nsobject<NSBezierPath> highlightPath([innerPath copy]);
210 [highlightPath transformUsingAffineTransform:highlightTransform]; 241 [highlightPath transformUsingAffineTransform:highlightTransform];
211 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2] setStroke]; 242 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2] setStroke];
212 [highlightPath stroke]; 243 [highlightPath stroke];
213 244
214 NSGradient *gradient = nil; 245 // Draw the gradient inside.
215 if (hoverAlpha == 0 && !isCustomTheme) {
216 gradient = defaultGradient;
217 } else {
218 gradient = [self gradientForHoverAlpha:hoverAlpha isThemed:isCustomTheme];
219 }
220 [gradient drawInBezierPath:innerPath angle:90.0]; 246 [gradient drawInBezierPath:innerPath angle:90.0];
221 247
222 [NSGraphicsContext restoreGraphicsState]; 248 [NSGraphicsContext restoreGraphicsState];
223 } 249 }
224 250
225 // Draw the outer stroke 251 // Draw the outer stroke.
226 NSColor* stroke = [theme strokeColorForStyle:GTMThemeStyleToolBarButton 252 NSColor* strokeColor = showClickedGradient ?
227 state:active]; 253 [NSColor colorWithCalibratedWhite:0.0 alpha:0.3] :
228 254 [theme strokeColorForStyle:GTMThemeStyleToolBarButton state:active];
229 if (showClickedGradient) { 255 [strokeColor setStroke];
230 stroke = [NSColor colorWithCalibratedWhite:0.0 alpha:0.3];
231 }
232 [stroke setStroke];
233 256
234 [innerPath setLineWidth:1]; 257 [innerPath setLineWidth:1];
235 [innerPath stroke]; 258 [innerPath stroke];
236 } 259 }
237 260
238 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { 261 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
239 // Constants from Cole. Will kConstant them once the feedback loop 262 // Constants from Cole. Will kConstant them once the feedback loop
240 // is complete. 263 // is complete.
241 NSRect drawFrame = NSInsetRect(cellFrame, 1.5, 1.5); 264 NSRect drawFrame = NSInsetRect(cellFrame, 1.5, 1.5);
242 NSRect innerFrame = NSInsetRect(cellFrame, 2, 1); 265 NSRect innerFrame = NSInsetRect(cellFrame, 2, 1);
(...skipping 13 matching lines...) Expand all
256 innerFrame.size.width += 2; 279 innerFrame.size.width += 2;
257 default: 280 default:
258 break; 281 break;
259 } 282 }
260 283
261 const float radius = 3.5; 284 const float radius = 3.5;
262 BOOL pressed = [self isHighlighted]; 285 BOOL pressed = [self isHighlighted];
263 NSWindow* window = [controlView window]; 286 NSWindow* window = [controlView window];
264 BOOL active = [window isKeyWindow] || [window isMainWindow]; 287 BOOL active = [window isKeyWindow] || [window isMainWindow];
265 288
266 GTMTheme *theme = [controlView gtm_theme]; 289 GTMTheme* theme = [controlView gtm_theme];
267 290
268 NSBezierPath* innerPath = 291 NSBezierPath* innerPath =
269 [NSBezierPath bezierPathWithRoundedRect:drawFrame 292 [NSBezierPath bezierPathWithRoundedRect:drawFrame
270 xRadius:radius 293 xRadius:radius
271 yRadius:radius]; 294 yRadius:radius];
272 NSBezierPath* outerPath = 295 NSBezierPath* outerPath =
273 [NSBezierPath bezierPathWithRoundedRect:NSInsetRect(drawFrame, -1, -1) 296 [NSBezierPath bezierPathWithRoundedRect:NSInsetRect(drawFrame, -1, -1)
274 xRadius:radius + 1 297 xRadius:radius + 1
275 yRadius:radius + 1]; 298 yRadius:radius + 1];
276 299
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 [NSGraphicsContext saveGraphicsState]; 338 [NSGraphicsContext saveGraphicsState];
316 339
317 CGContextRef context = 340 CGContextRef context =
318 (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]); 341 (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]);
319 342
320 NSColor* color = [theme iconColorForStyle:GTMThemeStyleToolBarButton 343 NSColor* color = [theme iconColorForStyle:GTMThemeStyleToolBarButton
321 state:YES]; 344 state:YES];
322 345
323 if (isTemplate) { 346 if (isTemplate) {
324 scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]); 347 scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
325 NSColor *shadowColor = [color gtm_legibleTextColor]; 348 NSColor* shadowColor = [color gtm_legibleTextColor];
326 shadowColor = [shadowColor colorWithAlphaComponent:0.25]; 349 shadowColor = [shadowColor colorWithAlphaComponent:0.25];
327 [shadow.get() setShadowColor:shadowColor]; 350 [shadow.get() setShadowColor:shadowColor];
328 [shadow.get() setShadowOffset:NSMakeSize(0, -1.0)]; 351 [shadow.get() setShadowOffset:NSMakeSize(0, -1.0)];
329 [shadow setShadowBlurRadius:1.0]; 352 [shadow setShadowBlurRadius:1.0];
330 [shadow set]; 353 [shadow set];
331 } 354 }
332 355
333 [self drawUnderlayImageWithFrame:cellFrame inView:controlView]; 356 [self drawUnderlayImageWithFrame:cellFrame inView:controlView];
334 357
335 CGContextBeginTransparencyLayer(context, 0); 358 CGContextBeginTransparencyLayer(context, 0);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 imageRect.size = [underlayImage_ size]; 390 imageRect.size = [underlayImage_ size];
368 [underlayImage_ setFlipped:[controlView isFlipped]]; 391 [underlayImage_ setFlipped:[controlView isFlipped]];
369 [underlayImage_ drawInRect:[self imageRectForBounds:cellFrame] 392 [underlayImage_ drawInRect:[self imageRectForBounds:cellFrame]
370 fromRect:imageRect 393 fromRect:imageRect
371 operation:NSCompositeSourceOver 394 operation:NSCompositeSourceOver
372 fraction:[self isEnabled] ? 1.0 : 0.5]; 395 fraction:[self isEnabled] ? 1.0 : 0.5];
373 } 396 }
374 } 397 }
375 398
376 @end 399 @end
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698