ftp.nice.ch/pub/next/developer/resources/classes/misckit/MiscKit.1.10.0.s.gnutar.gz#/MiscKit/Examples/BPM/CounterView.m

This is CounterView.m in view mode; [Download] [Up]

//		Written by Don Yacktman Copyright (c) 1994 by Don Yacktman.
//				Version 1.0.  All rights reserved.
//
//		This notice may not be removed from this source code.
//
//	This object is included in the MiscKit by permission from the author
//	and its use is governed by the MiscKit license, found in the file
//	"LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
//	for a list of all applicable permissions and restrictions.
//	

#import "CounterView.h"

@implementation CounterView

- initFrame:(const NXRect *)frm
{
	[super initFrame:frm];
	running = NO;
	[self counter];
	[self reset];
	return self;
}

- drawSelf:(NXRect *)rects :(int)rectCount
{
	NXRect theBorder;
	[self getFrame:&theBorder];
	theBorder.origin.x = 0.0;
	theBorder.origin.y = 0.0;
	NXDrawGrayBezel(&theBorder, NULL);
	NXInsetRect(&theBorder, 4.0, 4.0);
	if (running) NXSetColor(NX_COLORGREEN);
	else NXSetColor(NX_COLORRED);
	NXRectFill(&theBorder);
	return self;
}

- keyDown:(NXEvent *)myevent
{
	PSobscurecursor();  // subclasses which override need to do this.
	if (myevent->data.key.charSet == NX_ASCIISET &&
		(myevent->flags&(NX_CONTROLMASK|NX_ALTERNATEMASK|NX_COMMANDMASK)) == 0)
	{	
		if ((myevent->data.key.charCode) == ' ') { // allow pause
			[self tap:nil];
		} else if ((myevent->data.key.charCode) == 's') { // allow new game
			if (running) [self stop:nil];
			else [self start:nil];
		} else if ((myevent->data.key.charCode) == 'r') { // allow new game
			[self clear:nil];
		}
	}
	return self;
}

- mouseDown:(NXEvent *)event
{
	if (!running) {
		[self clear:nil];
		[self start:nil];
	} else [self tap:nil];
    return self;
}

- (MiscStopwatch *)counter
{
	if (!counter) counter = [[MiscStopwatch alloc] init];
	return counter;
}

- reset
{
	[beatsPerMeasure setIntValue:4];
	[self clear:nil];
	return self;
}

- clear:sender
{
	beatsCounted = 0;
	[self stop:nil];
	[beatsPerMinute setIntValue:0];
	[measuresPerMinute setIntValue:0];
	[secondsElapsed setIntValue:0];
	[[self counter] clearTiming:nil];
	[beatsPerMinute setBackgroundGray:0.666];
	[measuresPerMinute setBackgroundGray:0.666];
	[self update];
    return self;
}

- start:sender
{
	running = YES;
	[[self counter] continueTiming:nil];
	[beatsPerMinute setBackgroundGray:1.0];
	[measuresPerMinute setBackgroundGray:1.0];
	[self update];
	[self enableButtons:YES :NO :YES :YES];
    return self;
}

- stop:sender
{
	if (running) [self tap:nil];
	running = NO;
	[[self counter] pauseTiming:nil];
	[beatsPerMinute setBackgroundGray:0.666];
	[measuresPerMinute setBackgroundGray:0.666];
	[self update];
	[self enableButtons:YES :YES :NO :NO];
    return self;
}

- tap:sender
{
	int bm; id sc = [self counter];
	float seconds, bpm, mpm;

	if (!running) return [self start:nil];
	// get the basic infor we need
	beatsCounted++;
	[[self counter] calcElapsedTime:nil];
	seconds = [sc microsecond] / MISC_TIME_MAX_MICROSECONDS +
			[sc second] + 60 * [sc minute];
	bm = [beatsPerMeasure intValue];
	
	// avoid divide by zero
	if (bm < 1) bm = 1;
	if (seconds < 1) seconds = 1;

	// do calculations
	bpm = floor((beatsCounted * 600) / seconds) / 10;
	mpm = floor((bpm * 10) / bm) / 10;

	// update the interface
	[beatsPerMinute setFloatValue:bpm];
	[measuresPerMinute setFloatValue:mpm];
	[secondsElapsed setIntValue:seconds];
    return self;
}

- enableButtons:(BOOL)cb :(BOOL)sb :(BOOL)sb2 :(BOOL)tb
{
	[clearButton setEnabled:cb];
	[startButton setEnabled:sb];
	[stopButton setEnabled:sb2];
	[tapButton setEnabled:tb];
	return self;
}

- (BOOL)acceptsFirstMouse { return YES; }
- (BOOL)acceptsFirstResponder { return YES; }

@end

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.