I want a graphic clock, which looks like this:
It is very simple. I only need to add a new GUI component in the class TimeView. I call this new class "ClockView". Since "ClockView" will be the subview of "TimeView", when "TimeView" is update, I also need to update the "ClockView".
ClockView.h:
#import <AppKit/AppKit.h>
#include <math.h>
@interface ClockView : NSView
{
NSPoint posHour, posMinute;
}
- (void) setDate: (NSCalendarDate *) aDate;
@end
ClockView.m:
#import "ClockView.h"
@implementation ClockView
- (id) init
{
self = [super init];
posHour = NSMakePoint(0,0);
posMinute = NSMakePoint(0,0);
return self;
}
- (void) drawRect: (NSRect) frame
{
NSPoint origin = NSMakePoint(frame.size.width/2, frame.size.height/2);
NSBezierPath *bp = [NSBezierPath bezierPathWithRect: [self bounds]];
[[NSColor yellowColor] set];
[BP fill];
BP = [NSBezierPath bezierPathWithRect: NSMakeRect(1, 1,
frame.size.width-2,
frame.size.height-2)];
[[NSColor blackColor] set];
[BP stroke];
BP = [NSBezierPath bezierPath];
[BP setLineWidth: 3];
[BP moveToPoint: origin];
[BP relativeLineToPoint: posHour];
[BP stroke];
[BP setLineWidth: 1];
[BP moveToPoint: origin];
[BP relativeLineToPoint: posMinute];
[BP stroke];
}
- (void) setDate: (NSCalendarDate *) date;
{
int hour = [date hourOfDay];
int minute = [date minuteOfHour];
float hour_x = 40*sin((M_PI*hour/6)+(M_PI*minute/360));
float hour_y = 40*cos((M_PI*hour/6)+(M_PI*minute/360));
float minute_x = 60*sin(M_PI*minute/30);
float minute_y = 60*COs(M_PI*minute/30);
posHour = NSMakePoint(hour_x, hour_y);
posMinute = NSMakePoint(minute_x, minute_y);
[self setNeedsDisplay: YES];
}
@end
ClockView inherits from NSView. The most important method it should override is -drawRect:. When this view need to update, -drawRect: will be called. Therefore, I put all the drawing in this method. NSBezierPath is how GNUstep draws. I assign the path, set the color, then draw. There are good article about drawing: Introduction to Cocoa Graphics, Part I, Part II.
A few codes are needed to include ClockView in TimeView. One is to add ClockView as a subview of NSBox in TimeView. Another is to update ClockView when TimeView is update. In method -setDate: of ClockView, it uses [self setNeedsDisplay: YES] to make this view update. This modification is easy to do. You can play around it.