home *** CD-ROM | disk | FTP | other *** search
- static char rcsid[] = "$Id: Counter.m,v 1.1 1997/04/02 18:28:27 croehrig Exp $";
- /*
- * Counter: simple counter object that runs in its own thread.
- */
- #import <libc.h>
- #import <math.h>
- #import <appkit/Button.h>
- #import <appkit/Slider.h>
- #import "Counter.h"
- #import "ThreadedApp.h"
- #import "tprintf.h"
-
- #define INITIAL_INTERVAL 500 // in milliseconds
-
- @interface Counter(CounterPrivate)
- - (void)counter:sender;
- - (int)incCount;
- @end
-
- @implementation Counter : Object
-
- // number of counters created
- static int counters;
-
- #define STOPPED 0
- #define RUNNING 1
-
- #define myrandom() (random()/(double)MAXINT)
- + initialize
- {
- if( self == [Counter class] ){
- srandom(0);
- counters = 1;
- }
- tprintf_init();
- return self;
- }
-
-
- - init
- {
- NXScreen *screen;
- NXRect frame;
-
-
- [super init];
- interval = INITIAL_INTERVAL;
- running = NO;
- mynum = counters++;
-
- count = 0;
- if( [NXApp loadNibSection:"Counter.nib" owner:self] ){
- // set window title...
- title = (char *) malloc( 20*sizeof(char) ); // should be enough...
- sprintf( title, "Counter %d\n", mynum );
- [window setTitle:title];
-
- // move to random location
- [window getFrame:&frame andScreen:&screen];
- frame.size.width = screen->screenBounds.size.width
- - frame.size.width;
- frame.size.height = screen->screenBounds.size.height
- - frame.size.height;
- frame.origin = screen->screenBounds.origin;
- frame.origin.x += myrandom()*frame.size.width;
- frame.origin.y += myrandom()*frame.size.height;
- [window moveTo:frame.origin.x:frame.origin.y];
- [window makeKeyAndOrderFront:self];
-
- // set values
- [slider setIntValue:interval];
- [intervalField setIntValue:interval];
- [countField setIntValue:count];
-
- runlock = [[CJRConditionLock alloc] initWithCondition:STOPPED];
- // go!
- [self start:self];
- }
- return self;
- }
-
- - free
- {
- if( running )
- [self stop:self];
-
- [runlock free];
- if(title){
- free(title);
- }
- return [super free];
- }
-
-
- - windowWillClose:sender
- {
- [self stop:self];
- [NXApp delayedFree:self];
-
- return self;
- }
-
-
- // "private" methods
-
- - dispCount:(int)i
- {
- [countField setIntValue:i];
- return self;
- }
-
-
- - (int)incCount
- {
- count++;
- return count;
- }
-
-
- - (void)counter:sender
- {
-
- [runlock lockWhenCondition:RUNNING];
- while( running ){
-
- // update countField under main thread
- [NXApp callbackTarget:countField perform:@selector(setIntValue:)
- with:(id)count];
-
- // use a callback to make absolutely sure a 'reset' isn't lost
- [NXApp callbackAndWaitTarget:self perform:@selector(incCount)];
-
-
- if( interval > 0 )
- [NXApp sleepCurrentThread:interval];
- }
-
- [runlock unlockWithCondition:STOPPED];
- }
-
-
- // Actions...
-
- - start:sender
- {
- if( !running ){
- [runlock lock];
- [NXApp detachNewThreadSelector:@selector(counter:) toTarget:self
- withObject:self];
- running = YES;
- [runlock unlockWithCondition:RUNNING];
- }
- return self;
- }
-
-
- - stop:sender
- {
- if( running ){
- running = NO;
- // wait for thread to finish
- [runlock lockWhenCondition:STOPPED];
- [runlock unlock];
- }
-
- return self;
- }
-
- - startOrStop:sender
- {
- if( [sender state] == 0 ){
- [self start:sender];
- } else {
- [self stop:sender];
- }
- return self;
- }
-
-
- - reset:sender
- {
- count = 0;
- return self;
- }
-
-
- - setInterval:sender
- {
- int i, max;
-
- i = [sender intValue];
- max = (int) [slider maxValue];
- if( i < 0 ){
- i = 0;
- } else if( i > max ){
- i = max;
- }
- [slider setIntValue:i];
- [intervalField setIntValue:i];
-
- interval = i;
-
- return self;
- }
-
- @end
-