home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.0 / NeXTSTEP3.0.iso / NextDeveloper / Examples / AppKit / CalculatorLab / SimpleCalc.m < prev   
Text File  |  1990-10-29  |  5KB  |  242 lines

  1. /*
  2.  *    SimpleCalc -- Randy Nelson
  3.  *    A general class that directly supports a calculator interface
  4.  *    Created 8-8-90
  5.  *
  6.  *    You may freely copy, distribute and reuse the code in this example.
  7.  *    NeXT disclaims any warranty of any kind, expressed or implied, as to
  8.  *    its fitness for any particular use.
  9.  */
  10.  
  11. #import "SimpleCalc.h"
  12. #import <appkit/Application.h>
  13. #import <objc/NXStringTable.h>
  14. #import <appkit/Panel.h>
  15. #import <appkit/Text.h>
  16. #import <appkit/Button.h>
  17. #import <appkit/publicWraps.h>
  18. #import <stdio.h>
  19. #import <strings.h>
  20.  
  21. #define DECIMALPOINT 10
  22. #define DIVIDE 20
  23. #define MULTIPLY 21
  24. #define SUBTRACT 22
  25. #define ADD 23
  26. #define CLEAR 31
  27. #define CLEARALL 30
  28.  
  29. @implementation SimpleCalc
  30. - init
  31. {
  32.     [super init];
  33.     [self doInit];
  34.     return self;
  35. }
  36.  
  37. - doInit
  38. {
  39.     accumulator = 0;
  40.     operator = 0;
  41.     numberHasADecimal = NO;
  42.     startingSecondNumber = NO;
  43.     treatingOperationKeyLikeEqualKey = NO;
  44.     noFirstNumber = YES;
  45.     return self;
  46. }
  47.  
  48. - numberKeys:sender
  49. {
  50.     c7&    aDigit[2];
  51.     int     digit = [sender selectedTag];
  52.     
  53.     noFirstNumber = NO;
  54.     
  55.     /* clear the display in order to begin the second number */
  56.     if(startingSecondNumber == YES){
  57.     [display setStringValue:""];
  58.     startingSecondNumber = NO;
  59.     }
  60.     if(digit == DECIMALPOINT){
  61.     [self decimal];
  62.     return self;
  63.     }
  64.     sprintf(aDigit, "%d", digit);
  65.     [self appendToDisplay:(const char *)aDigit];
  66.     return self;
  67. }
  68.  
  69. - decimal
  70. {
  71.     if(numberHasADecimal == YES){
  72.     NXBeep();
  73.     return self;
  74.     }
  75.     /* internationalizable strings */
  76.     [self appendToDisplay:[stringSet valueForStringKey:"decimalPointString"]];
  77.     numberHasADecimal = YES;
  78.     return self;
  79. }
  80.  
  81. - operationKeys:sender
  82. {
  83.     //do nothing if noFirstNumber
  84.     if(noFirstNumber == YES){
  85.     NXBeep();
  86.     return self;
  87.     }
  88.     
  89.    /* if there's an operation and a first and second number
  90.     * act like the equal key was pressed
  91.     */
  92.     if((treatingOperationKeyLikeEqualKey == YES) &&
  93.       (startingSecondNumber == NO)){
  94.     [self equalsKey:self];
  95.     }
  96.     operator = [sender selectedTag];
  97.     switch(operator){
  98.     case DIVIDE: case MULTIPLY: case SUBTRACT: case ADD:{
  99.         accumulator = [display doubleValue];
  100.         numberHasADecimal = NO;
  101.         startingSecondNumber = YES;
  102.         treatingOperationKeyLikeEqualKey = YES;
  103.         break;
  104.     }
  105.     default:{
  106.         return self;
  107.     }
  108.     }
  109.     return self;
  110. }
  111.  
  112. - equalsKey:sender
  113. {
  114.     /* do nothing if noFirstNumber */
  115.     if(noFirstNumber == YES){
  116.         NXBeep();
  117.         return self;
  118.     }
  119.     switch(operator){
  120.     case DIVIDE:{
  121.         if([display doubleValue] == 0){
  122.         //can't divide by zero
  123.         NXBeep();
  124.         return self;
  125.         }
  126.         [display setDoubleValue:(accumulator / [display doubleValue])];
  127.         break;
  128.     }
  129.     case MULTIPLY:{
  130.         [display setDoubleValue:(accumulator * [display doubleValue])];
  131.         break;
  132.     }
  133.     case SUBTRACT:{
  134.         [display setDoubleValue:(accumulator - [display doubleValue])];
  135.         break;
  136.     }
  137.     case ADD:{
  138.         [display setDoubleValue:(accumulator + [display doubleValue])];
  139.         break;
  140.     }
  141.     default:{
  142.         return self;
  143.     }
  144.     }
  145.    /* just lke doInit
  146.     * but startingSecondNumber gets YES
  147.     * and noFirstNumber continues to be NO (there is a first number)
  148.     */
  149.     operator = 0;
  150.     accumulator = 0;
  151.     numberHasADecimal = NO;
  152.     startingSecondNumber = YES;
  153.     treatingOperationKeyLikeEqualKey = NO;
  154.     return self;
  155. }
  156.  
  157. - clearKeys:sender
  158. {
  159.     switch([sen7&selectedTag]){
  160.     case CLEAR:{
  161.         [display setStringValue:[stringSet
  162.                         valueForStringKey:"zeroString"]];
  163.         numberHasADecimal = NO;
  164.         startingSecondNumber = YES;
  165.         break;
  166.     }
  167.     case CLEARALL:{
  168.         [display setStringValue:[stringSet
  169.                         valueForStringKey:"zeroString"]];
  170.         [self doInit];
  171.         break;
  172.     }
  173.     default:{
  174.         break;
  175.     }
  176.     }
  177.     return self;
  178. }
  179.  
  180. - appendToDisplay:(const char *)theDigit
  181. {
  182.     char *copyOfDisplay = NXCopyStringBuffer([display stringValue]);
  183.     
  184.     /* if the display's current value is zero */
  185.     if([display doubleValue] == 0){
  186.     
  187.     /* and the zero doesn't have a decimal point */
  188.     if(numberHasADecimal == NO){
  189.         
  190.         /* replace the display with the digit passed */
  191.         [display setStringValue:theDigit];
  192.         return self;
  193.     }
  194.     }    
  195.    /* otherwise append the digit passed
  196.     * to the digits already in the display
  197.     */
  198.     [display setStringValue:strcat(copyOfDisplay, theDigit)];
  199.     
  200.     return self;
  201. }
  202.  
  203. - numberDirectFromDisplay:sender
  204. {
  205.     noFirstNumber = NO;
  206.     startingSecondNumber = YES;
  207.     return self;
  208. }
  209.  
  210. - appDidInit:sender
  211. {
  212.     /* enter key can't be set as key equivalent from IB */
  213.     [enterKey setKeyEquivalent:3];
  214.     [[display window] makeKeyAndOrderFront:self];
  215.     return self;
  216. }
  217.  
  218. - windowWillClose:window
  219. {
  220.     return [NXApp terminate:self];
  221. }
  222.  
  223. - infoPanel:sender
  224. {
  225.     if(infoPanel == nil){
  226.     [NXApp loadNibSection:"Info.nib" owner:self];
  227.     }
  228.     [infoPanel orderFront:sender];
  229.     return self;    
  230. }
  231.  
  232. - helpPanel:sender
  233. {
  234.     if(helpPanel == nil){
  235.     [NXApp loadNibSection:"Help.nib" owner:self];
  236.     }
  237.     [helpPanel orderFront:sender];
  238.     return self;    
  239.  
  240. }
  241. @end
  242.