Java tutorial
/** * 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; } }