diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/TableDocument.m | 1 | ||||
-rw-r--r-- | Source/YRKSpinningProgressIndicator.h | 27 | ||||
-rw-r--r-- | Source/YRKSpinningProgressIndicator.m | 108 |
3 files changed, 106 insertions, 30 deletions
diff --git a/Source/TableDocument.m b/Source/TableDocument.m index 724e9c60..49bde88b 100644 --- a/Source/TableDocument.m +++ b/Source/TableDocument.m @@ -1272,7 +1272,6 @@ if (_isWorkingLevel == 1 || !taskDisplayIsIndeterminate) { taskDisplayIsIndeterminate = YES; [taskProgressIndicator setIndeterminate:YES]; - [taskProgressIndicator animate:self]; [taskProgressIndicator startAnimation:self]; taskDisplayLastValue = 0; } diff --git a/Source/YRKSpinningProgressIndicator.h b/Source/YRKSpinningProgressIndicator.h index 355ebf2f..178551b9 100644 --- a/Source/YRKSpinningProgressIndicator.h +++ b/Source/YRKSpinningProgressIndicator.h @@ -11,35 +11,46 @@ NSInteger _position; NSInteger _numFins; - BOOL _isIndeterminate; - double _currentValue; - double _maxValue; - BOOL _isAnimating; + NSTimer *_animationTimer; NSThread *_animationThread; NSColor *_foreColor; NSColor *_backColor; BOOL _drawBackground; + + NSTimer *_fadeOutAnimationTimer; + BOOL _isFadingOut; + + // For determinate mode + BOOL _isIndeterminate; + double _currentValue; + double _maxValue; + + BOOL _usesThreadedAnimation; } -- (void)animate:(id)sender; + - (void)stopAnimation:(id)sender; - (void)startAnimation:(id)sender; + +// Accessors + - (NSColor *)foreColor; - (void)setForeColor:(NSColor *)value; - - (NSColor *)backColor; - (void)setBackColor:(NSColor *)value; - - (BOOL)drawBackground; - (void)setDrawBackground:(BOOL)value; - (BOOL)isIndeterminate; - (void)setIndeterminate:(BOOL)isIndeterminate; - - (double)doubleValue; - (void)setDoubleValue:(double)doubleValue; - (double)maxValue; - (void)setMaxValue:(double)maxValue; + +- (void)setUsesThreadedAnimation:(BOOL)useThreaded; +- (BOOL)usesThreadedAnimation; + @end diff --git a/Source/YRKSpinningProgressIndicator.m b/Source/YRKSpinningProgressIndicator.m index b9af4847..07e93863 100644 --- a/Source/YRKSpinningProgressIndicator.m +++ b/Source/YRKSpinningProgressIndicator.m @@ -34,7 +34,10 @@ @interface YRKSpinningProgressIndicator (YRKSpinningProgressIndicatorPrivate) +- (void)updateFrame:(NSTimer *)timer; - (void) animateInBackgroundThread; +- (void)actuallyStartAnimation; +- (void)actuallyStopAnimation; @end @@ -48,12 +51,11 @@ _position = 0; _numFins = 12; _isAnimating = NO; - _animationThread = nil; - _foreColor = nil; - _backColor = nil; + _isFadingOut = NO; _isIndeterminate = YES; _currentValue = 0.0; _maxValue = 100.0; + _usesThreadedAnimation = NO; } return self; } @@ -62,6 +64,7 @@ if (_foreColor) [_foreColor release]; if (_backColor) [_backColor release]; if (_isAnimating) [self stopAnimation:self]; + [super dealloc]; } @@ -70,12 +73,11 @@ [super viewDidMoveToWindow]; if ([self window] == nil) { - // No window? View hierarchy may be going away. Ensure animation is stopped. - [self stopAnimation:self]; + // No window? View hierarchy may be going away. Dispose timer to clear circular retain of timer to self to timer. + [self actuallyStopAnimation]; } else if (_isAnimating) { - [self stopAnimation:self]; - [self startAnimation:self]; + [self actuallyStartAnimation]; } } @@ -105,7 +107,6 @@ CGContextTranslateCTM(currentContext,[self bounds].size.width/2,[self bounds].size.height/2); if (_isIndeterminate) { - // do initial rotation to start place CGContextRotateCTM(currentContext, 3.14159*2/_numFins * _position); @@ -157,15 +158,23 @@ # pragma mark - # pragma mark Subclass -- (void)animate:(id)sender +- (void)updateFrame:(NSTimer *)timer; { - if(_position > 1) { + if(_position > 0) { _position--; } else { - _position = _numFins; + _position = _numFins - 1; + } + + if (_usesThreadedAnimation) { + // draw now instead of waiting for setNeedsDisplay (that's the whole reason + // we're animating from background thread) + [self display]; + } + else { + [self setNeedsDisplay:YES]; } - [self display]; } - (void) animateInBackgroundThread @@ -177,7 +186,7 @@ NSInteger poolFlushCounter = 0; do { - [self animate:nil]; + [self updateFrame:nil]; usleep(animationDelay); poolFlushCounter++; if (poolFlushCounter > 256) { @@ -194,23 +203,59 @@ { if (!_isIndeterminate) return; if (_isAnimating) return; + + [self actuallyStartAnimation]; _isAnimating = YES; - - _animationThread = [[NSThread alloc] initWithTarget:self selector:@selector(animateInBackgroundThread) object:nil]; - [_animationThread start]; } - (void)stopAnimation:(id)sender { + [self actuallyStopAnimation]; _isAnimating = NO; +} + +- (void)actuallyStartAnimation +{ + // Just to be safe kill any existing timer. + [self actuallyStopAnimation]; + + if ([self window]) { + // Why animate if not visible? viewDidMoveToWindow will re-call this method when needed. + if (_usesThreadedAnimation) { + _animationThread = [[NSThread alloc] initWithTarget:self selector:@selector(animateInBackgroundThread) object:nil]; + [_animationThread start]; + } + else { + _animationTimer = [[NSTimer timerWithTimeInterval:(NSTimeInterval)0.05 + target:self + selector:@selector(updateFrame:) + userInfo:nil + repeats:YES] retain]; + + [[NSRunLoop currentRunLoop] addTimer:_animationTimer forMode:NSRunLoopCommonModes]; + [[NSRunLoop currentRunLoop] addTimer:_animationTimer forMode:NSDefaultRunLoopMode]; + [[NSRunLoop currentRunLoop] addTimer:_animationTimer forMode:NSEventTrackingRunLoopMode]; + } + } +} + +- (void)actuallyStopAnimation +{ if (_animationThread) { + // we were using threaded animation [_animationThread cancel]; if (![_animationThread isFinished]) { [[NSRunLoop currentRunLoop] runMode:NSModalPanelRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.05]]; } - [_animationThread release], _animationThread = nil; + [_animationThread release]; + _animationThread = nil; } - + else if (_animationTimer) { + // we were using timer-based animation + [_animationTimer invalidate]; + [_animationTimer release]; + _animationTimer = nil; + } [self setNeedsDisplay:YES]; } @@ -277,7 +322,7 @@ { _isIndeterminate = isIndeterminate; if (!_isIndeterminate && _isAnimating) [self stopAnimation:self]; - [self displayIfNeeded]; + [self setNeedsDisplay:YES]; } - (double)doubleValue @@ -287,7 +332,10 @@ - (void)setDoubleValue:(double)doubleValue { - if (_isIndeterminate) _isIndeterminate = NO; + // Automatically put it into determinate mode if it's not already. + if (_isIndeterminate) { + [self setIndeterminate:NO]; + } _currentValue = doubleValue; [self setNeedsDisplay:YES]; } @@ -300,7 +348,25 @@ - (void)setMaxValue:(double)maxValue { _maxValue = maxValue; - [self displayIfNeeded]; + [self setNeedsDisplay:YES]; +} + +- (void)setUsesThreadedAnimation:(BOOL)useThreaded +{ + if (_usesThreadedAnimation != useThreaded) { + _usesThreadedAnimation = useThreaded; + + if (_isAnimating) { + // restart the timer to use the new mode + [self stopAnimation:self]; + [self startAnimation:self]; + } + } +} + +- (BOOL)usesThreadedAnimation +{ + return _usesThreadedAnimation; } @end |