1 // SimpleCalc -- Randy Nelson -- NeXT Developer Training
2 // A general class that serves as a liaison between a calculator interface
3 // and a calculator engine.
5 // You may freely copy, distribute and reuse the code in this example.
6 // NeXT disclaims any warranty of any kind, expressed or implied, as to
7 // its fitness for any particular use.
11 // C++ "linkage" directive - tells the C++ compiler that the following
12 // interface files contain Objective-C code.
16 #import <appkit/Application.h>
17 #import <appkit/Panel.h>
18 #import <appkit/TextField.h>
19 #import <appkit/Button.h>
24 #import <appkit/publicWraps.h>
25 #import <objc/error.h>
26 #import <objc/NXStringTable.h>
30 // The C++ "linkage" directive serves two purposes (when importing
31 // interface files that contain straight ANSI-C/Objective-C code). It:
33 // (a) allows you to link with libraries that have not been compiled with
34 // the C++ compiler. Since libraries on the NeXT computer are compiled
35 // with the Objective-C compiler (cc, not cc++), you must use the C++
36 // linkage directive when importing interface files that represent NeXT
37 // libraries (or any library that is not compiled with cc++).
39 // (b) tells the compiler to ignore C++ keywords that will result in
40 // syntax errors when importing ANSI-C/Objective-C interface files.
41 // The linkage directive essentially tells the C++ compiler to treat
42 // keywords (such as "new", "delete", etc.) as normal identifiers.
44 #import "SimpleCalc.h"
45 #import "CalcEngine.h"
46 #import "InfoManager.h"
48 @implementation SimpleCalc
50 // Initialize an instance of the SimpleCalc class. One instance variable of
51 // that class is the C++ calculator engine.
54 cplus_object
= new CalcEngine
; // new is a keyword in C++.
59 // Append a new digit entered by the user to the text field display.
60 - appendToDisplay
:(const char *)theDigit
62 char *copyOfDisplay
= NXCopyStringBuffer([display stringValue
]);
64 [display setStringValue
: strcat(copyOfDisplay
, theDigit
)];
69 // We need to keep a history of one action to make decisions about the display.
70 - registerAction
:(SEL)action
72 previousAction
= action
;
76 // The user has pushed the decimal key on the calculator.
79 if (previousAction
== @selector(operationKeys
:))
80 [display setStringValue
:"."];
82 if (strchr([display stringValue
], '.'))
85 [self appendToDisplay
:"."];
87 return [self registerAction
:_cmd
];
90 // One of the number keys was selected by the user.
94 int digit
= [sender selectedTag
];
96 sprintf(aDigit
, "%d", digit
);
98 if (previousAction
== @selector(operationKeys
:) ||
99 previousAction
== @selector(equalsKey
:))
101 [display setStringValue
:aDigit
];
103 if ([display doubleValue
] == 0 && !strchr([display stringValue
], '.'))
104 [display setStringValue
:aDigit
];
106 [self appendToDisplay
:aDigit
];
108 return [self registerAction
:_cmd
];
111 // The user pressed the equals key on the calculator interface.
114 if (previousAction
== 0)
118 [display setDoubleValue
:
119 cplus_object
->equalsKey([display doubleValue
])];
122 [myNXStringTable valueForStringKey
:"operationFailed"],
123 [myNXStringTable valueForStringKey
:NXLocalHandler.data1
],
124 [myNXStringTable valueForStringKey
:"OK"], NULL
, NULL
);
127 return [self registerAction
:_cmd
];
130 // The user pressed one of the operation keys.
131 - operationKeys
:sender
133 if (previousAction
== 0)
135 else if (previousAction
== @selector(operationKeys
:))
136 cplus_object
->setOperation([sender selectedTag
]);
139 [display setDoubleValue
:
140 cplus_object
->operationKeys([sender selectedTag
],
141 [display doubleValue
])];
144 [myNXStringTable valueForStringKey
:"operationFailed"],
145 [myNXStringTable valueForStringKey
:NXLocalHandler.data1
],
146 [myNXStringTable valueForStringKey
:"OK"], NULL
, NULL
);
149 return [self registerAction
:_cmd
];
152 // User pressed the Clear key.
155 [display setStringValue
:"0"];
159 // User pressed the Clear All key.
162 cplus_object
->clear();
163 [self registerAction
:0];
164 return [self clearKey
:sender
];
167 // Called just after the application initializes and starts up.
170 // Set the Enter key on the keypad to be equivalent to the = key.
171 [[display window
] addToEventMask
:NX_SYMBOLSET
];
172 [enterKey setKeyEquivalent
:3];
173 [[display window
] makeKeyAndOrderFront
:self];
177 // Called just before the window closes.
178 - windowWillClose
:sender
180 return [NXApp terminate
:self];
183 // Brings up the Info panel. Not done on startup because it's in a separate
184 // interface file. Saves startup time for the user if we do this when they ask
185 // for it, and not before.
188 if(infoManager
== nil){
189 infoManager
= [[InfoManager alloc
] init
];
191 [infoManager orderInfoPanelFront
:sender
];
195 // Brings up the Help panel. Not done on startup because it's in a separate
196 // interface file. Saves startup time for the user if we do this when they ask
197 // for it, and not before.
200 if(infoManager
== nil){
201 infoManager
= [[InfoManager alloc
] init
];
203 [infoManager orderHelpPanelFront
:sender
];