|
|
1.1 root 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.
4: //
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.
8: //
9: // Created 8-22-90
10: //
11: // C++ "linkage" directive - tells the C++ compiler that the following
12: // interface files contain Objective-C code.
13:
14: extern "Objective-C"
15: {
16: #import <appkit/Application.h>
17: #import <appkit/Panel.h>
18: #import <appkit/TextField.h>
19: #import <appkit/Button.h>
20: }
21:
22: extern "C"
23: {
24: #import <appkit/publicWraps.h>
25: #import <objc/error.h>
26: #import <objc/NXStringTable.h>
27: #import <strings.h>
28: }
29:
30: // The C++ "linkage" directive serves two purposes (when importing
31: // interface files that contain straight ANSI-C/Objective-C code). It:
32: //
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++).
38: //
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.
43:
44: #import "SimpleCalc.h"
45: #import "CalcEngine.h"
46: #import "InfoManager.h"
47:
48: @implementation SimpleCalc
49:
50: // Initialize an instance of the SimpleCalc class. One instance variable of
51: // that class is the C++ calculator engine.
52: - init
53: {
54: cplus_object = new CalcEngine; // new is a keyword in C++.
55: previousAction = 0;
56: return self;
57: }
58:
59: // Append a new digit entered by the user to the text field display.
60: - appendToDisplay:(const char *)theDigit
61: {
62: char *copyOfDisplay = NXCopyStringBuffer([display stringValue]);
63:
64: [display setStringValue: strcat(copyOfDisplay, theDigit)];
65:
66: return self;
67: }
68:
69: // We need to keep a history of one action to make decisions about the display.
70: - registerAction:(SEL)action
71: {
72: previousAction = action;
73: return self;
74: }
75:
76: // The user has pushed the decimal key on the calculator.
77: - decimalKey:sender
78: {
79: if (previousAction == @selector(operationKeys:))
80: [display setStringValue:"."];
81: else {
82: if (strchr([display stringValue], '.'))
83: NXBeep();
84: else
85: [self appendToDisplay:"."];
86: }
87: return [self registerAction:_cmd];
88: }
89:
90: // One of the number keys was selected by the user.
91: - numberKeys:sender
92: {
93: char aDigit[2];
94: int digit = [sender selectedTag];
95:
96: sprintf(aDigit, "%d", digit);
97:
98: if (previousAction == @selector(operationKeys:) ||
99: previousAction == @selector(equalsKey:))
100: {
101: [display setStringValue:aDigit];
102: } else {
103: if ([display doubleValue] == 0 && !strchr([display stringValue], '.'))
104: [display setStringValue:aDigit];
105: else
106: [self appendToDisplay:aDigit];
107: }
108: return [self registerAction:_cmd];
109: }
110:
111: // The user pressed the equals key on the calculator interface.
112: - equalsKey:sender
113: {
114: if (previousAction == 0)
115: NXBeep();
116: else {
117: NX_DURING
118: [display setDoubleValue:
119: cplus_object->equalsKey([display doubleValue])];
120: NX_HANDLER
121: NXRunAlertPanel(
122: [myNXStringTable valueForStringKey:"operationFailed"],
123: [myNXStringTable valueForStringKey:NXLocalHandler.data1],
124: [myNXStringTable valueForStringKey:"OK"], NULL, NULL);
125: NX_ENDHANDLER
126: }
127: return [self registerAction:_cmd];
128: }
129:
130: // The user pressed one of the operation keys.
131: - operationKeys:sender
132: {
133: if (previousAction == 0)
134: NXBeep();
135: else if (previousAction == @selector(operationKeys:))
136: cplus_object->setOperation([sender selectedTag]);
137: else {
138: NX_DURING
139: [display setDoubleValue:
140: cplus_object->operationKeys([sender selectedTag],
141: [display doubleValue])];
142: NX_HANDLER
143: NXRunAlertPanel(
144: [myNXStringTable valueForStringKey:"operationFailed"],
145: [myNXStringTable valueForStringKey:NXLocalHandler.data1],
146: [myNXStringTable valueForStringKey:"OK"], NULL, NULL);
147: NX_ENDHANDLER
148: }
149: return [self registerAction:_cmd];
150: }
151:
152: // User pressed the Clear key.
153: - clearKey:sender
154: {
155: [display setStringValue:"0"];
156: return self;
157: }
158:
159: // User pressed the Clear All key.
160: - clearAllKey:sender
161: {
162: cplus_object->clear();
163: [self registerAction:0];
164: return [self clearKey:sender];
165: }
166:
167: // Called just after the application initializes and starts up.
168: - appDidInit:sender
169: {
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];
174: return self;
175: }
176:
177: // Called just before the window closes.
178: - windowWillClose:sender
179: {
180: return [NXApp terminate:self];
181: }
182:
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.
186: - infoPanel:sender
187: {
188: if(infoManager == nil){
189: infoManager = [[InfoManager alloc] init];
190: }
191: [infoManager orderInfoPanelFront:sender];
192: return self;
193: }
194:
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.
198: - helpPanel:sender
199: {
200: if(infoManager == nil){
201: infoManager = [[InfoManager alloc] init];
202: }
203: [infoManager orderHelpPanelFront:sender];
204: return self;
205: }
206:
207: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.