Top of the page
Close

This is a red error

This is a red error

This is a red error

Building a Cocoa Calculator Application with XCode 3

Ondrej Rafaj on 2009.07.06 13:22:52

If you love Macs and are interested in learning how to build applications, this is the first in a series of screencasts showing how to build the interface.

In the second part in a series showing how to take the GUI interface of our calculator and set up event handling through actions and outlets using Xcode 3 on Mac! The third part of the series is unfortunately too long to post on youtube (25 minutes). It can be viewed on the blog at: http://strainthebrain.blogspot.com or downloaded here,

Part 1:

 

Part 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 

@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 
#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 

@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

Ondrej Rafaj

Ondrej Rafaj

Technical director @ Fuerte International

Back to top Comment

Comments ... Why not to get involved!
HTML Comment Box is loading comments...

Old comments:

Back to top

IE SUCKS, DON'T USE IT :) Digg this page