Edit (1/6/09): Thanks to one of my readers, we now have a secondary mirror site for downloading the video. Download locations: Mirror 1 Mirror 2
//
// CalcModel.h
// SimpleCalc
//
// Created by Chris Ball (chris.m.ball@gmail.com) on 1/17/08.
// Copyright 2008, Chris Ball, Strainthebrain.Blogspot.Com.
// All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface CalcModel : NSObject {
float running_total;
char sign_state;
bool first_call;
}
//Establishing some public-facing properties.
@property(readwrite) float running_total;
@property(readwrite) char sign_state;
@property(readwrite) bool first_call;
//Used for computing and maintaing the model data.
- (void) computeNewDisplayVal: (float) currDisplayVal;
@end
//
// CalcModel.m
// SimpleCalc
//
// Created by Chris Ball (chris.m.ball@gmail.com) on 1/17/08.
// Copyright 2008, Chris Ball, Strainthebrain.Blogspot.Com.
// All rights reserved.
//
#import "CalcModel.h"
@implementation CalcModel
//Implicity declaring the setters/getters for our properties.
@synthesize running_total, sign_state, first_call;
- (void) computeNewDisplayVal: (float) currDisplayVal {
if (self.first_call) {
self.running_total = currDisplayVal;
self.first_call = NO;
}
else {
switch (self.sign_state) {
case 'a':
self.running_total = self.running_total + currDisplayVal;
break;
case 'd':
self.running_total = self.running_total / currDisplayVal;
break;
case 'm':
self.running_total = self.running_total * currDisplayVal;
break;
case 's':
self.running_total = self.running_total - currDisplayVal;
break;
}
}
}
@end
//
// CalcController.h
// SimpleCalc
//
// Created by Chris Ball (chris.m.ball@gmail.com) on 1/17/08.
// Copyright 2008, Chris Ball, Strainthebrain.Blogspot.Com.
// All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "CalcModel.h"
@interface CalcController : NSObject {
IBOutlet id calc_display;
IBOutlet id a_button;
IBOutlet id s_button;
IBOutlet id m_button;
IBOutlet id d_button;
CalcModel* calc_model;
}
//Mathematical button events.
- (IBAction) push_add: (id) sender;
- (IBAction) push_divide: (id) sender;
- (IBAction) push_multiply: (id) sender;
- (IBAction) push_subtract: (id) sender;
//Numeric button events.
- (IBAction) push_zero: (id) sender;
- (IBAction) push_one: (id) sender;
- (IBAction) push_two: (id) sender;
- (IBAction) push_three: (id) sender;
- (IBAction) push_four: (id) sender;
- (IBAction) push_five: (id) sender;
- (IBAction) push_six: (id) sender;
- (IBAction) push_seven: (id) sender;
- (IBAction) push_eight: (id) sender;
- (IBAction) push_nine: (id) sender;
//Internal functions.
- (void) push_number: (id) sender;
- (BOOL) sign_pushed;
- (void) check_calc_model;
//Other button events.
- (IBAction) push_clear: (id) sender;
- (IBAction) push_decimal: (id) sender;
- (IBAction) push_equal: (id) sender;
@end
//
// CalcController.m
// SimpleCalc
//
// Created by Chris Ball (chris.m.ball@gmail.com) on 1/17/08.
// Copyright 2008, Chris Ball, Strainthebrain.Blogspot.Com.
// All rights reserved.
//
#import "CalcController.h"
#import <RegexKit/RegexKit.h>
@implementation CalcController
- (IBAction) push_add: (id) sender {
if ([m_button state] == NSOnState || [s_button state] == NSOnState || [d_button state] == NSOnState) {
[a_button setState:NSOffState];
}
else {
[self check_calc_model];
if (!calc_model.first_call)
[self push_equal:0];
calc_model.sign_state = 'a';
[calc_model computeNewDisplayVal:[calc_display floatValue]];
[calc_display setFloatValue:calc_model.running_total];
}
}
- (IBAction) push_divide: (id) sender {
if ([a_button state] == NSOnState || [s_button state] == NSOnState || [m_button state] == NSOnState) {
[d_button setState:NSOffState];
}
else {
[self check_calc_model];
if (!calc_model.first_call)
[self push_equal:0];
calc_model.sign_state = 'd';
[calc_model computeNewDisplayVal:[calc_display floatValue]];
[calc_display setFloatValue:calc_model.running_total];
}
}
- (IBAction) push_multiply: (id) sender {
if ([a_button state] == NSOnState || [s_button state] == NSOnState || [d_button state] == NSOnState)
[m_button setState:NSOffState];
else {
[self check_calc_model];
if (!calc_model.first_call)
[self push_equal:0];
calc_model.sign_state = 'm';
[calc_model computeNewDisplayVal:[calc_display floatValue]];
[calc_display setFloatValue:calc_model.running_total];
}
}
- (IBAction) push_subtract: (id) sender {
if ([a_button state] == NSOnState || [m_button state] == NSOnState || [d_button state] == NSOnState)
[s_button setState:NSOffState];
else {
[self check_calc_model];
if (!calc_model.first_call)
[self push_equal:0];
calc_model.sign_state = 's';
[calc_model computeNewDisplayVal:[calc_display floatValue]];
[calc_display setFloatValue:calc_model.running_total];
}
}
- (IBAction) push_zero: (id) sender {
[self push_number:sender];
}
- (IBAction) push_one: (id) sender {
[self push_number:sender];
}
- (IBAction) push_two: (id) sender {
[self push_number:sender];
}
- (IBAction) push_three: (id) sender {
[self push_number:sender];
}
- (IBAction) push_four: (id) sender {
[self push_number:sender];
}
- (IBAction) push_five: (id) sender {
[self push_number:sender];
}
- (IBAction) push_six: (id) sender {
[self push_number:sender];
}
- (IBAction) push_seven: (id) sender {
[self push_number:sender];
}
- (IBAction) push_eight: (id) sender {
[self push_number:sender];
}
- (IBAction) push_nine: (id) sender {
[self push_number:sender];
}
- (void) push_number: (id) sender {
if ([self sign_pushed]) {
[a_button setState:0];
[d_button setState:0];
[m_button setState:0];
[s_button setState:0];
[calc_display setStringValue:@""];
}
if ([[calc_display stringValue] compare:@"0"] && !calc_model.first_call)
[calc_display setStringValue:[[calc_display stringValue] stringByAppendingString:[sender title]]];
else
[calc_display setStringValue:[sender title]];
}
- (BOOL) sign_pushed {
if ([a_button state] == NSOnState || [s_button state] == NSOnState || [m_button state] == NSOnState || [d_button state] == NSOnState)
return YES;
else return NO;
}
- (void) check_calc_model {
@try {
if (calc_model == nil) {
calc_model = [[CalcModel alloc] init];
calc_model.first_call = YES;
}
}
@catch (NSException *ex) {
NSLog(@"check_calc_model: Caught %@: %@", [ex name], [ex reason]);
}
}
- (IBAction) push_clear: (id) sender {
if (calc_model != nil) {
[calc_model release];
calc_model = nil;
}
[calc_display setIntValue:0];
if ([self sign_pushed]) {
[a_button setState:0];
[d_button setState:0];
[m_button setState:0];
[s_button setState:0];
}
}
- (IBAction) push_decimal: (id) sender {
if ([self sign_pushed]) {
[a_button setState:0];
[d_button setState:0];
[m_button setState:0];
[s_button setState:0];
[calc_display setStringValue:@""];
}
if (![[calc_display stringValue] isMatchedByRegex:@"[.]"])
[calc_display setStringValue:[[calc_display stringValue] stringByAppendingString:@"."]];
}
- (IBAction) push_equal: (id) sender {
[self check_calc_model];
[calc_model computeNewDisplayVal:[calc_display floatValue]];
[calc_display setFloatValue:calc_model.running_total];
calc_model.first_call = YES;
}
@end
