Java/SWT JFace Eclipse/Calculator
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>