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.