home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / MiniExamples / AppKit / AskMe / ClockView.m < prev    next >
Encoding:
Text File  |  1995-06-12  |  6.0 KB  |  212 lines

  1. /* ClockView.m, a simple clock view 
  2.  * Author: Ali T. Ozer, NeXT Developer Support Group
  3.  * Created: May 26, 1989 (for version 0.9)
  4.  * Modified: June 14 and Aug 14, 1989 (for version 1.0)
  5.  * Redesigned for 2.0 by Julie Zelenski, NeXT Developer Support Group
  6.  * Adapted by Mai Nguyen for this mini-example. Basically, only the digital
  7.  * view of the clock is being used.
  8.  *
  9.  * Subclass of view to implement a simple clock. This view is pretty generic 
  10.  * and can probably be added to any program. 
  11.  * You may freely copy, distribute and reuse the code in this example.  
  12.  * NeXT disclaims any warranty of any kind, expressed or implied, as to its 
  13.  * fitness for any particular use.
  14.  */
  15.  
  16. #import "ClockView.h"
  17. #import "Clock.h"    // PSwrap routines
  18. #import <appkit/Application.h>
  19. #import <appkit/Button.h>
  20. #import <appkit/Window.h>
  21. #import <appkit/Font.h>
  22. #import <objc/NXStringTable.h>
  23. #import <string.h>
  24. #import <sys/time.h>    
  25. #import <dpsclient/wraps.h>    
  26. #import <appkit/nextstd.h>
  27.  
  28. @implementation ClockView:View
  29.  
  30.         
  31. /* ShowTime() is the timed entry function called by the
  32.  * timed entry mechanism. It first writes the time out on the face 
  33.  * of the clock, and then reinstalls the timed entry if the clock is 
  34.  * not showing the seconds. If the seconds are being shown, no need to 
  35.  * reinstall the timed entry; a second skipped here and then won't matter. 
  36.  * If minutes are being shown, we want to make sure that the minute jumps 
  37.  * at the next top of the minute, regardless of how long it took to service 
  38.  * the timed entry.
  39.  */
  40. void ShowTime (teNum, now, clock) 
  41. DPSTimedEntry teNum;
  42. double now;
  43. id clock;
  44. {
  45.     [clock display];
  46.     [[clock stopTimedEntry] startTimedEntry:NO];    
  47.     
  48. }
  49.  
  50.  
  51.  
  52.  
  53. - initFrame:(const NXRect *)frameRect
  54. /* initFrame for newly created view, initializes the various paramaters. 
  55.  * The constants above determine the lengths of the clock hands.
  56.  */
  57. {
  58.     [super initFrame:frameRect];
  59.     cacheWindow = [Window newContent:frameRect 
  60.                                style:NX_PLAINSTYLE
  61.                  backing:NX_RETAINED 
  62.               buttonMask:0 
  63.                    defer:NO];    
  64.     littleFont = [Font newFont:"Helvetica" size:12 style:0
  65.                 matrix:NX_IDENTITYMATRIX];
  66.     mediumFont = [Font newFont:"Times-Roman" size:14 style:0
  67.                 matrix:NX_IDENTITYMATRIX];
  68.     bigFont = [Font newFont:"Times-Roman" size:24 style:0
  69.                 matrix:NX_IDENTITYMATRIX];
  70.  
  71.     /* Set the default state (NO seconds, no date) */
  72.     
  73.     showSeconds = NO;
  74.     center.x = bounds.size.width/2.0;
  75.     center.y = bounds.size.height/2.0 + [mediumFont pointSize]/2.0;
  76.     radius = MIN(center.x,center.y-[mediumFont pointSize]);
  77.     needRedraw = YES;
  78.     
  79.     /* Start the time entry. YES indicates that this is the first time */
  80.     [self startTimedEntry:YES];
  81.     [self display];
  82.     return self;
  83. }
  84.  
  85.  
  86. - free
  87. /* Good idea to get rid of the timed entry while freeing... 
  88.  */
  89. {
  90.     [cacheWindow free];
  91.     [self stopTimedEntry];
  92.     return [super free];
  93. }
  94.  
  95.  
  96.  
  97.  
  98. /* PRIVATE METHODS */
  99.  
  100. - drawFace;
  101. /* drawFace draws the clock face image in the offscreen window.  This
  102.  * offscreen cache is composited on screen and then the hands, shadow,
  103.  * whatever is drawn on top of the face for the current time. Just
  104.  * erase the background before redrawing the digital time.
  105.  */
  106. {
  107.     
  108.     [[cacheWindow contentView] lockFocus];
  109.  
  110.     PSsetgray (NX_LTGRAY);
  111.     NXRectFill (&bounds);    // Erase background    
  112.     [[cacheWindow contentView] unlockFocus]; 
  113.     needRedraw = NO;
  114.     return self;
  115. }
  116.  
  117. - drawDigital:(struct tm *)time;
  118. /* drawDigital draws the time and date for the digital clock face
  119.  */
  120. {
  121.     int hour;
  122.     char timeString[10];
  123.    
  124.     
  125.     hour = fmod(time->tm_hour,12); /* get us off military time */
  126.     if (!hour) hour = 12;  /* if noon or midnight */
  127.     if (showSeconds)
  128.         sprintf(timeString,"%d:%.2d:%.2d",hour,
  129.                         time->tm_min,
  130.                         time->tm_sec);
  131.     else 
  132.         sprintf(timeString,"%d:%.2d", hour,time->tm_min);
  133.     [mediumFont set];
  134.     PSWcenterShow(center.x,center.y-8.0,timeString,NX_BLACK);
  135.     return self;
  136. }
  137.  
  138.  
  139.  
  140.  
  141. - drawSelf:(NXRect *)rects :(int)rectCount
  142. /* Draws face and hands of clock. If needRedraw is YES, a parameter has 
  143.  * changed and the face must be redrawn in the offscreen window. 
  144.  * Otherwise, the image in cacheWindow is copied into the bounds of the 
  145.  * view, and a routine is called to display the current date and time
  146.  */ 
  147. {    
  148.     struct tm *localTime;
  149.     struct timeval currentTime;
  150.  
  151.     if (needRedraw) [self drawFace];
  152.     PScomposite(0.0, 0.0, bounds.size.width, bounds.size.height,
  153.         [cacheWindow gState], bounds.origin.x, bounds.origin.y, 
  154.         NX_COPY);
  155.  
  156.     gettimeofday (¤tTime, NULL);
  157.     localTime = localtime (&(currentTime.tv_sec));
  158.     [self drawDigital:localTime];
  159.     return self;
  160. }
  161.  
  162.  
  163. - startTimedEntry:(BOOL)fireASAP
  164. /* startTimedEntry will install the timed entry. If fireASAP is YES, the
  165.  * timed entry is set to fire off as soon as possible (this would be the case
  166.  * at the start of the program, for instance). If fireASAP is NO, then the
  167.  * timed entry is set to fire off in one second (if seconds are being shown)
  168.  * or at the top of the next minute (in anytime between 0 and 60 seconds).
  169.  */
  170. {
  171.     double fireIn;
  172.  
  173.     if (fireASAP) fireIn = 0.0;          // Fire as soon as possible!
  174.     else if (showSeconds) fireIn = 1.0;      // Fire in a second (good enough)
  175.     else {
  176.         struct timeval currentTime;
  177.         gettimeofday (¤tTime, NULL);
  178.     fireIn = 60.0 - (currentTime.tv_sec % 60);  // Top of the minute
  179.     }
  180.     
  181.     teNum = DPSAddTimedEntry(fireIn, &ShowTime, self, NX_MODALRESPTHRESHOLD);
  182.     return self;
  183. }
  184.  
  185. - stopTimedEntry
  186. /* Removes the clock timed entry.
  187.  */
  188. {
  189.     if (teNum)
  190.          DPSRemoveTimedEntry (teNum);
  191.     teNum = (DPSTimedEntry)0;
  192.     return self;
  193. }
  194.  
  195.  
  196. - sizeTo:(NXCoord)w :(NXCoord)h
  197. /* Overriding sizeTo:: allows us to resize and fix up the clock whenever
  198.  * the size is changed.  Figure the radius of the clock (based on the size
  199.  * of the view) and then redraw
  200.  */
  201. {
  202.     [super sizeTo:w :h];
  203.     center.x = bounds.size.width/2.0;
  204.     center.y = bounds.size.height/2.0 + [mediumFont pointSize]/2.0;
  205.     radius = MIN(center.x, center.y-[mediumFont pointSize]);
  206.     needRedraw = YES;
  207.     return self;
  208. }
  209.  
  210.  
  211.  
  212. @end