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.