|
|
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.