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.