Java/SWT JFace Eclipse/Calculator

Материал из Java эксперт
Перейти к: навигация, поиск

Calculator by Michael Schmidt

   <source lang="java">

/**

* 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.ruposite; 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;
 }

}


      </source>
   
  
 
  



Engine for Calculator by Michael Schmidt

   <source lang="java">

/**

 The following code is from Michael Schmidt(MichaelMSchmidt (at) msn.ru).
 
 The code is published under BSD license.
 
 Thanks for the input from Michael Schmidt.
  • /

package us.mschmidt.komo; /**

* This is a generic calculator engine that includes a memory register, some
* numeric conversions (square root, inverse), and the ability to chain 
* calculations.  To use it, create a GUI shell with a display and some means 
* of entering keystrokes (Buttons work well).  Invoke this engine from the GUI
* shell using the constructor method, which requires that the display size 
* (String length) be set.  Obtain the initial display, if desired, with the 
* getDisplayString() method.  Subsequently, the display string is returned by 
* the setInput() method when an operation (character) is passed to the engine.
*

* The constructor requires a display size to be set. The minimum is three * characters, with at least 22 characters recommended and recommended size * being 30 characters. * * @author Michael Schmidt * @version 1.1 */ class CalcEngine { // Instantiatee constants private final String calcChars; private final String convChars; private final String dispChars; private final String memChars; private final String errChars; // Instantiate variables // The error messages private String nanErr = new String(); private String tooLongErr = new String(); private String infinityErr = new String(); private int displaySize; // The calculator "registers" private String displayString = new String(); private String memoryString = new String(); private String operatorString = new String(); // A boolean to indicate if display will be cleared on the next key entry private boolean clearDisplay; // A character to store the pending calculation private char calcChar; /** * Constructor to create the calculator engine object. * * @param displaySizeVal The GUI display size, minimum of 3 and * recommended size of 30 */ CalcEngine(final int displaySizeVal) { final int minSize = 3; // Initialize operation characters calcChars = "+-/*="; convChars = "IQ"; dispChars = "BCERS.0123456789"; memChars = "DLMP"; errChars = "EINO*"; // Set initial display and internal variables displayString = "0."; clearDisplay = true; calcChar = " "; // Set the display size displaySize = minSize; if (displaySizeVal > minSize) { displaySize = displaySizeVal; } // Customize the error strings based on the display size setErrorStrings(); } /** * Customizes the error messages based on the display size. */ private void setErrorStrings() { // Initialize constants for display size thresholds final int infLength = 8; final int nanLength = 12; final int tooLongLength = 15; final int fullLength = 22; // Set default strings for optimal display size nanErr = "Not a Number"; tooLongErr = "Number too long"; infinityErr = "Infinity"; if (displaySize < infLength) { nanErr = "NaN"; tooLongErr = "***"; infinityErr = "Inf"; } else if (displaySize < nanLength) { nanErr = "NaN"; tooLongErr = "Overflow"; } else if (displaySize < tooLongLength) { tooLongErr = "Overflow"; } else if (displaySize >= fullLength) { nanErr = "ERROR: " + nanErr; tooLongErr = "ERROR: " + tooLongErr; infinityErr = "ERROR: " + infinityErr; } } /** * Provides the display string to the calling class. Used after the * engine is instantiated. Subsequently, the display string is returned by * the setInput() method. * * @return the display String */ public String getDisplayString() { return displayString; } /** * Allows entry of keystrokes from the calling class. * * @param keyVal A designation of the key pressed by the user using the * code. * Display codes: B backspace, C clear, E clear entry, * R recall memory to display, S change sign, . decimal, * 0-9 numeric entries. * Memory codes: D clear memory, M subtract from memory, * L store in memory, P add to memory. * Calculate codes: I inverse, Q square root, S subtract. * @return boolean true if the display has changed, false if not */ public String setInput(final char keyVal) { final char keyChar = keyVal; if (dispChars.indexOf(keyChar) != -1) { doDisplayOp(keyChar); } else if (convChars.indexOf(keyChar) != -1) { doConvertOp(keyChar); } else if (memChars.indexOf(keyChar) != -1) { doMemoryOp(keyChar); } else if (calcChars.indexOf(keyChar) != -1) { doCalcOp(keyChar); } return displayString; } /** * Clears the display when 1) the clearDisplay flag had previously been set * to "true" and 2) a new character or calculation operation is entered. */ private void doDisplayClear() { if (clearDisplay) { displayString = ""; clearDisplay = false; } } /** * Performs number conversion operations: inverse (1/X) and square root. * * @param keyVal a designation of the key pressed by the user */ private void doConvertOp(final char keyVal) { final char opChar = keyVal; String tempString = doConvert(displayString, opChar); clearDisplay = true; if (tempString.length() > 0) { displayString = tempString; } } /** * Performs display operations. Simple assignment operations are performed * in this method while more complex operations are performed in sub-methods. * * @param keyVal a designation of which key was pressed by the user */ private void doDisplayOp(final char keyVal) { final char opChar = keyVal; switch (opChar) { case "B": // Backspace doBackspace(); break; case "C": // Clear. Note use of dropthrough operatorString = ""; calcChar = " "; case "E": // Clear Entry displayString = "0."; clearDisplay = true; break; case "R": // Recall Memory to Display displayString = memoryString; break; case "S": // Change Sign doChangeSign(); break; case ".": // Can"t have two decimal points. doDecimal(opChar); break; case "0": // Don"t want 00 to be entered. doZero(opChar); break; default: // Default case is for the digits 1 through 9. doAddChar(opChar); break; } } /** * Performs backspace operation. */ private void doBackspace() { if (isError(displayString)) { return; } if (displayString.length() > 0) { displayString = displayString.substring( 0, displayString.length() - 1); } } /** * Performs operation to add a character to the display. * * @param c the character to add */ private void doAddChar(final char c) { if (isError(displayString)) { return; } if (displayString.length() < displaySize) { doDisplayClear(); displayString += c; } } /** * Performs sign change operation. */ private void doChangeSign() { if (isError(displayString)) { return; } if ("-" == displayString.charAt(0)) { displayString = displayString.substring( 1, displayString.length()); } else if (displayString.length() < displaySize) { displayString = "-" + displayString; } } /** * Performs operation when decimal is pressed. * * @param c the decimal character */ private void doDecimal(final char c) { if (isError(displayString)) { return; } if (displayString.indexOf(".") == -1 && displayString.length() < displaySize) { doDisplayClear(); displayString += c; } } /** * Performs operation when "0" is pressed. * * @param c the zero operation character */ private void doZero(final char c) { if (isError(displayString)) { return; } if (!displayString.equals("0") && displayString.length() < displaySize) { doDisplayClear(); displayString += c; } } /** * Updates the value stored in the memory register. Simple assignment * operations are performed here while more complex operations are performed * in sub-methods. * * @param keyVal a designation of which key was pressed by the user */ private void doMemoryOp(final char keyVal) { final char opChar = keyVal; switch (opChar) { case "D": // Clear Memory memoryString = ""; break; case "L": // Save to Memory assignMemoryString(trimString(displayString)); break; case "M": // Subtract from Memory subtractFromMemory(); break; case "P": // Add to Memory addToMemory(); break; default: // Do nothing - this should never happen. break; } clearDisplay = true; } /** * Performs the operation to add a display entry to the number in the * memory register. */ private void addToMemory() { String tempString = new String(); if (0 == memoryString.length()) { tempString = trimString(displayString); } else { tempString = doComputation(memoryString, displayString, "+"); } assignMemoryString(tempString); } /** * Performs the operation to subtract a display entry from the number in the * memory register. */ private void subtractFromMemory() { String tempString = new String(); if (0 == memoryString.length()) { tempString = doComputation("0", displayString, "-"); } else { tempString = doComputation(memoryString, displayString, "-"); } assignMemoryString(tempString); } /** * Checks if String is valid and, if so, assigns it to the memory register. * * @param s the String to assign */ private void assignMemoryString(final String s) { if (isError(s)) { displayString = s; } else { memoryString = s; } } /** * Guides 2-number calculations. Updates the operator string, display * string, and the pending calculation flag. Performs calculation if * possible. * * @param keyVal a designation of which key was pressed byt he user */ private void doCalcOp(final char keyVal) { final char opChar = keyVal; // If there is no display value, the keystroke is deemed invalid and // nothing is done. if (0 == displayString.length()) { return; } // If there is no operator value, "=" key presses are considered // invalid. If a calculation key is pressed, check that the display // value is valid and if so, copy the display value to the operator. // No calculation is done. if (0 == operatorString.length()) { if ("=" != opChar) { if (isError(displayString)) { calcChar = " "; } else { operatorString = displayString; calcChar = opChar; } clearDisplay = true; } return; } // There are operator and display values, so do the pending calculation. displayString = doComputation(operatorString, displayString, 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 (("=" == opChar) || isError(displayString)) { calcChar = " "; operatorString = ""; } else { calcChar = opChar; operatorString = displayString; } // Set the clear display flag clearDisplay = true; } /** * Performs the computations. * * @param numStringA the displayed value * @param numStringB the stored value * @param opVal the operation to be performed * @return the solution as a string variable */ private String doComputation(final String numStringA, final String numStringB, final char opVal) { String valStringA = numStringA; String valStringB = numStringB; char opChar = opVal; Double valA = 0.0; Double valB = 0.0; Double valAnswer = 0.0; // Make sure register strings are numbers if (valStringA.length() > 0 && valStringB.length() > 0) { try { valA = Double.parseDouble(numStringA); valB = Double.parseDouble(numStringB); } catch (final NumberFormatException e) { return nanErr; } } else { return ""; } switch (opChar) { 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 properly formatted string. return trimString(valAnswer.toString()); } /** * Performs number conversion computations. * * @param numString the number to be converted * @param opVal designation of the operation to be performed * @return the converted value */ private String doConvert(final String numString, final char opVal) { char opChar = opVal; String valString = numString; Double valA = 0.0; Double valAnswer = 0.0; // Make sure String is a number. If it is zero-length, assume the // keystroke was inadvertent and return "". if (valString.length() > 0) { try { valA = Double.parseDouble(valString); } catch (final NumberFormatException e) { return nanErr; } } else { return ""; } switch (opChar) { case "Q": // Square Root valAnswer = Math.sqrt(valA); break; case "I": // Inverse valAnswer = 1.0 / valA; break; default: // Do nothing - this should never happen break; } // Return properly formatted result String. return trimString(valAnswer.toString()); } /** * Formats String to be displayed. * * @param stringVal a new string to be displayed * @return the properly formatted and trimmed string */ private String trimString(final String stringVal) { String returnString = stringVal; // Check if value is Not a Number if (returnString.equals("NaN")) { return nanErr; } // Check if value is infinity if (returnString.endsWith("Infinity")) { return infinityErr; } // Check if value is -0 if (returnString.equals("-0.0")) { return "0"; } // Trim unnecessary trailing .0 if (returnString.endsWith(".0")) { returnString = returnString.substring(0, returnString.length() - 2); } // Check if string is too long to display if (returnString.length() > displaySize) { return tooLongErr; } return returnString; } /** * Tests if the String is an error message. * * @param s the String to be tested * @return boolean true if this is an error message, false if not */ private boolean isError(final String s) { String testString = s; if (0 == testString.length()) { return false; } char c = testString.charAt(0); return ((errChars.indexOf(c) == -1)) ? false : true; } /** * Override to provide useful information when the class toString method is * called. * * @return the information String * @see java.lang.Object#toString() */ @Override public final String toString() { return "komo.CalcEngine is the engine portion of the calculator utility"; } } </source>