EdenMath Tutorial - How to create a scientific calculator with Cocoa

Purpose
Upon a programmer's first brush with the Cocoa API (based upon Next's derivative of Objective-C), this new language can seem a little befuddling to the uninitiated with different terms and new methods to design interfaces.
While I will try and dumb down this tutorial enough so I don't lose too many people (myself included), I'm not going to stop to explain basic programming concepts (i.e. What's a compiler?). If you are reading this tutorial, hopefully you have at least some background in programming, preferably in C, C++, Java, or best yet, Objective-C.
To create your own scientific calculator, you will need these items:

- A Macintosh computer with Mac OS X (preferably 10.1)
- Project Builder (1.1 for OS 10.1)

The EdenMath scientific calculator was designed on a Year 2000 400 MHz G4 PowerMac with 320 MB of RAM and a Year 2001 500 MHz G3 Ice iBook with 320 MB of RAM. Both ran Mac OS 10.1 and Project Builder 1.1. Project Builder and other Apple Developer tools can be acquired by purchasing a retail version of OS X, or by joining the free ADC membership and downloading the tools.
There are some small differences in interface design between Project Builder 1.0 (available for OS 10.0.x) and Project Builder 1.1. I will make note of any differences I can find. If you need more reference to PB 1.0, the book Learning Cocoa is a good r eference.
Disclaimer
As with any program, there are multiple ways to design and implement it. What is being offered in this tutorial is just one way of many. I make no offer that this is necessarily the best or the slickest way to go about creating a calculator. It comes down to this: the program works, and it works well.
Since EdenMath is freeware, and this tutorial was included, EdenMath and its code should be used for educational purposes. Do not redistribute or steal the code to put into your own application and claim it is yours. Anyway, it would be pretty silly to just steal this code, recompile it, and distribute another Scientific Calculator out there, especially since there are quite a few already available (some for free, others available as shareware). And if free isn't good enought for you, well...what's wro ng with you? Isn't enough that I spent my own time to create this application, AND be nice enough to create a tutorial and make the source code available?!
Starting Out
1. Start up the Project Builder (/Developer/Applications/Project Builder).
2. Select a Cocoa Application (not a Document-based application).
3. Name the program whatever you want. In this example, it has been named EdenMath.
Main.m
By default, there should be a main.m file in the Other Sources file. You don't need to make any modifications to it. The #import <Cocoa/Cocoa.h> line can be also replaced with #import <AppKit /AppKit.h>.
The entire main.m file will look like this:

    #import <Cocoa/Cocoa.h>

    int main(int argc, const char *argv[])
    {
        return NSApplicationMain(argc, argv);
    }

Setting Up the Interface
1. Open up the MainMenu.nib by double-clicking on the NIB file in the Resources folder.
2. Click on the window where the interface will be added. Go to the Tools menu and click on Show Info.
3. The Window Info window should appear. Select the Attributes option in the drop down menu if it is not already selected.
4. In the Title field, type in the name of your application. In this case, I gave the name EdenMath.
Adding a Display
1. In the Views palette, drag a text field (underneath the Button) and drag it over to the interface window.
2. In the NSTextField Info palette, select the alignment to be right aligned ->|.
3. Type the number 0 for the Title.
Adding a Controller
1. In the MainMenu.nib window, click on the Classes tab.
2. If necessary, scroll around until you find the NSObject and click on NSObject to highlight it.
3. Go to the Classes menu and click on Subclass NSObject.
4. Double-click on MyObject to rename it. In this example, I named it EMController.
5. Highlight the EMController in the MainMenu.nib. In the EMController Class Info palette, click on the + to the right of Outlet text. Rename myOutlet to displayField.
6. Make an instance of the EMController class by going to the Classes menu and selecting Instantiate EMController.
7. Now connect the EMController to the display. CTRL-click and drag a line from EMController to the text field in the interface window.
8. Click the Connect button in the EMController (Custom) Info palette.
Generating Files
1. Go to the Classes pane of the nib file window.
2. Select the EMController class.
3. Choose Create Files from the Classes menu.
4. The Interface Builder will then display a dialog box. Verify that the checkboxes in the Create column next to the .h and .m files are selected.
5. Verify that the checkbox next to Nib Files is selected.
6. Click the Choose button.
Creating Responder
Now it's time to create a responder class which will respond to the input the EMController brings in.
1. Go to File -> New File.
2. Create a new Objective-C file, and name it EMResponder. Two files will be generated, EMResponder.h and EMResponder.m.
3. In the EMController.h and EMController.m, add the line #import <EMResponder.h>
4. Since this program will deal heavily with math (being a calculator and all), add the line #include <math.h> to the top of the EMResponder.h file.
Begin Coding
Now it's time to begin the real 'fun'. Starting out takes a bit of explaining, but soon things will start rolling along quite smoothly. For right now, we are going to set up the initial functions and connections between the two main classes: EMControlle r and EMResponder. Let's start with the EMController files, then move on to EMResponder.
As with many header files, EMController contains the main variables, other types (such as structures or enumerated types) and function/method prototypes. These functions (or methods as they are sometimes referred as) will be in the EMController.m file. Here is the EMController.h file. Copy or type it into your own header file.
EMController.h

    #import <Foundation/Foundation.h>
    #import <AppKit/AppKit.h>
    #import "EMResponder.h"

    @interface EMController : NSObject
    {
        EMResponder *em; 			// model responder to buttons
        IBOutlet NSTextField *displayField; // display field showing output
        NSUndoManager *undoManager;		// the undo manager
    }

    // prototypes for EMController class methods will go under here

    @end

Currently, the EMController.m file is pretty small, and it only allocates and deallocates memory for the program to run. Many more functions will be added in later which will communicate with the EMResponder. The comments should hopefully explain most o f what is going on so far. Here is the file for EMController.m so far.
EMController.m.

    #import "EMController.h"

    @implementation EMController

    // -------------------------------------------------------
    // (id)init
    // Allocate memory and french fries for EdenMath
    // -------------------------------------------------------
    - (id)init
    {
        em 		= [[EMResponder alloc] init];
        undoManager = [[NSUndoManager alloc] init];
        return self;
    }

    // -------------------------------------------------------
    // (id)dealloc
    // Deallocate/free up memory used by Edenmath
    // -------------------------------------------------------
    - (void)dealloc
    {
        [em release];
        [undoManager release];
        [super dealloc];
    }

    @end

EMResponder.h

    #import <Foundation/Foundation.h>

    typedef enum Op_Type
    {
        NO_OP 	= 0,
        ADD_OP 	= 1,
        SUBTRACT_OP = 2,
        MULTIPLY_OP = 3,
        DIVIDE_OP 	= 4,
        EXPONENT_OP = 5,
        XROOT_OP 	= 6,
        MOD_OP 	= 7,
        EE_OP 	= 8,
        NPR_OP 	= 9,
        NCR_OP 	= 10
    } OpType;

    typedef enum Angle_Type
    {
        DEGREE 	= 0,
        RADIAN 	= 1,
        GRADIENT 	= 2
    } AngleType;

    @interface EMResponder : NSObject
    {
        double current_value;		// the current number (which is being edited)
        double previous_value;              // the other operand (previous operand)
        double e_value;			// the number e
        OpType op_type;		        // the current operator
        AngleType angle_type;	     	// type of angle used (radian, degree, gradient)
        int trailing_digits;                // used in decimal number input
        BOOL startNewDigit;                 // allow new number in display
    }

    @end

EMResponder.m

    #import "EMResponder.h"

    #include <math.h>

    @implementation EMResponder

    // -------------------------------------------------------
    // (id) init
    // -------------------------------------------------------
    - (id) init
    {

        current_value	= 0.0;
        previous_value	= 0.0;
        op_type	 	= NO_OPERATOR;
        angle_type 		= DEGREE;
        e_value		= 2.718281828;
        trailing_digits 	= 0;
        startNewDigit	= YES;

        return self;
    }

    @end

Adding a Help Menu
http://www.oreillynet.com/pub/a/mac/2001/05/25/mac_help.html
Creating Icons
(Note: modified instructions from Learning Cocoa, pages 316-318)
1. Launch Photoshop and make a new 128 x 128 image with a transparent background. To make the background transparent, in the box where the layers are shown, click on the eye icon to make the current layer invisible.
2. Draw or copy the art into the document.
3. Create a new image channel usin the Channels tab. This new channel will function as an alpha mask. Paint the areas of the mask that you wish to be transparent in the finder and in the Dock.
4. Save the file as a TIFF image. This is the recommended format for image files used in Cocoa.
5. Launch the Icon Composer application in /Developer/Applications.
6. Choose Import Image from the File menu. Icon Composer's Open dialog box features a pop-up menu that lets you specify what kind of icon to make from the imported image. You'll need a thumbnail icon at the very least, so select Thumbnail 32 Bit Data fr om the Import To pop up at the bottom of the dialog box and open the TIFF document.
7. Drag and drop the image from the Thumbnail row to the huge, Large, and SMall rows. Icon compser will automatically scale the image for each size. If your icon imagery doesn't scale well, you can create variations for each so users can clearly identif y your application's icon no matter the icon size.
8. Save the file from Icon Composer as Edenmath.icns.
9. Add the icon file to the Project Builder project. It's a good idea to copy the file into the project directory so it will travel with the project.
10. In the Application Settings pane, type the name of the icon file in the text field labeled Icon.
11. Build the project. You should see the new icon in the finder, and it should appear in the Dock when the application is launched. However, if you create the icon and add it to the project before the essential Cocoa code is written, the icon will not appear in the Dock.

Version 1.0
Last modified: 23. February 2002