//----------------------------------------------------------------------------------------------------
//
//	CalendarClock
//
//	Inherits From:		Clock
//
//	Declared In:		CalendarClock.h
//
//	Disclaimer
//
//		You may freely copy, distribute and reuse this software and its
//		associated documentation. I disclaim any warranty of any kind, 
//		expressed or implied, as to its fitness for any particular use.
//
//----------------------------------------------------------------------------------------------------
#import "CalendarClock.h"


#define TIMESTRING_OFFSET		8.0
#define DAYSTRING_OFFSET		3.0
#define DATESTRING_OFFSET		28.0
#define MONTHSTRING_OFFSET	27.0

static const char*  DAYS [7] = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
static const char*  MONTHS [12] = 
{ "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };

static  id timeFont;
static  id dayOfWeekFont;
static  id dateFont;
static  id monthFont;


@implementation CalendarClock

//----------------------------------------------------------------------------------------------------
//	Private Methods
//----------------------------------------------------------------------------------------------------
- (NXPoint) _locationForString: (STR)aString usingFont: aFont
{
	NXPoint	stringLocation;

	stringLocation.x = ((NX_WIDTH(&bounds) - [aFont getWidthOf:aString]) / 2.0);
	stringLocation.y = ((NX_HEIGHT(&bounds) / 2.0) + ([aFont pointSize] / 2.0));

	return stringLocation;
}


- _drawDayOfWeek
{
    	char 	stringBuffer[5];
	NXPoint	stringLocation;
	
	sprintf (stringBuffer,"%s", DAYS[WEEKDAY(displayTimeAndDate)]);
	stringLocation = [self _locationForString:stringBuffer usingFont: dayOfWeekFont];
	NXSetColor (weekdayColor);	
	[dayOfWeekFont set];
	PSmoveto (stringLocation.x, stringLocation.y - DAYSTRING_OFFSET);
	PSshow (stringBuffer);
	return self;
}
	

- _drawDate
{
    	char 	stringBuffer[5];
	NXPoint	stringLocation;
	
	sprintf (stringBuffer,"%d", DAY(displayTimeAndDate));
	stringLocation = [self _locationForString:stringBuffer usingFont: dateFont];
	NXSetColor (dateColor);	
	[dateFont set];
	PSmoveto (stringLocation.x, stringLocation.y - DATESTRING_OFFSET);
	PSshow (stringBuffer);
	return self;
}


- _drawMonth
{
    	char 	stringBuffer[10];
	NXPoint	stringLocation;
	
	if (wantsYear)
		sprintf (stringBuffer,"%s%.2d", 
			MONTHS[MONTH(displayTimeAndDate)], YEAR(displayTimeAndDate));
	else
		sprintf (stringBuffer,"%s", MONTHS[MONTH(displayTimeAndDate)]);
	
	stringLocation = [self _locationForString:stringBuffer usingFont: monthFont];
	NXSetColor (monthColor);	
	[monthFont set];
	PSmoveto (stringLocation.x, stringLocation.y - MONTHSTRING_OFFSET);
	PSshow (stringBuffer);
	return self;
}


//----------------------------------------------------------------------------------------------------
//	Initialization and Freeing
//----------------------------------------------------------------------------------------------------
+ initialize
{
	timeFont = [Font newFont:"Times-Italic" size:14 style:0 matrix:NX_IDENTITYMATRIX];
	dayOfWeekFont = [Font newFont:"Helvetica" size:8 style:0 matrix:NX_IDENTITYMATRIX];
	dateFont = [Font newFont:"Times-Roman" size:24 style:0 matrix:NX_IDENTITYMATRIX];
	monthFont = [Font newFont:"Helvetica-Oblique" size:9 style:0 matrix:NX_IDENTITYMATRIX];
	return self;
}


- initFrame: (const NXRect *)aRect
{
	//  Give default characteristics.  Fix size to 64 x 64. 
	
	NXRect	frameRect;
	NXSetRect (&frameRect, NX_X(aRect), NX_Y(aRect), 64.0, 64.0);
	[super initFrame:&frameRect];
	
	[self clockFace: [NXImage findImageNamed: "CalendarFace"]];
	[self timeColor: NX_COLORGREEN];
	[self weekdayColor: NX_COLORBLACK];
	[self dateColor: NX_COLORBLACK];
	[self monthColor: NX_COLORRED];
	[self wantsDate: YES];
	[self wantsYear: NO];
	
	return self;
}


//----------------------------------------------------------------------------------------------------
//	Accessing Display Colors
//----------------------------------------------------------------------------------------------------
- timeColor: (NXColor) aColor
{
	timeColor = aColor;
	[self update];
	return self;
}


- weekdayColor: (NXColor) aColor;
{
	weekdayColor = aColor;
	[self update];
	return self;
}


- dateColor: (NXColor) aColor;
{
	dateColor = aColor;
	[self update];
	return self;
}


- monthColor: (NXColor) aColor;
{
	monthColor = aColor;
	[self update];
	return self;
}


- (NXColor) timeColor
{
	return timeColor;
}


- (NXColor) weekdayColor;
{
	return weekdayColor;
}


- (NXColor) dateColor;
{
	return dateColor;
}


- (NXColor) monthColor;
{
	return monthColor;
}


//----------------------------------------------------------------------------------------------------
//	Enabling Year Display
//-----------------------------------------------------------------------------------------------------
- wantsYear: (BOOL) aFlag
{
	wantsYear = aFlag;
	[self update];
	return self;
}


- (BOOL) wantsYear
{
	return wantsYear;
}


//----------------------------------------------------------------------------------------------------
//	Action Methods
//----------------------------------------------------------------------------------------------------
- takeWantsYearFlagFrom :sender
{
	if ([sender isKindOf: [Matrix class]])
		sender = [sender selectedCell];
		
	if ([sender respondsTo: @selector (state)])
		[self wantsYear: [sender state]];
		
	return self;
}


- takeTimeColorFrom: sender
{
	if ([sender respondsTo: @selector (color)]) [self timeColor: [sender color]];
	return self;
}


- takeWeekdayColorFrom: sender
{
	if ([sender respondsTo: @selector (color)]) [self weekdayColor: [sender color]];
	return self;
}


- takeDateColorFrom: sender
{
	if ([sender respondsTo: @selector (color)]) [self dateColor: [sender color]];
	return self;
}


- takeMonthColorFrom: sender
{
	if ([sender respondsTo: @selector (color)]) [self monthColor: [sender color]];
	return self;
}


//-----------------------------------------------------------------------------------------------------
//	Draw Methods
//-----------------------------------------------------------------------------------------------------
- drawTime
{
    	int 		hour = HOUR(displayTimeAndDate);
    	char 	stringBuffer[10];
	NXPoint	stringLocation;
	
	if (! flags.wantsMilitaryTime)
		{
    		hour = fmod (HOUR(displayTimeAndDate),12);
    		if (! hour) hour = 12;
		}
		
	if (flags.wantsMilitaryTime)
		sprintf (stringBuffer, "%.2d:%.2d", hour, MINUTE(displayTimeAndDate));
	else
		sprintf (stringBuffer, "%d:%.2d", hour, MINUTE(displayTimeAndDate));

   	 if (flags.wantsSeconds)
		sprintf (stringBuffer, "%s:%.2d", stringBuffer, SECOND(displayTimeAndDate));
	else
		if (! flags.wantsMilitaryTime)
 			sprintf (stringBuffer, "%s %s", 
				stringBuffer, 
				(HOUR(displayTimeAndDate) < 12 ? "am" : "pm"));
  
	stringLocation = [self _locationForString:stringBuffer usingFont: timeFont];

	[timeFont set];
	NXSetColor (timeColor);	
	PSmoveto (stringLocation.x, stringLocation.y + TIMESTRING_OFFSET);
	PSshow (stringBuffer);

	return self;
}


- drawDate
{
	[self _drawDayOfWeek];
	[self _drawDate];
	[self _drawMonth];
	return self;
}


//----------------------------------------------------------------------------------------------------
//	Archiving Methods
//----------------------------------------------------------------------------------------------------
- read: (NXTypedStream*) stream
{
	[super read: stream];
	timeColor = NXReadColor (stream);
	weekdayColor = NXReadColor (stream);
	dateColor = NXReadColor (stream);
	monthColor = NXReadColor (stream);
	NXReadTypes (stream, "c", &wantsYear);
	return self;
}


- write: (NXTypedStream*) stream
{
	[super write: stream];
	NXWriteColor (stream, timeColor);
	NXWriteColor (stream, weekdayColor);
	NXWriteColor (stream, dateColor);
	NXWriteColor (stream, monthColor);
	NXWriteTypes (stream, "c", &wantsYear);
	return self;
}


//----------------------------------------------------------------------------------------------------
//	Superclass Overrides
//----------------------------------------------------------------------------------------------------
- wantsDate: (BOOL) aFlag
{
	return [super wantsDate: YES];
}


//----------------------------------------------------------------------------------------------------
//	IB Methods
//----------------------------------------------------------------------------------------------------
- getMinSize:(NXSize *)minSize maxSize:(NXSize *)maxSize from:(int)where
{
	//  Constrains resize within IB.
	
	minSize->width = maxSize->width = 64.0;
	minSize->height = maxSize->height = 64.0;
	return self;
}


- (const char*) getInspectorClassName
{
	//  Returns the name of the class responsible for managing custom 
	//  IB Attributes inspection.
		
	return "CalendarClockInspector";
}


@end