This is ClockView.m in view mode; [Download] [Up]
//
// ClockView.m
//
// Matt Pharr- pharr@cs.yale.edu
//
#import "ClockView.h"
#import <appkit/graphics.h>
#import <libc.h>
#import <dpsclient/wraps.h>
#import <time.h>
#import <strings.h>
#import <appkit/NXImage.h>
#import <appkit/Font.h>
#import <appkit/publicWraps.h>
@implementation ClockView
- oneStep
{
  time_t tTime;
  struct tm *currentTime;
  int i;
  currentLocation.x += moveVector.x;       // move the x and y positions of the image
  currentLocation.y += moveVector.y;       // as indicated by the move vectors
  if (currentLocation.x <= bounds.origin.x)  // keep it ON the screen
    moveVector.x= randBetween(1.0, 5.0);
  if (currentLocation.x + currentSize.width >= (bounds.size.width - bounds.origin.x))
    moveVector.x= (-1) * randBetween(1.0, 5.0);
  if (currentLocation.y <= bounds.origin.y)
    moveVector.y= randBetween(1.0, 5.0);
  if (currentLocation.y + currentSize.height >= (bounds.size.height - bounds.origin.y))
    moveVector.y= (-1) * randBetween(1.0, 5.0);
  time(&tTime);
  currentTime= localtime(&tTime);
  strftime(theTime, 10, "%H:%M:%S", currentTime);
  if (strcmp(theTime, lastTime) != 0) {   // if the time has changed...
    strcpy(lastTime, theTime);
    currentLocation.x += moveVector.x;   // move it one more time so it's not so jerky
    currentLocation.y += moveVector.y;   // when the time changes...
    if ([currentImage lockFocus] == YES) {
      PSsetgray(0.0);
      PSrectfill(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
      [theFont set];
      PSsetgray(.333);                     // give it a little shadow
      for(i=1; i < 4; ++i) {
        PSmoveto(10.0 + i, 140.0 - i);
        PSshow(theTime);
     }
      PSmoveto(10.0, 138.0);
      [self chooseColor];
      PSshow(theTime);
      [currentImage unlockFocus];
    }
  }
  [currentImage composite:NX_SOVER toPoint:¤tLocation];
  usleep(20000);      // could reduce this without adding flicker. 20000 makes for
                      // a pretty comfortable speed, though.
  return self;
}
- chooseColor
{
  float dr, dg, db;
  if ([Window defaultDepthLimit] == NX_TwoBitGrayDepth) {
     currGrey= 1.0;          // boring city...
     PSsetgray(currGrey);
  }
  else {
     dr= randBetween(-.1, .1);   // randomly move the red, green, and blue
     dg= randBetween(-.1, .1);   // components of the color around between
     db= randBetween(-.1, .1);   // 0 and 1. There is a minor bummer in that
                                 // you only see the effect of the color
                                 // change once a second, because it only
                                 // draws the time into the bitmap when the
                                 // time changes. Would be an easy modification
                                 // to get it to redraw the bitmap more
                                 // frequently, but its probably not worth
                                 // the trouble. Depending on how this ends
                                 // up looking in color (wish I knew!), it
                                 // might be better to replace everything
                                 // between the else and the PSsetrgbcolor
                                 // with just a PSsetrgbcolor(), with constant
                                 // arguments...
     currR += dr;    currG += dg;     currB += db;
     if (currR < 0.0) currR= 0.0;
     if (currR > 1.0) currR= 1.0;
     if (currG < 0.0) currG= 0.0;
     if (currG > 1.0) currG= 1.0;
     if (currB < 0.0) currB= 0.0;
     if (currB > 1.0) currB= 1.0;
     PSsetrgbcolor(currR, currG, currB);
  }
  return self;
}
- drawSelf:(const NXRect *)rects :(int)rectCount
{
  if (!rects || !rectCount) {
    return self;
  }
  PSsetgray(0);
  NXRectFill(rects);
  return self;
}
- init
{
  [super init];
  currentLocation.x= 400.0;
  currentLocation.y= 400.0;
  moveVector.x= randBetween(1.0, 5.0);
  moveVector.y= randBetween(1.0, 5.0);
  *theTime= '\0';
  *lastTime= '\0';
  theFont=  [Font newFont:"Times-Roman" size:180.0];
  currGrey= currR= currG= currB= .5;
  currentSize.width= [theFont getWidthOf:"88:88:88"] + 17.0;  // keep the bitmap a 
  currentSize.height= 180.0;                                  // little on the big size,
                                                              // so there is extra black
                                                              // around the edges, so that
                                                              // the previous drawing
                                                              // is automagically erased.
  currentImage= [[NXImage alloc] initSize:¤tSize];
  [currentImage setFlipped:YES];
  return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.