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

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

Issue 2407343002: cocoa browser: fix meaning of "continuous pulsing" (Closed)
Patch Set: setIsContinuousPulsing -> setPulseIsStuckOn Created 4 years, 2 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <cmath> 7 #include <cmath>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #import "base/mac/scoped_nsobject.h" 10 #import "base/mac/scoped_nsobject.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 43
44 // Note: due to a bug (?), drawWithFrame:inView: does not call 44 // Note: due to a bug (?), drawWithFrame:inView: does not call
45 // drawBorderAndFillForTheme::::: unless the mouse is inside. The net 45 // drawBorderAndFillForTheme::::: unless the mouse is inside. The net
46 // effect is that our "fade out" when the mouse leaves becaumes 46 // effect is that our "fade out" when the mouse leaves becaumes
47 // instantaneous. When I "fixed" it things looked horrible; the 47 // instantaneous. When I "fixed" it things looked horrible; the
48 // hover-overed bookmark button would stay highlit for 0.4 seconds 48 // hover-overed bookmark button would stay highlit for 0.4 seconds
49 // which felt like latency/lag. I'm leaving the "bug" in place for 49 // which felt like latency/lag. I'm leaving the "bug" in place for
50 // now so we don't suck. -jrg 50 // now so we don't suck. -jrg
51 static const NSTimeInterval kAnimationHideDuration = 0.4; 51 static const NSTimeInterval kAnimationHideDuration = 0.4;
52 52
53 static const NSTimeInterval kAnimationContinuousCycleDuration = 0.4;
54
55 @implementation GradientButtonCell 53 @implementation GradientButtonCell
56 54
57 @synthesize hoverAlpha = hoverAlpha_; 55 @synthesize hoverAlpha = hoverAlpha_;
58 56
59 // For nib instantiations 57 // For nib instantiations
60 - (id)initWithCoder:(NSCoder*)decoder { 58 - (id)initWithCoder:(NSCoder*)decoder {
61 if ((self = [super initWithCoder:decoder])) { 59 if ((self = [super initWithCoder:decoder])) {
62 [self sharedInit]; 60 [self sharedInit];
63 } 61 }
64 return self; 62 return self;
(...skipping 11 matching lines...) Expand all
76 if (trackingArea_) { 74 if (trackingArea_) {
77 [[self controlView] removeTrackingArea:trackingArea_]; 75 [[self controlView] removeTrackingArea:trackingArea_];
78 trackingArea_.reset(); 76 trackingArea_.reset();
79 } 77 }
80 [super dealloc]; 78 [super dealloc];
81 } 79 }
82 80
83 // Return YES if we are pulsing (towards another state or continuously). 81 // Return YES if we are pulsing (towards another state or continuously).
84 - (BOOL)pulsing { 82 - (BOOL)pulsing {
85 if ((pulseState_ == gradient_button_cell::kPulsingOn) || 83 if ((pulseState_ == gradient_button_cell::kPulsingOn) ||
86 (pulseState_ == gradient_button_cell::kPulsingOff) || 84 (pulseState_ == gradient_button_cell::kPulsingOff))
87 (pulseState_ == gradient_button_cell::kPulsingContinuous))
88 return YES; 85 return YES;
89 return NO; 86 return NO;
90 } 87 }
91 88
92 // Perform one pulse step when animating a pulse. 89 // Perform one pulse step when animating a pulse.
93 - (void)performOnePulseStep { 90 - (void)performOnePulseStep {
94 NSTimeInterval thisUpdate = [NSDate timeIntervalSinceReferenceDate]; 91 NSTimeInterval thisUpdate = [NSDate timeIntervalSinceReferenceDate];
95 NSTimeInterval elapsed = thisUpdate - lastHoverUpdate_; 92 NSTimeInterval elapsed = thisUpdate - lastHoverUpdate_;
96 CGFloat opacity = [self hoverAlpha]; 93 CGFloat opacity = [self hoverAlpha];
97 94
98 // Update opacity based on state. 95 // Update opacity based on state.
99 // Adjust state if we have finished. 96 // Adjust state if we have finished.
100 switch (pulseState_) { 97 switch (pulseState_) {
101 case gradient_button_cell::kPulsingOn: 98 case gradient_button_cell::kPulsingOn:
102 opacity += elapsed / kAnimationShowDuration; 99 opacity += elapsed / kAnimationShowDuration;
103 if (opacity > 1.0) { 100 if (opacity > 1.0) {
104 [self setPulseState:gradient_button_cell::kPulsedOn]; 101 [self setPulseState:gradient_button_cell::kPulsedOn];
105 return; 102 return;
106 } 103 }
107 break; 104 break;
108 case gradient_button_cell::kPulsingOff: 105 case gradient_button_cell::kPulsingOff:
109 opacity -= elapsed / kAnimationHideDuration; 106 opacity -= elapsed / kAnimationHideDuration;
110 if (opacity < 0.0) { 107 if (opacity < 0.0) {
111 [self setPulseState:gradient_button_cell::kPulsedOff]; 108 [self setPulseState:gradient_button_cell::kPulsedOff];
112 return; 109 return;
113 } 110 }
114 break; 111 break;
115 case gradient_button_cell::kPulsingContinuous: 112 case gradient_button_cell::kPulsingStuckOn:
116 opacity += elapsed / kAnimationContinuousCycleDuration * pulseMultiplier_; 113 outerStrokeAlphaMult_ = 1.0;
117 if (opacity > 1.0) {
118 opacity = 1.0;
119 pulseMultiplier_ *= -1.0;
120 } else if (opacity < 0.0) {
121 opacity = 0.0;
122 pulseMultiplier_ *= -1.0;
123 }
124 outerStrokeAlphaMult_ = opacity;
125 break; 114 break;
126 default: 115 default:
127 NOTREACHED() << "unknown pulse state"; 116 NOTREACHED() << "unknown pulse state";
128 } 117 }
129 118
130 // Update our control. 119 // Update our control.
131 lastHoverUpdate_ = thisUpdate; 120 lastHoverUpdate_ = thisUpdate;
132 [self setHoverAlpha:opacity]; 121 [self setHoverAlpha:opacity];
133 [[self controlView] setNeedsDisplay:YES]; 122 [[self controlView] setNeedsDisplay:YES];
134 123
135 // If our state needs it, keep going. 124 // If our state needs it, keep going.
136 if ([self pulsing]) { 125 if ([self pulsing]) {
137 [self performSelector:_cmd withObject:nil afterDelay:0.02]; 126 [self performSelector:_cmd withObject:nil afterDelay:0.02];
138 } 127 }
139 } 128 }
140 129
141 - (gradient_button_cell::PulseState)pulseState { 130 - (gradient_button_cell::PulseState)pulseState {
142 return pulseState_; 131 return pulseState_;
143 } 132 }
144 133
145 // Set the pulsing state. This can either set the pulse to on or off 134 // Set the pulsing state. This can either set the pulse to on or off
146 // immediately (e.g. kPulsedOn, kPulsedOff) or initiate an animated 135 // immediately (e.g. kPulsedOn, kPulsedOff) or initiate an animated
147 // state change. 136 // state change.
148 - (void)setPulseState:(gradient_button_cell::PulseState)pstate { 137 - (void)setPulseState:(gradient_button_cell::PulseState)pstate {
149 pulseState_ = pstate; 138 pulseState_ = pstate;
150 pulseMultiplier_ = 0.0;
151 [NSObject cancelPreviousPerformRequestsWithTarget:self]; 139 [NSObject cancelPreviousPerformRequestsWithTarget:self];
152 lastHoverUpdate_ = [NSDate timeIntervalSinceReferenceDate]; 140 lastHoverUpdate_ = [NSDate timeIntervalSinceReferenceDate];
153 141
154 switch (pstate) { 142 switch (pstate) {
155 case gradient_button_cell::kPulsedOn: 143 case gradient_button_cell::kPulsedOn:
156 case gradient_button_cell::kPulsedOff: 144 case gradient_button_cell::kPulsedOff:
157 outerStrokeAlphaMult_ = 1.0; 145 outerStrokeAlphaMult_ = 1.0;
158 [self setHoverAlpha:((pulseState_ == gradient_button_cell::kPulsedOn) ? 146 [self setHoverAlpha:((pulseState_ == gradient_button_cell::kPulsedOn) ?
159 1.0 : 0.0)]; 147 1.0 : 0.0)];
160 [[self controlView] setNeedsDisplay:YES]; 148 [[self controlView] setNeedsDisplay:YES];
161 break; 149 break;
162 case gradient_button_cell::kPulsingOn: 150 case gradient_button_cell::kPulsingOn:
163 case gradient_button_cell::kPulsingOff: 151 case gradient_button_cell::kPulsingOff:
164 outerStrokeAlphaMult_ = 1.0; 152 outerStrokeAlphaMult_ = 1.0;
165 // Set initial value then engage timer. 153 // Set initial value then engage timer.
166 [self setHoverAlpha:((pulseState_ == gradient_button_cell::kPulsingOn) ? 154 [self setHoverAlpha:((pulseState_ == gradient_button_cell::kPulsingOn) ?
167 0.0 : 1.0)]; 155 0.0 : 1.0)];
168 [self performOnePulseStep]; 156 [self performOnePulseStep];
169 break; 157 break;
170 case gradient_button_cell::kPulsingContinuous: 158 case gradient_button_cell::kPulsingStuckOn:
171 // Semantics of continuous pulsing are that we pulse independent 159 // Semantics of continuous pulsing are that we pulse independent
172 // of mouse position. 160 // of mouse position.
173 pulseMultiplier_ = 1.0;
174 [self performOnePulseStep]; 161 [self performOnePulseStep];
175 break; 162 break;
176 default: 163 default:
177 CHECK(0); 164 CHECK(0);
178 break; 165 break;
179 } 166 }
180 } 167 }
181 168
182 - (void)safelyStopPulsing { 169 - (void)safelyStopPulsing {
183 [NSObject cancelPreviousPerformRequestsWithTarget:self]; 170 [NSObject cancelPreviousPerformRequestsWithTarget:self];
184 } 171 }
185 172
186 - (void)setIsContinuousPulsing:(BOOL)continuous { 173 - (void)setPulseIsStuckOn:(BOOL)on {
187 if (!continuous && pulseState_ != gradient_button_cell::kPulsingContinuous) 174 if (!on && pulseState_ != gradient_button_cell::kPulsingStuckOn)
188 return; 175 return;
189 if (continuous) { 176 if (on) {
190 [self setPulseState:gradient_button_cell::kPulsingContinuous]; 177 [self setPulseState:gradient_button_cell::kPulsingStuckOn];
191 } else { 178 } else {
192 [self setPulseState:(isMouseInside_ ? gradient_button_cell::kPulsedOn : 179 [self setPulseState:(isMouseInside_ ? gradient_button_cell::kPulsedOn :
193 gradient_button_cell::kPulsedOff)]; 180 gradient_button_cell::kPulsedOff)];
194 } 181 }
195 } 182 }
196 183
197 - (BOOL)isContinuousPulsing { 184 - (BOOL)isPulseStuckOn {
198 return (pulseState_ == gradient_button_cell::kPulsingContinuous) ? 185 return (pulseState_ == gradient_button_cell::kPulsingStuckOn) ?
199 YES : NO; 186 YES : NO;
200 } 187 }
201 188
202 #if 1 189 #if 1
203 // If we are not continuously pulsing, perform a pulse animation to 190 // If we are not continuously pulsing, perform a pulse animation to
204 // reflect our new state. 191 // reflect our new state.
205 - (void)setMouseInside:(BOOL)flag animate:(BOOL)animated { 192 - (void)setMouseInside:(BOOL)flag animate:(BOOL)animated {
206 isMouseInside_ = flag; 193 isMouseInside_ = flag;
207 if (pulseState_ != gradient_button_cell::kPulsingContinuous) { 194 if (pulseState_ != gradient_button_cell::kPulsingStuckOn) {
208 if (animated) { 195 if (animated) {
209 // In Material Design, if the button is already fully on, don't pulse it 196 // In Material Design, if the button is already fully on, don't pulse it
210 // on again if the mouse is within its bounds. 197 // on again if the mouse is within its bounds.
211 if ([self tag] == [self isMaterialDesignButtonType] && 198 if ([self tag] == [self isMaterialDesignButtonType] &&
212 isMouseInside_ && pulseState_ == gradient_button_cell::kPulsedOn) { 199 isMouseInside_ && pulseState_ == gradient_button_cell::kPulsedOn) {
213 return; 200 return;
214 } 201 }
215 202
216 [self setPulseState:(isMouseInside_ ? gradient_button_cell::kPulsingOn : 203 [self setPulseState:(isMouseInside_ ? gradient_button_cell::kPulsingOn :
217 gradient_button_cell::kPulsingOff)]; 204 gradient_button_cell::kPulsingOff)];
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 NSGradient* gradient = [[NSGradient alloc] initWithColorsAndLocations: 270 NSGradient* gradient = [[NSGradient alloc] initWithColorsAndLocations:
284 startColor, hoverAlpha * 0.33, 271 startColor, hoverAlpha * 0.33,
285 endColor, 1.0, nil]; 272 endColor, 1.0, nil];
286 273
287 return [gradient autorelease]; 274 return [gradient autorelease];
288 } 275 }
289 276
290 - (void)sharedInit { 277 - (void)sharedInit {
291 shouldTheme_ = YES; 278 shouldTheme_ = YES;
292 pulseState_ = gradient_button_cell::kPulsedOff; 279 pulseState_ = gradient_button_cell::kPulsedOff;
293 pulseMultiplier_ = 1.0;
294 outerStrokeAlphaMult_ = 1.0; 280 outerStrokeAlphaMult_ = 1.0;
295 gradient_.reset([[self gradientForHoverAlpha:0.0 isThemed:NO] retain]); 281 gradient_.reset([[self gradientForHoverAlpha:0.0 isThemed:NO] retain]);
296 } 282 }
297 283
298 - (void)setShouldTheme:(BOOL)shouldTheme { 284 - (void)setShouldTheme:(BOOL)shouldTheme {
299 shouldTheme_ = shouldTheme; 285 shouldTheme_ = shouldTheme;
300 } 286 }
301 287
302 - (NSImage*)overlayImage { 288 - (NSImage*)overlayImage {
303 return overlayImage_.get(); 289 return overlayImage_.get();
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 // Stroke the borders and appropriate fill gradient. If we're borderless, the 582 // Stroke the borders and appropriate fill gradient. If we're borderless, the
597 // only time we want to draw the inner gradient is if we're highlighted or if 583 // only time we want to draw the inner gradient is if we're highlighted or if
598 // we're drawing the focus ring manually. In Material Design, the "border" is 584 // we're drawing the focus ring manually. In Material Design, the "border" is
599 // actually a highlight, which should be drawn if 585 // actually a highlight, which should be drawn if
600 // |showsBorderOnlyWhileMouseInside| is true. 586 // |showsBorderOnlyWhileMouseInside| is true.
601 BOOL hasMaterialHighlight = 587 BOOL hasMaterialHighlight =
602 [self isMaterialDesignButtonType] && 588 [self isMaterialDesignButtonType] &&
603 ![self showsBorderOnlyWhileMouseInside] && 589 ![self showsBorderOnlyWhileMouseInside] &&
604 enabled; 590 enabled;
605 if (([self isBordered] && ![self showsBorderOnlyWhileMouseInside]) || 591 if (([self isBordered] && ![self showsBorderOnlyWhileMouseInside]) ||
606 pressed || [self isMouseInside] || [self isContinuousPulsing] || 592 pressed || [self isMouseInside] || [self isPulseStuckOn] ||
607 hasMaterialHighlight) { 593 hasMaterialHighlight) {
608 // When pulsing we want the bookmark to stand out a little more. 594 // When pulsing we want the bookmark to stand out a little more.
609 BOOL showClickedGradient = pressed || 595 BOOL showClickedGradient = pressed ||
610 (pulseState_ == gradient_button_cell::kPulsingContinuous); 596 (pulseState_ == gradient_button_cell::kPulsingStuckOn);
611 BOOL showHighlightGradient = [self isHighlighted] || hasMaterialHighlight; 597 BOOL showHighlightGradient = [self isHighlighted] || hasMaterialHighlight;
612 598
613 [self drawBorderAndFillForTheme:themeProvider 599 [self drawBorderAndFillForTheme:themeProvider
614 controlView:controlView 600 controlView:controlView
615 innerPath:innerPath 601 innerPath:innerPath
616 showClickedGradient:showClickedGradient 602 showClickedGradient:showClickedGradient
617 showHighlightGradient:showHighlightGradient 603 showHighlightGradient:showHighlightGradient
618 hoverAlpha:[self hoverAlpha] 604 hoverAlpha:[self hoverAlpha]
619 active:active 605 active:active
620 cellFrame:cellFrame 606 cellFrame:cellFrame
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 options:options 845 options:options
860 owner:self 846 owner:self
861 userInfo:nil]); 847 userInfo:nil]);
862 if (isMouseInside_ != mouseInView) { 848 if (isMouseInside_ != mouseInView) {
863 [self setMouseInside:mouseInView animate:NO]; 849 [self setMouseInside:mouseInView animate:NO];
864 [controlView setNeedsDisplay:YES]; 850 [controlView setNeedsDisplay:YES];
865 } 851 }
866 } 852 }
867 853
868 @end 854 @end
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/gradient_button_cell.h ('k') | chrome/browser/ui/cocoa/gradient_button_cell_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698