This is Animator.m in view mode; [Download] [Up]
/* Not generated by Interface Builder */
#import "Animator.h"
#import <appkit/Control.h>
#import <appkit/Button.h>
#import <sys/time.h>
@implementation Animator
// These are our default values for a new Animator.
static float defaultTiming, defaultThreshold;
static SEL defaultAction;
BOOL defaultRunning, defaultContinuous;
+ initialize
{
[self setDefaultTiming:0.0];
[self setDefaultThreshold:NX_BASETHRESHOLD];
[self setDefaultAction:@selector( animate:)];
[self setDefaultRunning:NO];
[self setDefaultContinuous:YES];
return self;
}
// Where our DPSTimedEntry ends up. data should be self, so that the correct
// Animator instance can be called to sendAction.
static void doAnimator( DPSTimedEntry te, double curTime, void *data)
{
if( ![(id)data continuous]) // If one-shot,
[(id)data stop:(id)data]; // stop it.
[(id)data sendAction];
}
+ new // create a new Animator.
{
self = [super new];
target=nil;
[self setTiming:defaultTiming];
[self setThreshold:defaultThreshold];
running=NO;
[self setRunning:defaultRunning];
[self setAction:defaultAction];
[self setContinuous:defaultContinuous];
startTime=elapsed=-1.0;
return self;
}
+ setDefaultTiming:(float)dtiming
{
defaultTiming=dtiming;
return self;
}
+ setDefaultThreshold:(float)dthreshold
{
defaultThreshold=dthreshold;
return self;
}
+ setDefaultAction:(SEL)daction
{
defaultAction=daction;
return self;
}
+ setDefaultRunning:(BOOL)state
{
defaultRunning=state;
return self;
}
+ setDefaultContinuous:(BOOL)state
{
defaultContinuous=state;
return self;
}
- free
{
[self stop:self];
return [super free];
}
- setTarget:anObject
{
if( target==anObject) // if already set,
return self; // just return.
target = anObject;
if( target && [anObject respondsTo:@selector( setAnimator:)])
[anObject setAnimator:self]; // anObject can store us,
// or just set us up.
return self;
}
- target { return target; }
- setTiming:(float)t
{
timing=t;
if( running)
[[self stop:self] start:self];
return self;
}
-(float)timing { return timing; }
- setThreshold:(float)t
{
threshold=t;
if( running)
[[self stop:self] start:self];
return self;
}
-(float)threshold { return threshold; }
-(double)doubleValue // return the amount of time since last call.
{
return running ? elapsed : -1.0;
}
-(float)floatValue // return as a float.
{
return [self doubleValue];
}
-(int)intValue
{
return [self doubleValue];
}
-(BOOL)continuous // return the continuous flag.
{
return continuous;
}
- setContinuous:(BOOL)state // set the continuous flag.
{
continuous=state;
}
- setAction:(SEL)theAction
{
action=theAction;
return self;
}
-(SEL)action { return action; }
- setRunning:(BOOL)state
{
return state==running ? self : [self toggleRun:self];
}
- (BOOL)running { return running; }
// These both force non-continuous.
- callAfter:(double)sec // wait and call me then.
{
[self setContinuous:NO];
[self setTiming:sec];
[self start:self];
return self;
}
- callAt:(double)absSec // call at this time.
{
[self resetValue]; // get the current time.
if( absSec-startTime<0)
absSec+=86400;
return [self callAfter:absSec-startTime];
}
- sendAction:(SEL)theAction to:theTarget
{
struct timeval curTime;
double now;
gettimeofday( &curTime, 0);
now=(float)(curTime.tv_sec)+(float)(curTime.tv_usec)/1000000.0;
elapsed=now-startTime;
if( theAction && theTarget && [theTarget respondsTo:theAction])
[theTarget perform:theAction with:self];
return self;
}
- sendAction
{
return [self sendAction:action to:target];
}
- resetValue:(double)value
{
startTime=value;
elapsed=0;
return self;
}
- resetValue
{
struct timeval curTime;
gettimeofday( &curTime, 0);
return [self resetValue:(float)(curTime.tv_sec)+(float)(curTime.tv_usec)/1000000.0];
}
- start:sender
{
if( !running)
te=DPSAddTimedEntry( timing, &doAnimator, self, threshold);
running=YES;
return [self resetValue];
}
- stop:sender
{
if( running)
DPSRemoveTimedEntry( te);
running=NO;
return self;
}
- toggleRun:sender
{
return running ? [self stop:sender] : [self start:sender];
}
- takeTimingFrom:sender
{
[self setTiming:[sender floatValue]];
return self;
}
- takeRunningFrom:sender
{
[self setRunning:[sender state]];
return self;
}
- takeContinuousFrom:sender // set continuous by sender.
{
[self setContinuous:[sender state]];
return self;
}
- copy
{
id newAnimator=[super copy];
[newAnimator setTarget:nil];
[newAnimator setTiming:[self timing]];
[newAnimator setThreshold:[self threshold]];
[newAnimator setAction:[self action]];
[newAnimator setRunning:[self running]];
[newAnimator setContinuous:[self continuous]];
return newAnimator;
}
- awake
{
if( running)
{
running=NO;
[self start:self];
}
return self;
}
- write:(NXTypedStream *)stream
{
[super write:stream];
NXWriteObjectReference( stream, target);
NXWriteTypes(stream, "ffii:", &timing, &threshold, &running, &continuous,
&action);
return self;
}
- read:(NXTypedStream *)stream
{
[super read:stream];
target=NXReadObject( stream);
NXReadTypes(stream, "ffii:", &timing, &threshold, &running, &continuous,
&action);
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.