This is ClockView.m in view mode; [Download] [Up]
// ClockView.m
// By Jayson Adams, NeXT Developer Support Team
// You may freely copy, distribute and reuse the code in this example.
// NeXT disclaims any warranty of any kind, expressed or implied, as to its
// fitness for any particular use.
#import "ClockView.h"
#import "Date.h"
#import <appkit/appkit.h>
#import <math.h>
static void MinuteSecondTimer(port_t timerPort)
{
msg_header_t nullMsg, updateMsg;
port_t aPort;
kern_return_t error;
if ( port_allocate(task_self(), &aPort) != KERN_SUCCESS )
cthread_exit(0);
/* Set the thread's priority. */
error = cthread_priority(cthread_self(), 0, FALSE);
if ( error != KERN_SUCCESS )
mach_error("Call to cthread_priority() failed", error);
while( (int)cthread_data(cthread_self()) != 0 )
{
nullMsg.msg_local_port = aPort;
nullMsg.msg_size = sizeof(msg_header_t);
/* wait until timeout */
msg_receive(&nullMsg, RCV_TIMEOUT, 1000);
/* Now send an update message to the appkit thread */
updateMsg.msg_simple = TRUE;
updateMsg.msg_size = sizeof(msg_header_t);
updateMsg.msg_type = MSG_TYPE_NORMAL;
updateMsg.msg_local_port = PORT_NULL;
updateMsg.msg_remote_port = timerPort;
updateMsg.msg_id = 0;
msg_send(&updateMsg, MSG_OPTION_NONE, 0);
}
port_deallocate(task_self(), aPort);
cthread_exit(0);
}
@implementation ClockView
static void UpdateHandler(msg_header_t *msg, ClockView *self)
{
Date *date = self->dateObj;
NXRect dummy;
/* If we are not visible do nothing */
if( [self getVisibleRect: &dummy] == NO )
return;
/* Display the current time */
self->t_now = [date sysTime];
self->t_min = (self->t_now - self->t_start) / 60;
self->t_sec = self->t_now - self->t_start - 60 * self->t_min;
self->t_min %= 60;
[self display];
}
- initFrame:(const NXRect *)frameRect
{
NXSize oneSize, twoSize;
int i;
char *numberNames[] = {"DigitalZero", "DigitalOne", "DigitalTwo",
"DigitalThree", "DigitalFour", "DigitalFive",
"DigitalSix", "DigitalSeven", "DigitalEight",
"DigitalNine", ""};
[super initFrame : frameRect];
/* get the images we'll use in drawSelf:: */
clockImage = [NXImage findImageNamed : "Clock"];
for (i = 0; *numberNames[i]; i++)
numbers[i] = [NXImage findImageNamed:numberNames[i]];
colon = [NXImage findImageNamed : "Colon"];
amImage = [NXImage findImageNamed : "AM"];
pmImage = [NXImage findImageNamed : "PM"];
/* compute the colon's location (it never changes) */
[numbers[1] getSize : &oneSize];
[numbers[2] getSize : &twoSize];
colonPosition_clock.x = oneSize.width + twoSize.width + 4.0;
colonPosition_clock.y = ceil((bounds.size.height - twoSize.height) / 2.0);
/* Center the ':' for the timer */
colonPosition_timer.x = bounds.size.width / 2.0;
colonPosition_timer.y = colonPosition_clock.y;
/* Init the date to the current time */
dateObj = [[Date alloc] initFromNow];
/* Check my time to see if it is AM or PM */
if ([dateObj hours] < 12)
meridianImage = amImage;
else
meridianImage = pmImage;
return self;
}
- free
{
if( timerActive == YES )
{
DPSRemovePort(timerPort);
port_deallocate(task_self(), timerPort);
cthread_set_data(timerCthread, (any_t) 0);
}
return [super free];
}
/* Date initialization methods */
- setDate : (short) d : (short) m : (short) y
{
if([dateObj initFromDate : d : m : y] == nil)
return nil;
/* Check my time to see if it is AM or PM */
if ([dateObj hours] < 12)
meridianImage = amImage;
else
meridianImage = pmImage;
[self display];
return self;
}
- setTime : (short) hr : (short) min : (short) sec
{
if([dateObj setTime : hr : min : sec] == nil)
return nil;
/* Check my time to see if it is AM or PM */
if ([dateObj hours] < 12)
meridianImage = amImage;
else
meridianImage = pmImage;
[self display];
return self;
}
- now
{
if([dateObj initFromNow] == nil)
return nil;
[self display];
return self;
}
- startMinSecTimer : sender
{
t_start = [dateObj sysTime];
if( timerPort == PORT_NULL )
{ /* Create a port and add the port handler. If timerPort is not
PORT_NULL, we assume we are just resetting the timer. */
port_allocate(task_self(), &timerPort);
DPSAddPort(timerPort, (DPSPortProc) UpdateHandler, sizeof(msg_header_t), self,
NX_MODALRESPTHRESHOLD +1);
timerCthread = cthread_fork((cthread_fn_t) MinuteSecondTimer, (any_t) timerPort);
cthread_set_data(timerCthread, (any_t) 1);
cthread_detach(timerCthread);
timerActive = YES;
}
[self display];
return self;
}
- endTimer : sender
{
if( timerActive == YES )
{
DPSRemovePort(timerPort);
port_deallocate(task_self(), timerPort);
cthread_set_data(timerCthread, (any_t) 0);
timerPort = PORT_NULL;
timerCthread = (cthread_t) 0;
}
timerActive = NO;
return self;
}
- drawSelf:(NXRect *) rects :(int) count
{
NXPoint position;
NXSize size, hoursTensSize = {0.0, 0.0}, hoursUnitsSize;
int t0,t1;
/* Set the hour & minute (minute & second) positions
depending on the timer state */
if(timerActive == YES)
{
t0 = t_min;
t1 = t_sec;
}
else
{
t0 = [dateObj hours];
if(t0 > 12)
t0 %= 12;
t1 = [dateObj minutes];
}
/* draw the background */
[clockImage composite:NX_SOVER toPoint:&(bounds.origin)];
/* AM or PM */
if(timerActive == NO)
{
[meridianImage getSize:&size];
position.x = bounds.size.width - size.width - 4.0;
position.y = floor((bounds.size.height - size.height) / 2.0);
[meridianImage composite:NX_SOVER toPoint:&position];
}
/* compute starting position for all drawing; the colon is stationary */
if(timerActive == NO)
position = colonPosition_clock;
else
position = colonPosition_timer;
if (t0 / 10)
{
[numbers[t0 / 10] getSize:&hoursTensSize];
}
[numbers[t0 % 10] getSize:&hoursUnitsSize];
position.x -= hoursTensSize.width + hoursUnitsSize.width;
/* draw the hours tens digit */
if (t0 / 10)
{
[numbers[t0 / 10] composite:NX_SOVER toPoint:&position];
position.x += hoursTensSize.width;
}
/* hours units digit */
[numbers[t0 % 10] composite:NX_SOVER toPoint:&position];
position.x += hoursUnitsSize.width;
/* draw the colon */
[[colon getSize:&size] composite:NX_SOVER toPoint:&position];
position.x += size.width;
/* tens digit of minutes */
[[numbers[t1 / 10] getSize:&size] composite:NX_SOVER
toPoint:&position];
position.x += size.width;
/* minutes units digit */
[numbers[t1 % 10] composite:NX_SOVER toPoint:&position];
return self;
}
@end
/* RCS Information:
$Author: me $;
$Date: 93/02/23 02:00:26 $;
$Source: /usr1/me/NeXTSrc/MyClasses/RCS/ClockView.m,v $;
$Revision: 1.1 $;
*/
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.