This is ClockView.m in view mode; [Download] [Up]
/* Generated by Interface Builder */
/* [yeah, right, the Interface Builder generated this. -scott] */
// My stuff.
#import "ClockView.h"
#import "Animator.h"
// appkit stuff.
#import <appkit/nextstd.h> // MAX()
#import <appkit/Matrix.h> // For getting the clockType.
// unix stuff.
#import <math.h> // cos, sin, M_PI
// dps stuff.
#import <dpsclient/wraps.h> // PS*().
@implementation ClockView
extern long time( long *);
+ newFrame:(NXRect *)r
{
self = [super newFrame:r];
[self setClockType:BEZIER];
[self setDialSize:.05];
return self;
}
- free
{
[animator stop:self];
[animator setTarget:nil];
return [super free];
}
- takeDialSizeFrom:sender // set the dial size via slider.
{
return [self setDialSize:[sender floatValue]];
}
- takeClockTypeFrom:sender // set the clock type via matrix.
{
return [self setClockType:[[sender selectedCell] tag]];
}
- setDialSize:(float)size // Set programatically.
{
dialSize=size;
return [self display];
}
- setClockType:(int)type
{
clockType=type;
return [self display];
}
-(int)clockType // return the data.
{
return clockType;
}
-(float)dialSize
{
return dialSize;
}
// Draws the dials in the currently focussed region, etc. Makes little or
// no sense if not used to draw in this view. Also, won't work nicely for non-
// square views.
- drawDials
{
float half=bounds.size.height/2.0;
float secang=sec*6*M_PI/180.0;
float minang=min*6*M_PI/180.0;
float hourang=((hour)%12)*30*M_PI/180.0+minang/12;
// define the size multiplier for each hand.
#define HOUR (.4*half)
#define MINUTE (.75*half)
#define SECOND (.85*half)
PSsetlinewidth( dialSize*half);
PSsetlinecap( 1); // Rounded ends.
PSsetlinejoin( 1); // Rounded joins.
PStranslate( half, half);
PSmoveto( sin( minang)*MINUTE, cos( minang)*MINUTE);
switch( clockType)
{
case NORMAL : // "Normal" clock.
PSlineto( 0, 0);
PSlineto( sin( secang)*SECOND, cos( secang)*SECOND);
PSlineto( 0, 0);
PSlineto( sin( hourang)*HOUR, cos( hourang)*HOUR);
break;
case LINES :
PSlineto( sin( secang)*SECOND, cos( secang)*SECOND);
PSlineto( sin( hourang)*HOUR, cos( hourang)*HOUR);
break;
case CURVES :
PScurveto( 0, 0, 0, 0,
sin( secang)*SECOND, cos( secang)*SECOND);
PScurveto( 0, 0, 0, 0,
sin( hourang)*HOUR, cos( hourang)*HOUR);
PScurveto( 0, 0, 0, 0,
sin( minang)*MINUTE, cos( minang)*MINUTE);
break;
case BEZIER :
PScurveto( sin( secang)*SECOND, cos( secang)*SECOND,
0, 0, sin( hourang)*HOUR, cos( hourang)*HOUR);
break;
}
PSstroke();
PStranslate( -half, -half);
return self;
}
- setAnimator:anObject
{
if( animator==anObject) // nip loops in the bud.
return self;
animator=anObject;
[animator setTarget:self];
[animator setTiming:1.0];
[animator setThreshold:NX_MODALRESPTHRESHOLD]; // this makes it run smoother. why?
return self;
}
- animate:sender
{
long clock;
struct tm *t;
[self lockFocus];
PSsetgray( NX_LTGRAY); // Erase the old time.
[self drawDials];
time( &clock); // Snarf the new time.
t=localtime( &clock);
hour=t->tm_hour;
min=t->tm_min;
sec=t->tm_sec;
PSsetgray( NX_BLACK); // Draw the new time.
[self drawDials];
[self unlockFocus]; // Make it be.
[[self window] flushWindow];
NXPing();
return self;
}
- animator
{
return animator;
}
- drawSelf:(NXRect *)r :(int)count
{
long clock;
struct tm *t;
int i;
float half=bounds.size.height/2.0;
#define TICKS (.95*half)
time( &clock); // Snarf the time.
t=localtime( &clock);
hour=t->tm_hour;
min=t->tm_min;
sec=t->tm_sec;
PSsetgray( NX_LTGRAY); // Clear the background.
NXRectFill( &bounds);
PSsetgray( NX_BLACK); // Draw the dials.
[self drawDials];
PStranslate( half, half);
// Then, draw the tick marks (assume linewidth/cap set by drawDials).
PSnewpath();
for( i=0; i<12; i++, PSrotate( 30))
{
PSmoveto( TICKS, 0);
PSlineto( half, 0);
}
PSstroke();
[[self window] flushWindow];
NXPing();
return self;
}
// Here is a useful function - cut this out for your programs. This is a Window
// delegate function which keeps the window from resizing to a non-square
// size. It's not what I'd like, though - the resize bar still has that
// section for resizing vertically only. When that occurs, you do not get
// to do anything. I tried _making_ it resize, but that did not work. So,
// this is what you get.
- windowWillResize:sender toSize:(NXSize *)f
{
NXRect curFrame;
[sender getFrame:&curFrame];
if( curFrame.size.width==f->width || curFrame.size.height==f->height)
{
*f=curFrame.size;
return self;
}
f->width-=curFrame.size.width;
f->height-=curFrame.size.height;
f->width=f->height=MAX( f->width, f->height);
f->width+=curFrame.size.width;
f->height+=curFrame.size.height;
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.