aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2010-05-09 16:18:34 +0000
committerrowanbeentje <rowan@beent.je>2010-05-09 16:18:34 +0000
commit91fe90f0f75cbfd14933f00c40e8cee17937b30c (patch)
tree92a477ff74c99211becc6cb4f2011dd1f147c3d7 /Source
parent4144a5e1b78480fd86994a9c255c9a0fb98db48b (diff)
downloadsequelpro-91fe90f0f75cbfd14933f00c40e8cee17937b30c.tar.gz
sequelpro-91fe90f0f75cbfd14933f00c40e8cee17937b30c.tar.bz2
sequelpro-91fe90f0f75cbfd14933f00c40e8cee17937b30c.zip
- Update task progress spinner to draw on the main thread rather than a background thread; should fix a number of issues logged by the crash reporter
- Update indicator code to merged master incorporating our changes, reworked and improved
Diffstat (limited to 'Source')
-rw-r--r--Source/TableDocument.m1
-rw-r--r--Source/YRKSpinningProgressIndicator.h27
-rw-r--r--Source/YRKSpinningProgressIndicator.m108
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