home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1994 June / NEBULA_SE.ISO / SourceCode / Palettes / TTools / TToolsPalette / Timer.subproj / Timer.m < prev    next >
Encoding:
Text File  |  1993-11-10  |  6.4 KB  |  283 lines

  1. /* Timer.m
  2.  * Written By:  Thomas Burkholder
  3.  *
  4.  * You may freely copy, distribute, and reuse the code in this example.
  5.  * NeXT disclaims any warranty of any kind, expressed or  implied, as to its
  6.  * fitness for any particular use.
  7.  */
  8.  
  9.  
  10. #import "Timer.h"
  11.  
  12. #define DEFAULTPERIOD 1.0
  13. #define LOWPERIOD 0.05
  14. #define HIGHPERIOD MAXDOUBLE
  15.  
  16. #define DEFAULTSYNC 60
  17. #define LOWSYNC 1
  18. #define HIGHSYNC MAXINT
  19.  
  20. #define DEFAULTSTART 0.0
  21. #define LOWSTART MINDOUBLE
  22. #define HIGHSTART MAXDOUBLE
  23.  
  24. #define LOWWRAP MINDOUBLE
  25. #define HIGHWRAP MAXDOUBLE
  26.  
  27. #define DEFAULTINCREMENT 1.0
  28. #define LOWINCREMENT MINFLOAT
  29. #define HIGHINCREMENT MAXFLOAT
  30.  
  31. #define DEFAULTPRIORITY NX_BASETHRESHOLD
  32. #define LOWPRIORITY 0
  33. #define HIGHPRIORITY 30
  34.  
  35.  
  36. //#define MAX(_x,_y) (_x>_y)?_x:_y
  37. //#define MIN(__x,__y) (__x<__y)?__x:__y
  38. #define CONSTRAIN(__a,__low,__high) MIN(MAX(__a,__low),__high)
  39.  
  40. @implementation Timer
  41.  
  42. // function that does what's necessary to the object.  To maximise speed, 
  43. // methodFor: is used.
  44. void handle(DPSTimedEntry tag, double now, char *userdata)
  45. {
  46.     Timer *self = (id)userdata;
  47.  
  48.     self->value += self->incrementBy;
  49.     self->syncCounter++;
  50.     if (self->bFlags.sync && (self->syncCounter >= self->syncValue)) {
  51.         [self synchronize:self];
  52.         self->syncCounter = 0;
  53.     }
  54.     if (self->bFlags.wrap && (self->value >= self->wrapValue))
  55.         self->value = self->startValue;
  56.     if (self->actionFunc)
  57.         self->actionFunc(self->target,self->action,self);
  58.     return;
  59. }
  60.  
  61. // initializing and freeing
  62. + initialize
  63. {
  64.     if (self == [Timer class])
  65.         [self setVersion:1];
  66.     return self;
  67. }
  68.  
  69. - init
  70. {
  71.     [super init];
  72.  
  73.     entry = NULL;
  74.     period = DEFAULTPERIOD;
  75.     priority = DEFAULTPRIORITY;
  76.  
  77.     bFlags.visibleDebug = NO;
  78.     bFlags.wrap = YES;
  79.     bFlags.sync = NO;
  80.  
  81.     syncValue = DEFAULTSYNC;
  82.     value = 0.0;
  83.     startValue = DEFAULTSTART;
  84.     wrapValue = 60.0;
  85.     incrementBy = DEFAULTINCREMENT;
  86.  
  87.     target = nil;
  88.     action = (SEL)0;
  89.     actionFunc = NULL;
  90.     return self;
  91. }
  92.  
  93. - free
  94. {
  95.     if (entry) {
  96.         [self stop:self];
  97.     }
  98.     return [super free];
  99. }
  100.  
  101. // debugging methods
  102. - logError:(char *)str
  103. {
  104.     if (bFlags.visibleDebug)
  105.         NXRunAlertPanel("ERROR",str,NULL,NULL,NULL);
  106.     NXLogError(str);
  107.     return self;
  108. }
  109.  
  110. // private methods
  111. - stopEntry
  112. {
  113.     if (entry == NULL) {
  114.         [self logError:"Stop called on stopped timer!\n"];
  115.         return nil;
  116.     } else {
  117.         DPSRemoveTimedEntry(entry);
  118.         entry = NULL;
  119.     }
  120.     return self;
  121. }
  122.  
  123. - startEntry
  124. {
  125.     if (entry != NULL) {
  126.         [self stopEntry];
  127.     }
  128.  
  129.     // get function for method, so we can be super-efficient
  130.     if (target && action)
  131.         actionFunc = [target methodFor:action];
  132.  
  133.     // make a new timed entry
  134.     entry = DPSAddTimedEntry(period,(DPSTimedEntryProc)handle,self,priority);
  135.  
  136.     // check it
  137.     if ((int)entry == -1) {
  138.         [self logError:"Couldn't start timer!\n"];
  139.         entry = NULL;
  140.         return nil;
  141.     }
  142.     return self;
  143. }
  144.  
  145. // actions
  146. - start:sender
  147. {
  148.     // stop timer if necessary
  149.     value = startValue;
  150.     syncTime = [self currentTime];
  151.     syncCounter = 0;
  152.     [self startEntry];
  153.     return self;
  154. }
  155.  
  156. - stop:sender
  157. {
  158.     return [self stopEntry];
  159. }
  160.  
  161. - pause:sender
  162. {
  163.     return [self stopEntry];;
  164. }
  165.  
  166. - resume:sender
  167. {
  168.     return [self startEntry];
  169. }
  170.  
  171. // just in case anyone wants to fool with the timer directly
  172. - (DPSTimedEntry) entry
  173. {
  174.     return entry;
  175. }
  176.  
  177. - (unsigned int)currentTime
  178. {
  179.     struct timeval curTime;
  180.     gettimeofday (&curTime, NULL);
  181.     return (curTime.tv_sec) * 1000 + curTime.tv_usec / 1000;
  182. }
  183.  
  184. - synchronize:sender;
  185. {
  186.     int correctedTicks = (([self currentTime]-syncTime)/((int)(period*1000)));
  187.     if (bFlags.wrap) {
  188.         correctedTicks = correctedTicks % (int)((wrapValue-startValue)/incrementBy);
  189.     }
  190.     value = correctedTicks*incrementBy;
  191.     return self;
  192. }
  193.  
  194. // methods to get/set the value of the timer
  195. - (float)floatValue { return value; }
  196. - setFloatValue:(float)aValue { value = aValue; return self; }
  197. - (int)intValue { return (int)value; }
  198. - setIntValue:(int)aValue { value = (float)aValue; return self; }
  199. - (const char *)stringValue { static char str[20]; sprintf(str,"%f",value); return str; }
  200. - setStringValue:(const char *)aValue { value = atof(aValue); return self; }
  201. - (double)doubleValue { return (double)value; }
  202. - setDoubleValue:(double)aValue { value = (double)aValue; return self; }
  203.  
  204. // methods to get/set behaviours
  205. - setIncrementBy:(float)aValue { incrementBy = aValue; return self; }
  206. - (float)incrementBy { return incrementBy; }
  207. - setStartValue:(float)aValue { startValue = aValue; return self; }
  208. - (float)startValue { return startValue; }
  209. - setWrap:(BOOL)yn { bFlags.wrap = yn; return self; }
  210. - (BOOL)wrap { return (BOOL)(bFlags.wrap); }
  211. - setWrapValue:(float)aValue { wrapValue = CONSTRAIN(aValue,LOWWRAP,HIGHWRAP); return self; }
  212. - (float)wrapValue { return wrapValue; }
  213. - (int)syncValue { return syncValue; }
  214. - setSyncValue:(int)aValue { syncValue = CONSTRAIN(aValue,LOWSYNC,HIGHSYNC); return self; }
  215. - (BOOL)sync { return (BOOL)(bFlags.sync); }
  216. - setSync:(BOOL)yn { bFlags.sync = yn; return self; }
  217. - (BOOL)visibleDebug { return (BOOL)(bFlags.visibleDebug); }
  218. - setVisibleDebug:(BOOL)yn { bFlags.visibleDebug = yn; return self; }
  219. - (int)priority { return priority; }
  220. - setPriority:(int)aPriority { priority = CONSTRAIN(aPriority,LOWPRIORITY,HIGHPRIORITY); return self; }
  221. - (double)period { return period; }
  222. - setPeriod:(double)aPeriod { period = CONSTRAIN(aPeriod,LOWPERIOD,HIGHPERIOD); return self; }
  223. - (SEL)action { return action; }
  224.  
  225. - setAction:(SEL)anAction
  226. {
  227.     action = anAction;
  228.     // in case someone decides to change targets while the timer is operational
  229.     if (target && action)
  230.         actionFunc = [target methodFor:action];
  231.     return self; 
  232. }
  233.  
  234. - target
  235. {
  236.     return target;
  237. }
  238.  
  239. - setTarget:anObject
  240. {
  241.     target = anObject;
  242.     // in case someone decides to change targets while the timer is operational
  243.     if (target && action)
  244.         actionFunc = [target methodFor:action];
  245.     return self;
  246. }
  247.  
  248. // archival methods
  249. - read:(NXTypedStream *)stream
  250. {
  251.     float sv;
  252.     [super read:stream];
  253.     switch (NXTypedStreamClassVersion(stream, "Timer")) {
  254.         case 0 :  // syncValue was a float
  255.             NXReadTypes(stream,"@:dicfffff", &target, &action, &period,
  256.                             &priority, &bFlags, &sv,
  257.                             &startValue, &wrapValue, &value, 
  258.                             &incrementBy);
  259.             syncValue = (int)sv;
  260.             break;
  261.         default:
  262.             NXReadTypes(stream,"@:diciffff", &target, &action, &period,
  263.                             &priority, &bFlags, &syncValue,
  264.                             &startValue, &wrapValue, &value, 
  265.                             &incrementBy);
  266.     }
  267.     entry = NULL;
  268.     actionFunc = NULL;
  269.     return self;
  270. }
  271.  
  272. - write:(NXTypedStream *)stream
  273. {
  274.     [super write:stream];
  275.     NXWriteTypes(stream,"@:diciffff", &target, &action, &period,
  276.                             &priority, &bFlags, &syncValue,
  277.                             &startValue, &wrapValue, &value,
  278.                             &incrementBy);
  279.     return self;
  280. }
  281.  
  282. @end
  283.