This is MiscClockView.m in view mode; [Download] [Up]
//
// MiscClockView.m -- a simple view class for displaying date/time
// Written by Scott Anguish Copyright (c) 1993 by Scott Anguish.
// Version 1.2. All rights reserved.
//
// This notice may not be removed from this source code.
//
// This object is included in the MiscKit by permission from the author
// and its use is governed by the MiscKit license, found in the file
// "LICENSE.rtf" in the MiscKit distribution. Please refer to that file
// for a list of all applicable permissions and restrictions.
//
#import <sys/time.h>
#import <appkit/appkit.h>
#import "MiscClockView.h"
@interface MiscClockView(private)
- _setUp;
@end
@interface MiscClockView(Delegate)
- dateChanged:sender;
@end
@implementation MiscClockView
#define Misc_BuildHImage(a, b, c, d, e) NXSetRect(theRect, (b), (c), (d), (e)); \
(a)[0] = [[NXImage alloc] initFromImage:theImage rect:theRect]; \
theRect->origin.y += 137.0; \
(a)[1] = [[NXImage alloc] initFromImage:theImage rect:theRect];
#define Misc_BuildImage(a, b, c, d, e) NXSetRect(theRect, (b), (c), (d), (e)); \
a = [[NXImage alloc] initFromImage:theImage rect:theRect];
+ initialize
{
[MiscClockView setVersion:4];
return self;
}
- _setUp
{
char buf[MAXPATHLEN + 1] = "";
NXRect rectStorage, *theRect = &rectStorage;
NXSize oneSize, twoSize;
if (theImage) return self; // don't want to leak!
[[NXBundle bundleForClass:[self class]] getPath:buf forResource:"MiscClockStuff" ofType:"tiff"];
theImage = [[NXImage alloc] initFromFile:buf];
/* Yes this is ugly, and there is alot of extra junk in here, but to a
* large degree at this point I didn't know where else to store these
* co-ordinates where I wouldn't loose them! */
Misc_BuildHImage (imageA, 65.0, 0.0, 9.0, 11.0);
Misc_BuildHImage (imageP, 74.0, 0.0, 9.0, 11.0);
Misc_BuildHImage (DigitalNumbers[1], 89.0, 0.0, 4.0, 11.0);
Misc_BuildHImage (DigitalNumbers[2], 93.0, 0.0, 9.0, 11.0);
Misc_BuildHImage (DigitalNumbers[3], 104.0, 0.0, 8.0, 11.0);
Misc_BuildHImage (DigitalNumbers[4], 112.0, 0.0, 9.0, 11.0);
Misc_BuildHImage (DigitalNumbers[5], 121.0, 0.0, 9.0, 11.0);
Misc_BuildHImage (DigitalNumbers[6], 130.0, 0.0, 9.0, 11.0);
Misc_BuildHImage (DigitalNumbers[7], 140.0, 0.0, 8.0, 11.0);
Misc_BuildHImage (DigitalNumbers[8], 148.0, 0.0, 9.0, 11.0);
Misc_BuildHImage (DigitalNumbers[9], 157.0, 0.0, 9.0, 11.0);
Misc_BuildHImage (DigitalNumbers[0], 166.0, 0.0, 9.0, 11.0);
Misc_BuildHImage (imageColon, 175.0, 0.0, 3.0, 11.0);
Misc_BuildHImage (imageAM, 179.0, 0.0, 12.0, 6.0);
Misc_BuildHImage (imagePM, 192.0, 0.0, 11.0, 6.0);
Misc_BuildHImage (DayNames[1], 0, 65, 19, 5);
Misc_BuildHImage (DayNames[2], 0, 59, 19, 5);
Misc_BuildHImage (DayNames[3], 0, 53, 19, 5);
Misc_BuildHImage (DayNames[4], 0, 47, 19, 5);
Misc_BuildHImage (DayNames[5], 0, 41, 19, 5);
Misc_BuildHImage (DayNames[6], 0, 35, 19, 5);
Misc_BuildHImage (DayNames[0], 0, 29, 19, 5);
Misc_BuildHImage (MonthNames[0], 40, 66, 22, 5);
Misc_BuildHImage (MonthNames[1], 40, 60, 22, 5);
Misc_BuildHImage (MonthNames[2], 40, 54, 22, 5);
Misc_BuildHImage (MonthNames[3], 40, 48, 22, 5);
Misc_BuildHImage (MonthNames[4], 40, 42, 22, 5);
Misc_BuildHImage (MonthNames[5], 40, 36, 22, 5);
Misc_BuildHImage (MonthNames[6], 40, 30, 22, 5);
Misc_BuildHImage (MonthNames[7], 40, 24, 22, 5);
Misc_BuildHImage (MonthNames[8], 40, 18, 22, 5);
Misc_BuildHImage (MonthNames[9], 40, 12, 22, 5);
Misc_BuildHImage (MonthNames[10], 40, 6, 22, 5);
Misc_BuildHImage (MonthNames[11], 40, 0, 22, 5);
Misc_BuildHImage (DateNumbers[0], 172.0, 14.0, 10.0, 17.0);
Misc_BuildHImage (DateNumbers[1], 65.0, 14.0, 8.0, 17.0);
Misc_BuildHImage (DateNumbers[2], 76.0, 14.0, 10.0, 17.0);
Misc_BuildHImage (DateNumbers[3], 88.0, 14.0, 9.0, 17.0);
Misc_BuildHImage (DateNumbers[4], 100.0, 14.0, 10.0, 17.0);
Misc_BuildHImage (DateNumbers[5], 112.0, 14.0, 10.0, 17.0);
Misc_BuildHImage (DateNumbers[6], 124.0, 14.0, 10.0, 17.0);
Misc_BuildHImage (DateNumbers[7], 136.0, 14.0, 10.0, 17.0);
Misc_BuildHImage (DateNumbers[8], 148.0, 14.0, 10.0, 17.0);
Misc_BuildHImage (DateNumbers[9], 160.0, 14.0, 10.0, 17.0);
Misc_BuildHImage (YearNumbers[0], 12.0, 8.0, 6.0, 5.0);
Misc_BuildHImage (YearNumbers[1], 0.0, 20.0, 2.0, 5.0);
Misc_BuildHImage (YearNumbers[2], 2.0, 20.0, 5.0, 5.0);
Misc_BuildHImage (YearNumbers[3], 7.0, 20.0, 5.0, 5.0);
Misc_BuildHImage (YearNumbers[4], 12.0, 20.0, 5.0, 5.0);
Misc_BuildHImage (YearNumbers[5], 0.0, 14.0, 5.0, 5.0);
Misc_BuildHImage (YearNumbers[6], 5.0, 14.0, 6.0, 5.0);
Misc_BuildHImage (YearNumbers[7], 11.0, 14.0, 5.0, 5.0);
Misc_BuildHImage (YearNumbers[8], 0.0, 8.0, 6.0, 5.0);
Misc_BuildHImage (YearNumbers[9], 6.0, 8.0, 6.0, 5.0);
Misc_BuildHImage (YearColon, 18.0, 25.0, 1.0, 5.0);
Misc_BuildImage (clockbase, 64, 72, 64, 64);
[DigitalNumbers[1][0] getSize:&oneSize];
[DigitalNumbers[2][0] getSize:&twoSize];
colonPosition.x = oneSize.width + twoSize.width + 7.0;
timedEntry = 0;
if (keepingTime)
{
[self startClock:self];
}
return self;
}
- initFrame:(const NXRect *)frameRect
{
[super initFrame:frameRect];
hidden=NO;
keepingTime=NO;
[self _setUp];
return self;
}
- awake
{
id ret = [super awake];
[self _setUp];
return ret;
}
- awakeFromNib
{
id ret = [super awake];
[self _setUp];
return ret;
}
- drawSelf:(const NXRect *)rects :(int)rectCount
{
NXPoint imageOrigin;
NXSize size, theSize, tensSize = {0.0, 0.0}, onesSize, twoSize;
id imageAyear, imageByear, imageCyear, imageDyear;
float width, widthA, widthB, widthC;
float imageAdjust;
int currentYear, hrs;
int highlight;
highlight = 0;
if (hidden) {
PSsetgray(NX_LTGRAY);
NXRectFill(&bounds);
}
[DigitalNumbers[1][highlight] getSize:&onesSize];
[DigitalNumbers[2][highlight] getSize:&twoSize];
if (!militaryTime)
colonPosition.x = onesSize.width + twoSize.width + 7.0;
else
colonPosition.x = 30;
if (showYear)
{
imageAdjust = 5;
colonPosition.y = 51;
}
else
{
imageAdjust = 0;
colonPosition.y = 46;
}
imageOrigin.x = 0;
imageOrigin.y = 0 + imageAdjust; //(0)
[clockbase composite:NX_COPY toPoint:&imageOrigin];
if (militaryTime)
{
hrs = hours;
}
else
{
hrs = hours % 12;
if (!hrs) hrs = 12;
}
[imageAM[highlight] getSize:&size];
imageOrigin.x = 44;
imageOrigin.y = 48 + imageAdjust; //(48)
if (!militaryTime)
{
if (meridian)
{
imageOrigin.x = 45;
[imagePM[highlight] composite:NX_COPY toPoint:&imageOrigin];
}
else
[imageAM[highlight] composite:NX_COPY toPoint:&imageOrigin];
}
// Hours
highlight = highlightSelection == 4 ? 1 : 0;
imageOrigin = colonPosition;
if (hrs / 10 || militaryTime)
[DigitalNumbers[hrs / 10][highlight] getSize:&tensSize];
[DigitalNumbers[hrs % 10][highlight] getSize:&onesSize];
imageOrigin.x -= tensSize.width + onesSize.width;
if (hrs / 10 || militaryTime)
{
[DigitalNumbers[hrs / 10][highlight] composite:NX_COPY toPoint:&imageOrigin];
imageOrigin.x += tensSize.width;
}
[DigitalNumbers[hrs % 10][highlight] composite:NX_COPY toPoint:&imageOrigin];
imageOrigin.x += onesSize.width;
// Colon
highlight = 0;
[[imageColon[highlight] getSize:&size] composite:NX_COPY toPoint:&imageOrigin];
imageOrigin.x += size.width;
// Minutes
highlight = highlightSelection == 5 ? 1 : 0;
[[DigitalNumbers[minutes / 10][highlight] getSize:&size] composite:NX_COPY toPoint:&imageOrigin];
imageOrigin.x += size.width;
[DigitalNumbers[minutes % 10][highlight] composite:NX_COPY toPoint:&imageOrigin];
// Weekday
highlight = 0;
imageOrigin.x = 21;
imageOrigin.y = 34 + imageAdjust; //(34)
[DayNames[weekday][highlight] composite:NX_COPY toPoint:&imageOrigin];
// Month
highlight = highlightSelection == 2 ? 1 : 0;
imageOrigin.x = 19;
imageOrigin.y = 9 + imageAdjust; //(9)
[MonthNames[month][highlight] composite:NX_COPY toPoint:&imageOrigin];
tensSize.width = 0.0;
tensSize.height = 0.0;
// Day
highlight = highlightSelection == 3 ? 1 : 0;
imageOrigin.x = 30;
imageOrigin.y = 15 + imageAdjust; //(15)
if (date / 10)
[DateNumbers[date / 10][highlight] getSize:&tensSize];
[DateNumbers[date % 10][highlight] getSize:&onesSize];
imageOrigin.x -= (tensSize.width + onesSize.width) / 2;
if (date / 10)
[DateNumbers[date / 10][highlight] composite:NX_COPY toPoint:&imageOrigin];
imageOrigin.x += tensSize.width + 1;
[DateNumbers[date % 10][highlight] composite:NX_COPY toPoint:&imageOrigin];
//Draw the year
if (showYear)
{
// Year
highlight = highlightSelection == 1 ? 1 : 0;
currentYear = [self year] + 1900;
imageAyear = YearNumbers[currentYear / 1000][highlight];
currentYear = currentYear % 1000;
imageByear = YearNumbers[currentYear / 100][highlight];
currentYear = currentYear % 100;
imageCyear = YearNumbers[currentYear / 10][highlight];
currentYear = currentYear % 10;
imageDyear = YearNumbers[currentYear][highlight];
[imageAyear getSize:&theSize];
widthA = theSize.width;
[imageByear getSize:&theSize];
widthB = theSize.width;
[imageCyear getSize:&theSize];
widthC = theSize.width;
[imageDyear getSize:&theSize];
width = widthA + widthB + widthC + theSize.width;
imageOrigin.x = 32 - (width / 2.0);
imageOrigin.y = 0;
[imageAyear composite:NX_COPY toPoint:&imageOrigin];
imageOrigin.x = imageOrigin.x + widthA;
[imageByear composite:NX_COPY toPoint:&imageOrigin];
imageOrigin.x = imageOrigin.x + widthB;
[imageCyear composite:NX_COPY toPoint:&imageOrigin];
imageOrigin.x = imageOrigin.x + widthC;
[imageDyear composite:NX_COPY toPoint:&imageOrigin];
}
return self;
}
- setSeconds:(int)theSeconds
{
seconds = theSeconds;
return self;
}
- setMinutes:(int)theMinutes
{
minutes = theMinutes;
return self;
}
- setHours:(int)theHours
{
hours = theHours;
return self;
}
- setWeekday:(int)theWeekday
{
weekday = theWeekday;
return self;
}
- setDate:(int)theDate
{
date = theDate;
return self;
}
- setMonth:(int)theMonth
{
month = theMonth;
return self;
}
- setYear:(int)theYear
{
year = theYear;
return self;
}
- setMeridian:(int)theMeridian
{
meridian = theMeridian;
return self;
}
- takeMinutesFrom:sender
{
[self setMinutes:[sender intValue]];
[self display];
return self;
}
- takeHoursFrom:sender
{
int localhours = [sender intValue];
localhours %= 24;
if (localhours < 12)
{
[self setMeridian:0];
}
else
{
[self setMeridian:1];
}
[self setHours:localhours];
[self display];
return self;
}
- takeWeekdayFrom:sender
{
[self setWeekday:[sender intValue]];
[self display];
return self;
}
- takeDateFrom:sender
{
[self setDate:[sender intValue]];
[self display];
return self;
}
- takeMonthFrom:sender
{
[self setMonth:[sender intValue]];
[self display];
return self;
}
- setTime: (struct tm*)theTime
{
seconds = theTime->tm_sec;
minutes = theTime->tm_min;
hours = theTime->tm_hour;
if (hours < 12)
{
meridian = 0;
}
else
{
meridian = 1;
};
date = theTime->tm_mday;
month = theTime->tm_mon;
year = theTime->tm_year;
weekday = theTime->tm_wday;
return self;
};
- (const char *)getInspectorClassName
{
return "MiscClockViewInspector";
}
- (int)year
{
return year;
}
- (int)month
{
return month;
}
- (int)weekday
{
return weekday;
}
- (int)date
{
return date;
}
- (int)hours
{
return hours;
}
- (int)minutes
{
return minutes;
}
- (int)seconds
{
return seconds;
}
- (BOOL)militaryTime
{
return militaryTime;
}
- (BOOL)showYear
{
return showYear;
}
- setShowYear:(BOOL)state
{
showYear = state;
return self;
}
- setMilitaryTime:(BOOL)state
{
militaryTime = state;
return self;
}
- (BOOL)keepingTime
{
return keepingTime;
}
- setKeepingTime:(BOOL)yesno
{
keepingTime = yesno;
return self;
}
- read:(NXTypedStream *) stream
{
int myVersion = NXTypedStreamClassVersion (stream,[self name]);
[super read:stream];
if (myVersion < 2)
{
NXReadTypes (stream, "iiiiiiiiii", &seconds, &minutes, &hours,
&date, &month, &year, &weekday, &meridian, &showYear, &militaryTime);
}
else
{
NXReadTypes (stream, "iiiiiiiicc", &seconds, &minutes, &hours,
&date, &month, &year, &weekday, &meridian, &showYear, &militaryTime);
}
if (myVersion < 1)
{
keepingTime = NO;
}
else if (myVersion == 1)
{
NXReadType (stream, "i", &keepingTime);
}
else
{
NXReadType (stream, "c", &keepingTime);
}
if (myVersion > 2) {
NXReadType (stream, "c", &hidden);
} else {
hidden = NO;
}
if (myVersion > 3)
{
delegate = NXReadObject (stream);
}
else
{
delegate = nil;
}
return self;
}
- write:(NXTypedStream *) stream
{
[super write:stream];
NXWriteTypes (stream, "iiiiiiiicc", &seconds, &minutes, &hours,
&date, &month, &year, &weekday, &meridian, &showYear, &militaryTime);
NXWriteType (stream, "c", &keepingTime);
NXWriteType (stream, "c", &hidden);
NXWriteObject (stream, delegate);
return self;
}
- setHide:(BOOL)hide
{
hidden = hide;
return self;
}
- (BOOL)isHidden
{
return hidden;
}
void
Animate (timedEntry, now, self)
DPSTimedEntry timedEntry;
double now;
id self;
{
[(id)self ticktock];
}
- ticktock
{
struct timeval tp;
struct timezone tzp;
struct tm *tv;
gettimeofday (&tp, &tzp);
tv = localtime (&tp.tv_sec);
[self setTime:tv];
[self display];
return self;
}
- startClock:sender
{
if (!keepingTime)
{
[self ticktock];
timedEntry = DPSAddTimedEntry (60, Animate, (void *)self, NX_MODALRESPTHRESHOLD);
keepingTime = YES;
NXPing ();
}
return self;
}
- stopClock:sender
{
if (timedEntry)
{
DPSRemoveTimedEntry (timedEntry);
[self ticktock];
keepingTime = NO;
timedEntry = 0;
}
return self;
}
- free
{
int i,j;
for(j=0;j<2;j++)
{
[imageA[j] free];
[imageP[j] free];
for(i=0;i<10;i++)
[DigitalNumbers[i][j] free];
[imageColon[j] free];
[imageAM[j] free];
[imagePM[j] free];
for(i=0;i<7;i++)
[DayNames[i][j] free];
for(i=0;i<12;i++)
[MonthNames[i][j] free];
for(i=0;i<10;i++)
[DateNumbers[i][j] free];
for(i=0;i<10;i++)
[YearNumbers[i][j] free];
[YearColon[j] free];
}
[clockbase free];
[theImage free];
if (timedEntry != NULL)
DPSRemoveTimedEntry (timedEntry);
return[super free];
}
- setToCurrentTime:sender
{
struct timeval tp;
struct timezone tzp;
struct tm *tv;
gettimeofday (&tp, &tzp);
tv = localtime (&tp.tv_sec);
[self setTime:tv];
[self display];
return self;
}
// Action stuff
- mouseDown:(NXEvent *)theEvent
{
NXPoint mouseLocation;
NXRect minuteRect;
NXRect hourRect;
NXRect dayRect;
NXRect monthRect;
NXRect yearRect;
BOOL flipped = [self isFlipped];
int oldSelection = highlightSelection;
mouseLocation = theEvent->location;
/* ... and convert them into our view coordinate system */
[self convertPoint:&mouseLocation fromView:nil];
NXSetRect(&hourRect,colonPosition.x-21.0,colonPosition.y,20.0,11.0);
NXSetRect(&minuteRect,colonPosition.x+1.0,colonPosition.y,20.0,11.0);
if(showYear)
{
NXSetRect(&dayRect,30.0,20.0,20.0,17.0);
NXSetRect(&monthRect,19.0,14.0,22.0,5.0);
NXSetRect(&yearRect,22.0,0.0,20.0,5.0);
}
else
{
NXSetRect(&dayRect,30.0,15.0,20.0,17.0);
NXSetRect(&monthRect,19.0,9.0,22.0,5.0);
} // Find out what we hit
highlightSelection = 0;
// 1. Year
if(showYear)
{
if(NXMouseInRect(&mouseLocation, &yearRect, flipped))
{
highlightSelection = 1;
return oldSelection == highlightSelection ? self : [self display];
}
}
// 2. Month
if(NXMouseInRect(&mouseLocation, &monthRect, flipped))
{
highlightSelection = 2;
}
// 3. Day
else if(NXMouseInRect(&mouseLocation, &dayRect, flipped))
{
highlightSelection = 3;
}
// 4. Hour
else if(NXMouseInRect(&mouseLocation, &hourRect, flipped))
{
highlightSelection = 4;
}
// 5. Minutes
else if(NXMouseInRect(&mouseLocation, &minuteRect, flipped))
{
highlightSelection = 5;
}
return oldSelection == highlightSelection ? self : [self display];
}
- increment:sender
{
return [self changeDate:1];
}
- decrement:sender
{
return [self changeDate:-1];
}
- changeDate:(int) change
{
static int monthDays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int daysInMonth;
struct tm tmDate;
time_t time;
switch(highlightSelection)
{
case 1: // Year
year += change;
break;
case 2: // Month
month += change;
break;
case 3: // Day
date += change;
break;
case 4: // Hours
hours += change;
break;
case 5: // Minutes
minutes += change;
break;
default: // Nothing selected
return nil;
}
// Consistency checks
if(minutes > 59)
{
++hours;
minutes = 0;
}
else if(minutes < 0)
{
--hours;
minutes = 59;
}
if(hours > 23)
{
++date;
hours = 0;
}
else if(hours < 0)
{
--date;
hours = 23;
}
meridian = hours > 12 ? 1 : 0;
if(month != 1)
{
daysInMonth = monthDays[month];
}
else
{
daysInMonth = (year % 4) ? 28 : 29;
}
if(date > daysInMonth)
{
++month;
date = 1;
}
else if(date < 1)
{
--month;
if(month != 1)
{
daysInMonth = monthDays[month];
}
else
{
daysInMonth = (year % 4) ? 28 : 29;
}
date = daysInMonth;
}
if(month > 11)
{
++year;
month = 0;
}
else if(month < 0)
{
--year;
month = 11;
}
// We have to set the correct week day
tmDate.tm_sec = 0;
tmDate.tm_min = 0;
tmDate.tm_hour = 0;
tmDate.tm_mday = 1;
tmDate.tm_mon = month;
tmDate.tm_year = year - 1900;
tmDate.tm_wday = 0;
tmDate.tm_yday = 0;
tmDate.tm_isdst = 0;
tmDate.tm_gmtoff = 0;
tmDate.tm_zone = "";
time = mktime(&tmDate);
tmDate = *localtime(&time);
time -= tmDate.tm_gmtoff;
tmDate = *localtime(&time);
weekday = tmDate.tm_wday;
if(delegate && [delegate respondsTo:@selector(dateChanged:)])
{
[delegate dateChanged:self];
}
return [self display];
}
- setDelegate:aDelegate
{
delegate = aDelegate;
return self;
}
- delegate
{
return delegate;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.