Calculator by Michael Schmidt : Calculator « SWT JFace Eclipse « Java






Calculator by Michael Schmidt

Calculator by Michael Schmidt

/**
 * Instances of this object class open a dialog with a simple calculator.
 * The calculator includes a memory register, Tooltips for the keys, and error 
 * checking.  It performs double precision calculations and includes square 
 * root and inverse functions.  Other computations can be added easily.
 * The code contains extensive comments.    
 * This class can be called via an Action from the menu or toolbar.
 * Feel free to use this in your application!
 * 
 * @author Michael Schmidt, 2006.
 */
//package mschmidt.komo;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class CalculatorMichaelSchmidt extends Dialog {

  /*
  * Initialize variables needed for this class.
  */
  private Text displayText;
  // The three calculator registers.
  private String displayString = "0.";
  private String memoryString = new String();
  private String operatorString = new String();
  // A variable to store the pending calculation
  private char calcChar = ' ';
  // Error strings
  private final String ERROR_STRING = "Error: ";
  private final String NAN_STRING = "Not a Number";
  private final String LONG_STRING = "Number too long";
  private final String INFINITY_STRING = "Infinity";
  // A flag to check if display should be cleared on the next keystroke
  private boolean clearDisplay = true;
  // An ID constant for the copy to clipboard key
  private static final int CLIPBOARD_ID = IDialogConstants.NO_TO_ALL_ID + 1;

  public static void main(String[] a){
    new CalculatorMichaelSchmidt(new Shell(new Display()));
    
  }
  
  /*
   * Standard constructor to create the dialog.
   * @param parentShell the Dialog shell
   */
  public CalculatorMichaelSchmidt(final Shell parentShell) {
    super(parentShell);
  }

  /*
   * Create contents of the dialog, a display at the top and the various
   * buttons.  The Tooltip for each button explains its function.
   * @param parent the composite
   * @return Control the controls
   */
  @Override
  protected Control createDialogArea(final Composite parent) {
    Composite container = (Composite) super.createDialogArea(parent);
    final GridLayout calculatorGridLayout = new GridLayout();
    calculatorGridLayout.marginRight = 5;
    calculatorGridLayout.marginLeft = 5;
    calculatorGridLayout.marginBottom = 5;
    calculatorGridLayout.marginTop = 5;
    calculatorGridLayout.marginWidth = 10;
    calculatorGridLayout.marginHeight = 2;
    calculatorGridLayout.numColumns = 4;
    calculatorGridLayout.verticalSpacing = 2;
    calculatorGridLayout.makeColumnsEqualWidth = true;
    calculatorGridLayout.horizontalSpacing = 2;
    container.setLayout(calculatorGridLayout);

    // The display.  Note that it has a limit of 30 characters, 
    // much greater than the length of a double-precision number. 
    displayText = new Text(container, SWT.RIGHT | SWT.BORDER);
    displayText.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
    displayText.setEditable(false);
    displayText.setDoubleClickEnabled(false);
    displayText.setTextLimit(30);
    displayText.setText(displayString);
    displayText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 4, 1));

    final Button msButton = new Button(container, SWT.NONE);
    msButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateMemory('S');
      }
    });
    msButton.setToolTipText("Save value to Memory");
    msButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    msButton.setText("MS");

    final Button mcButton = new Button(container, SWT.NONE);
    mcButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('D');
      }
    });
    mcButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    mcButton.setToolTipText("Clear Memory");
    mcButton.setText("MC");

    final Button clearButton = new Button(container, SWT.NONE);
    clearButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('C');
      }
    });
    clearButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    clearButton.setToolTipText("Clear all Calculator Registers");
    clearButton.setText("C");

    final Button ceButton = new Button(container, SWT.NONE);
    ceButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('E');
      }
    });
    ceButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    ceButton.setToolTipText("Clear Entry");
    ceButton.setText("CE");

    final Button memAddButton = new Button(container, SWT.NONE);
    memAddButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateMemory('+');
      }
    });
    memAddButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    memAddButton.setToolTipText("Add value to Memory");
    memAddButton.setText("M+");

    final Button mrButton = new Button(container, SWT.NONE);
    mrButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('R');
      }
    });
    mrButton.setToolTipText("Recall value in Memory");
    mrButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    mrButton.setText("MR");

    final Button backButton = new Button(container, SWT.NONE);
    backButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('B');
      }
    });
    backButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    backButton.setToolTipText("Backspace");
    backButton.setText("BACK");

    final Button divideButton = new Button(container, SWT.NONE);
    divideButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateCalc('/');
      }
    });
    divideButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    divideButton.setToolTipText("Divide");
    divideButton.setText("/");

    final Button memSubtractButton = new Button(container, SWT.NONE);
    memSubtractButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateMemory('-');
      }
    });
    memSubtractButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    memSubtractButton.setToolTipText("Subtract value from Memory");
    memSubtractButton.setText("M-");

    final Button inverseButton = new Button(container, SWT.NONE);
    inverseButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('I');
      }
    });
    inverseButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    inverseButton.setToolTipText("Inverse of value");
    inverseButton.setText("1/X");

    final Button sqrtButton = new Button(container, SWT.NONE);
    sqrtButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('Q');
      }
    });
    sqrtButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    sqrtButton.setToolTipText("Square Root of value");
    sqrtButton.setText("SQRT");

    final Button multiplyButton = new Button(container, SWT.NONE);
    multiplyButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateCalc('*');
      }
    });
    multiplyButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    multiplyButton.setToolTipText("Multiply");
    multiplyButton.setText("*");

    final Button num7Button = new Button(container, SWT.NONE);
    num7Button.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('7');
      }
    });
    num7Button.setToolTipText("Numeric Pad");
    num7Button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    num7Button.setText("7");

    final Button num8Button = new Button(container, SWT.NONE);
    num8Button.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('8');
      }
    });
    num8Button.setToolTipText("Numeric Pad");
    num8Button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    num8Button.setText("8");

    final Button num9Button = new Button(container, SWT.NONE);
    num9Button.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('9');
      }
    });
    num9Button.setToolTipText("Numeric Pad");
    num9Button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    num9Button.setText("9");

    final Button SubtractButton = new Button(container, SWT.NONE);
    SubtractButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateCalc('-');
      }
    });
    SubtractButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    SubtractButton.setToolTipText("Subtract");
    SubtractButton.setText("-");

    final Button num4Button = new Button(container, SWT.NONE);
    num4Button.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('4');
      }
    });
    num4Button.setToolTipText("Numeric Pad");
    num4Button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    num4Button.setText("4");

    final Button num5Button = new Button(container, SWT.NONE);
    num5Button.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('5');
      }
    });
    num5Button.setToolTipText("Numeric Pad");
    num5Button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    num5Button.setText("5");

    final Button num6Button = new Button(container, SWT.NONE);
    num6Button.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('6');
      }
    });
    num6Button.setToolTipText("Numeric Pad");
    num6Button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    num6Button.setText("6");

    final Button AdditionButton = new Button(container, SWT.NONE);
    AdditionButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateCalc('+');
      }
    });
    AdditionButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    AdditionButton.setToolTipText("Add");
    AdditionButton.setText("+");

    final Button num1Button = new Button(container, SWT.NONE);
    num1Button.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('1');
      }
    });
    num1Button.setCapture(true);
    num1Button.setToolTipText("Numeric Pad");
    num1Button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    num1Button.setText("1");

    final Button num2Button = new Button(container, SWT.NONE);
    num2Button.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('2');
      }
    });
    num2Button.setToolTipText("Numeric Pad");
    num2Button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    num2Button.setText("2");

    final Button num3Button = new Button(container, SWT.NONE);
    num3Button.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('3');
      }
    });
    num3Button.setToolTipText("Numeric Pad");
    num3Button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    num3Button.setText("3");

    final Button equalsButton = new Button(container, SWT.NONE);
    equalsButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateCalc('=');
      }
    });
    equalsButton.setToolTipText("Equals (get result)");
    equalsButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 2));
    equalsButton.setText("=");

    final Button num0Button = new Button(container, SWT.NONE);
    num0Button.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('0');
      }
    });
    num0Button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    num0Button.setToolTipText("Numeric Pad");
    num0Button.setText("0");

    final Button decimalButton = new Button(container, SWT.NONE);
    decimalButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('.');
      }
    });
    decimalButton.setToolTipText("Numeric Pad");
    decimalButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    decimalButton.setText(".");

    final Button signButton = new Button(container, SWT.NONE);
    signButton.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(final SelectionEvent e) {
        updateDisplay('-');
      }
    });
    signButton.setToolTipText("Change sign of value");
    signButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    signButton.setText("+/-");
    new Label(container, SWT.NONE);
    //
    return container;
  }

  /*
   * Create contents of the button bar, including a button to copy the 
   * display to the system clipboard and a close button.
   * @param parent
   */
  @Override
  protected void createButtonsForButtonBar(final Composite parent) {
    createButton(parent, CLIPBOARD_ID, "Copy to Clipboard", false);
    createButton(parent, IDialogConstants.CANCEL_ID, 
        IDialogConstants.CLOSE_LABEL, true);
  }

  /*
   * Set the initial size of the dialog.
   */
  @Override
  protected Point getInitialSize() {
    return new Point(260, 350);
  }

  /*
  *  Standard method to configure the shell.
  */
  protected void configureShell(final Shell newShell) {
    super.configureShell(newShell);
    newShell.setText("Calculator");
    // Include code here to set the window icon.  The line here is a sample using the 
    // Eclipse plugin getImageDescriptor convenience method.
//    newShell.setImage(KomoPlugin.getImageDescriptor(ApplicationImages.CALCULATOR_ICON).createImage());
  }
  
  /*
   *  (non-Javadoc)
   *  Method that copies contents of the display window to the clipboard when 
   *  the Copy to Clipboard button is clicked.
   * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int)
   */
  @Override
  protected void buttonPressed(final int buttonID) {
    if (buttonID == CLIPBOARD_ID) {
      displayText.selectAll();
      displayText.copy();
      displayText.clearSelection();
    } else {
      super.buttonPressed(buttonID);
      
    }
  }

  /*
   * This method updates the display text based on user input.
   */
  private void updateDisplay(final char keyPressed) {
    char keyVal = keyPressed;
    String tempString = new String();
    boolean doClear = false;
    
    if (!clearDisplay) {
      tempString = displayString;
    }
    
    switch (keyVal) {
    case 'B': // Backspace
      if (tempString.length() < 2) {
        tempString = "";
      } else {
        tempString = tempString.substring(0, tempString.length() - 1);
      }
      break;
      
    case 'C': // Clear
      tempString = "0.";
      operatorString = "";
      calcChar = ' ';
      doClear = true;
      break;
      
    case 'D': // Clear Memory
      memoryString = "";
      break;
      
    case 'E': // Clear Entry
      tempString = "0.";
      doClear = true;
      break;
      
    case 'I': // Inverse
      tempString = doCalc(displayString, "", keyVal);
      doClear = true;
      break;
      
    case 'Q': // Square Root
      tempString = doCalc(displayString, "", keyVal);
      doClear = true;
      break;
      
    case 'R': // Recall Memory to Display
      tempString = memoryString;
      doClear = true;
      break;
      
    case '-': // Change Sign
      if (tempString.startsWith("-")) {
        tempString = tempString.substring(1, tempString.length());
      } else {
        tempString = keyVal + tempString;
      }
      break;
    
    case '.': // Can't have two decimal points.
      if (tempString.indexOf(".") == -1 && tempString.length() < 29) {
        tempString = tempString + keyVal;
      }
      break;
      
    case '0': // Don't want 00 to be entered.
      if (!tempString.equals("0") && tempString.length() < 29) {
        tempString = tempString + keyVal;
      }
      break;

    default:  // Default case is for the digits 1 through 9.
      if (tempString.length() < 29) {
        tempString = tempString + keyVal;
      }
      break;
    }
    
    clearDisplay = doClear;
    if (!displayString.equals(tempString)) {
      displayString = tempString;
      displayText.setText(displayString);
    }
  }
  
  /*
   * This method updates the value stored in memory.
   * The value is cleared in the updateDisplay method. 
   */
  private void updateMemory(final char keyPressed) {
    char keyVal = keyPressed;
    String tempString = new String();
    
    switch (keyVal) {
    case 'S': // Save to Memory
      tempString = trimString(displayString);
      break;
      
    case '+': // Add to Memory
      if (memoryString.length() == 0) {
        tempString = trimString(displayString);
      } else {
        tempString = doCalc(memoryString, displayString, '+');
      }
      break;
    
    case '-': // Subtract from Memory
      if (memoryString.length() == 0) {
        if (displayString.startsWith("-")) {
          tempString = displayString.substring(1, displayString.length());
          tempString = trimString(tempString);
        } else if (displayString.equals("0.0") 
          || displayString.equals("0") 
          || displayString.equals("0.")
          || displayString.equals("-0.0")) {
          tempString = "0";
        } else {
          tempString = keyVal + displayString;
          tempString = trimString(displayString);
        }
      } else {
        tempString = doCalc(memoryString, displayString, '-');
      }
      break;
      
    default:  // Do nothing - this should never happen.
      break;
    }
    
    // Do not save invalid entries to memory.
    if (tempString.startsWith(ERROR_STRING)) {
      if (!displayString.equals(tempString)) {
        displayString = tempString;
        displayText.setText(displayString);
      }
    } else {
      memoryString = tempString;
    }
    clearDisplay = true;

  }

  /*
   * This method converts the operator and display strings to double values
   * and performs the calculation.
   */
  private String doCalc(final String valAString, final String valBString, 
      final char opChar) {
    String resultString = ERROR_STRING + NAN_STRING;
    Double valA = 0.0; 
    Double valB = 0.0;
    Double valAnswer = 0.0;
    
    // Make sure register strings are numbers
    if (valAString.length() > 0) {
      try {
        valA = Double.parseDouble(valAString);
      } catch (NumberFormatException e) {
        return resultString;
      }
    } else {
      return resultString;
    }
    
    if (opChar != 'Q' && opChar != 'I') {
      if (valBString.length() > 0) {
        try {
          valB = Double.parseDouble(valBString);
        } catch (NumberFormatException e) {
          return resultString;
        }
      } else {
        return resultString;
      }
    }
    
    switch (opChar) {
    case 'Q': // Square Root
      valAnswer = Math.sqrt(valA);
      break;
      
    case 'I': // Inverse
      valB = 1.0;
      valAnswer = valB/valA;
      break;
      
    case '+': // Addition
      valAnswer = valA + valB;
      break;
      
    case '-': // Subtraction
      valAnswer = valA - valB;
      break;
      
    case '/': // Division
      valAnswer = valA/valB;
      break;
      
    case '*': // Multiplication
      valAnswer = valA*valB;
      break;
      
    default:  // Do nothing - this should never happen
      break;
      
    }

    // Convert answer to string and format it before return.
    resultString = valAnswer.toString();
    resultString = trimString(resultString);
    return resultString;
  }
  
  /*
   * This method updates the operator and display strings, and the 
   * pending calculation flag.
   */
  private void updateCalc(char keyPressed) {
    char keyVal = keyPressed;
    String tempString = displayString;
    
    /*
     * If there is no display value, the keystroke is deemed invalid and 
     * nothing is done.
     */ 
    if (tempString.length() == 0) {
      return;
    }
    
    /* 
     * If there is no operator value, only calculation key presses are 
     * considered valid.  Check that the display value is valid and
     * if so, move the display value to the operator.  No calculation is done.
     */
    if (operatorString.length() == 0) {
      if (keyVal != '=') {
        tempString = trimString(tempString);
        if (tempString.startsWith(ERROR_STRING)) {
          clearDisplay = true;
          operatorString = "";
          calcChar = ' ';
        } else {
          operatorString = tempString;
          calcChar = keyVal;
          clearDisplay = true;
        }
      }
      return;
    }
    
    // There is an operator and a display value, so do the calculation.
    displayString = doCalc(operatorString, tempString, calcChar);
    
    /* 
     * If '=' was pressed or result was invalid, reset pending calculation
     * flag and operator value.  Otherwise, set new calculation flag so 
     * calculations can be chained.
     */ 
    if (keyVal == '=' || displayString.startsWith(ERROR_STRING)) {
      calcChar = ' ';
      operatorString = "";
    } else {
      calcChar = keyVal;
      operatorString = displayString;
    }
    
    // Set the clear display flag and show the result.
    clearDisplay = true;
    displayText.setText(displayString);
  }

  /*
   * This method formats a string.
   */
  private String trimString(final String newString) {
    String tempString = newString;
    
    // Value is not a number
    if (tempString.equals("NaN")) {
      tempString = ERROR_STRING + NAN_STRING;
      return tempString;
    }
    // Value is infinity
    if (tempString.equals("Infinity") || tempString.equals("-Infinity")) {
      tempString = ERROR_STRING + INFINITY_STRING;
      return tempString;
    }
    // Value is -0
    if (tempString.equals(-0.0)) {
      tempString = "0";
      return tempString;
    }
    // Trim unnecessary trailing .0
    if (tempString.endsWith(".0")) {
      tempString = tempString.substring(0, tempString.length() - 2);
    }
    // String is too long to display
    if (tempString.length() > 28) {
      tempString = ERROR_STRING + LONG_STRING;
    }
    
    return tempString;
  }

}


           
       








Related examples in the same category

1.Engine for Calculator by Michael Schmidt