All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jidesoft.swing.Calculator Maven / Gradle / Ivy

There is a newer version: 3.6.18
Show newest version
/*
 * @(#)Calculator.java 7/11/2006
 *
 * Copyright 2002 - 2006 JIDE Software Inc. All rights reserved.
 */

package com.jidesoft.swing;

import com.jidesoft.utils.PortingUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;

/**
 * Calculator is a component that can do simple arithmetic calculation. Since it extends JPanel, you can use it
 * at any place in your application.
 * 

* To make it more flexible, the Calculator has no text field to display the result. You can create your own * JTextField or JLabel to display the result. Here is a simple example to create a text field and associate it with * Calculator. *


 * final JTextField textField = new JTextField();
 * textField.setColumns(20);
 * textField.setHorizontalAlignment(JTextField.TRAILING);
 * Calculator calculator = new Calculator();
 * calculator.registerKeyboardActions(textField, JComponent.WHEN_FOCUSED);
 * calculator.addPropertyChangeListener(Calculator.PROPERTY_DISPLAY_TEXT, new PropertyChangeListener() {
 *     public void propertyChange(PropertyChangeEvent evt) {
 *         textField.setText("" + evt.getNewValue());
 *     }
 * });
 * calculator.clear();
 * 
* With the code above, user can type in directly into text field and do the calculation. If you just want to display * the result and don't mind if the text field accepts keyboard input, you don't need to call registerKeyboardActions * method. *

* All numeric and operator keys work as expected. Here are a few special keys that worth mentioning

  • 'C', 'c' * or ESC to clear current result
  • '!' to make current displayed number from positive to negative (or from negative * to positive)
  • ENTER is equivalent to '='..
*

* Another interesting way to use Calculator is to use it without using GUI. *


 * Calculator calculator = new Calculator();
 * calculator.input('1');
 * calculator.input('0');
 * calculator.input('*');
 * calculator.input('2');
 * calculator.input('4');
 * calculator.input('=');
 * System.out.println("10 * 24 = " + calculator.getDisplayText());
 * 
* The print out will be "10 * 24 = 240". *

* There are several methods you can use to get internal state of the Calculator.

  • {@link #getDisplayText()}: * to get the result that should be displayed. Please note, this method return a string.
  • {@link #getResult()}: to * get the last calculated result. This method returns a double value.
  • {@link #getOperator()}: to get the current * operator
  • {@link #isOverflow()}: to check if there is an overflow. Usually if you try to divide by zero, you will * get an overflow.
*/ public class Calculator extends JPanel implements ActionListener { private double _result; private StringBuffer _op1; private StringBuffer _op2; private int _operator = OPERATOR_NONE; private String _displayText; private boolean _overflow = false; private boolean _negationOp1 = true; private boolean _backspaceOp1 = false; private boolean _backspaceOp2 = false; private boolean _clearOperatorPending = false; private boolean _isFakedEqualPressed = false; // When it is true, it means the focus is lost. So the result should not be updated. private boolean _resultCalculated = false; public static final int OPERATOR_NONE = -1; public static final int OPERATOR_ADD = 0; public static final int OPERATOR_MINUS = 1; public static final int OPERATOR_MULTIPLY = 2; public static final int OPERATOR_DIVIDE = 3; private AbstractButton _addButton; private AbstractButton _minusButton; private AbstractButton _multiplyButton; private AbstractButton _divideButton; private AbstractButton _pointButton; private AbstractButton _equalButton; private AbstractButton _backspaceButton; private AbstractButton _clearButton; private AbstractButton _negativeButton; private AbstractButton[] _numberButtons; private char _actualCharPoint; private NumberFormat _displayFormat; public static final char CHAR_CLEAR = 'c'; public static final char CHAR_POINT = '.'; public static final char CHAR_ADD = '+'; public static final char CHAR_MINUS = '-'; public static final char CHAR_MULTIPLY = '*'; public static final char CHAR_DIVIDE = '/'; public static final char CHAR_EQUAL = '='; public static final char CHAR_NEGATIVE = '!'; public static final char CHAR_BACKSPACE = '<'; public static final char CHAR_0 = '0'; public static final char CHAR_1 = '1'; public static final char CHAR_2 = '2'; public static final char CHAR_3 = '3'; public static final char CHAR_4 = '4'; public static final char CHAR_5 = '5'; public static final char CHAR_6 = '6'; public static final char CHAR_7 = '7'; public static final char CHAR_8 = '8'; public static final char CHAR_9 = '9'; public static final String PROPERTY_DISPLAY_TEXT = "displayText"; public static final String PROPERTY_OPERATOR = "operator"; private int _buttonWidth = 24; private int _buttonHeight = 24; private int _buttonGap = 2; /** * Creates a Calculator. */ public Calculator() { _op1 = new StringBuffer(); _op2 = new StringBuffer(); _displayFormat = NumberFormat.getNumberInstance(); configureNumberFormat(); initComponents(); registerKeyboardActions(this, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); } @Override public void setLocale(Locale l) { unregisterKeyboardActions(this); super.setLocale(l); _op1 = new StringBuffer(); _op2 = new StringBuffer(); _displayFormat = NumberFormat.getNumberInstance(getLocale()); configureNumberFormat(); _actualCharPoint = getDisplayFormat().format(2.01).charAt(1); _pointButton.setText("" + _actualCharPoint); registerKeyboardActions(this, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); } /** * Configures the number format for displaying purpose. */ protected void configureNumberFormat() { _displayFormat.setMaximumFractionDigits(20); _displayFormat.setMinimumFractionDigits(0); _displayFormat.setGroupingUsed(false); } /** * Checks if the key event a valid key event that can be accepted by the Calculator. * * @param keyEvent the key event. * @return true if it is a valid key event for the Calculator. */ public static boolean isValidKeyEvent(KeyEvent keyEvent) { char c = keyEvent.getKeyChar(); return (keyEvent.getModifiers() & ~KeyEvent.SHIFT_MASK) != 0 // if it has any modify, ignore it || Character.isDigit(c) || isOperator(keyEvent) || isEnterOrEqual(keyEvent) || c == KeyEvent.VK_PERIOD || c == KeyEvent.VK_COMMA || c == CHAR_CLEAR || Character.toLowerCase(c) == CHAR_CLEAR || c == KeyEvent.VK_ESCAPE || c == KeyEvent.VK_BACK_SPACE; } /** * Checks if the key event a key event for operators. In the other words, if it is {@link #CHAR_ADD}, {@link * #CHAR_MINUS}, {@link #CHAR_MULTIPLY} or {@link #CHAR_DIVIDE}, this method will return true. * * @param keyEvent the key event. * @return true if it is a valid key event is an operator. */ public static boolean isOperator(KeyEvent keyEvent) { char c = keyEvent.getKeyChar(); return c == CHAR_ADD || c == CHAR_MINUS || c == CHAR_MULTIPLY || c == CHAR_DIVIDE; } /** * Checks if the key event a key event for enter. In the other words, if it is {@link KeyEvent#VK_ENTER} or {@link * KeyEvent#VK_EQUALS}, this method will return true. * * @param keyEvent the key event. * @return true if it is a valid key event is an enter key or an equal key. */ public static boolean isEnterOrEqual(KeyEvent keyEvent) { char c = keyEvent.getKeyChar(); return c == KeyEvent.VK_ENTER || c == KeyEvent.VK_EQUALS; } /** * Registers necessary keyboard actions onto the component. Usually the component is a JTextField. * * @param component the component where the key input will be taken and passed to the Calculator. * @param condition the condition as defined in {@link JComponent#registerKeyboardAction(java.awt.event.ActionListener, * javax.swing.KeyStroke, int)}. */ public void registerKeyboardActions(JComponent component, int condition) { boolean isCellEditor = isCellEditor(); component.registerKeyboardAction(this, "" + CHAR_ADD, KeyStroke.getKeyStroke(CHAR_ADD), condition); component.registerKeyboardAction(this, "" + CHAR_MINUS, KeyStroke.getKeyStroke(CHAR_MINUS), condition); component.registerKeyboardAction(this, "" + CHAR_MULTIPLY, KeyStroke.getKeyStroke(CHAR_MULTIPLY), condition); component.registerKeyboardAction(this, "" + CHAR_DIVIDE, KeyStroke.getKeyStroke(CHAR_DIVIDE), condition); component.registerKeyboardAction(this, "" + CHAR_EQUAL, KeyStroke.getKeyStroke(CHAR_EQUAL), condition); if (!isCellEditor) component.registerKeyboardAction(this, "" + CHAR_EQUAL, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), condition); component.registerKeyboardAction(this, "" + CHAR_0, KeyStroke.getKeyStroke(CHAR_0), condition); component.registerKeyboardAction(this, "" + CHAR_1, KeyStroke.getKeyStroke(CHAR_1), condition); component.registerKeyboardAction(this, "" + CHAR_2, KeyStroke.getKeyStroke(CHAR_2), condition); component.registerKeyboardAction(this, "" + CHAR_3, KeyStroke.getKeyStroke(CHAR_3), condition); component.registerKeyboardAction(this, "" + CHAR_4, KeyStroke.getKeyStroke(CHAR_4), condition); component.registerKeyboardAction(this, "" + CHAR_5, KeyStroke.getKeyStroke(CHAR_5), condition); component.registerKeyboardAction(this, "" + CHAR_6, KeyStroke.getKeyStroke(CHAR_6), condition); component.registerKeyboardAction(this, "" + CHAR_7, KeyStroke.getKeyStroke(CHAR_7), condition); component.registerKeyboardAction(this, "" + CHAR_8, KeyStroke.getKeyStroke(CHAR_8), condition); component.registerKeyboardAction(this, "" + CHAR_9, KeyStroke.getKeyStroke(CHAR_9), condition); component.registerKeyboardAction(this, "" + _actualCharPoint, KeyStroke.getKeyStroke(_actualCharPoint), condition); component.registerKeyboardAction(this, "" + CHAR_BACKSPACE, KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), condition); if (!isCellEditor) component.registerKeyboardAction(this, "" + CHAR_CLEAR, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), condition); if (!isCellEditor) component.registerKeyboardAction(this, "" + CHAR_CLEAR, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); component.registerKeyboardAction(this, "" + CHAR_CLEAR, KeyStroke.getKeyStroke(Character.toUpperCase(CHAR_CLEAR)), condition); component.registerKeyboardAction(this, "" + CHAR_CLEAR, KeyStroke.getKeyStroke(Character.toLowerCase(CHAR_CLEAR)), condition); } /** * Unregisters the keyboard actions you registered using {@link #registerKeyboardActions(javax.swing.JComponent, * int)}. * * @param component the component. */ public void unregisterKeyboardActions(JComponent component) { boolean isCellEditor = isCellEditor(); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(CHAR_ADD)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(CHAR_MINUS)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(CHAR_MULTIPLY)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(CHAR_DIVIDE)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(CHAR_EQUAL)); if (!isCellEditor) component.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(CHAR_0)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(CHAR_1)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(CHAR_2)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(CHAR_3)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(CHAR_4)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(CHAR_5)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(CHAR_6)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(CHAR_7)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(CHAR_8)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(CHAR_9)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(_actualCharPoint)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0)); if (!isCellEditor) component.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0)); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(Character.toUpperCase(CHAR_CLEAR))); component.unregisterKeyboardAction(KeyStroke.getKeyStroke(Character.toLowerCase(CHAR_CLEAR))); } protected void initComponents() { setLayout(new CalculatorLayoutManager()); add(_addButton = createButton("+")); add(_minusButton = createButton("-")); add(_multiplyButton = createButton("*")); add(_divideButton = createButton("/")); _numberButtons = new AbstractButton[10]; for (int i = 0; i <= 9; i++) { add(_numberButtons[i] = createButton("" + i)); } _actualCharPoint = getDisplayFormat().format(2.01).charAt(1); add(_pointButton = createButton("" + _actualCharPoint)); add(_equalButton = createButton("=")); add(_backspaceButton = createButton(null, new BackspaceIcon())); add(_negativeButton = createButton(null, new ToggleNegativeIcon())); add(_clearButton = createButton("C")); } /** * Get the flag indicating if the result was calculated at least once. * * @return true if the result was calculated at least once. Otherwise false. */ public boolean isResultCalculated() { return _resultCalculated; } /** * Set the flag indicating if the result was calculated at least once. * * @param resultCalculated the flag */ public void setResultCalculated(boolean resultCalculated) { _resultCalculated = resultCalculated; } class BackspaceIcon implements Icon { public BackspaceIcon() { } public void paintIcon(Component c, Graphics g, int x, int y) { Object save = JideSwingUtilities.setupShapeAntialiasing(g); Color old = g.getColor(); g.setColor(c.getForeground()); g.drawLine(x, y + 3, x + 3, y); g.drawLine(x, y + 3, x + 3, y + 6); g.drawLine(x + 3, y + 3, x + 7, y + 3); g.setColor(old); JideSwingUtilities.restoreShapeAntialiasing(g, save); } public int getIconWidth() { return 7; } public int getIconHeight() { return 7; } } class ToggleNegativeIcon implements Icon { public ToggleNegativeIcon() { } public void paintIcon(Component c, Graphics g, int x, int y) { Color old = g.getColor(); Object save = JideSwingUtilities.setupShapeAntialiasing(g); g.setColor(c.getForeground()); g.drawLine(x, y + 2, x + 6, y + 2); g.drawLine(x, y + 7, x + 6, y + 7); g.drawLine(x + 3, y, x + 3, y + 5); g.setColor(old); JideSwingUtilities.restoreShapeAntialiasing(g, save); } public int getIconWidth() { return 7; } public int getIconHeight() { return 7; } } /** * Creates the button that is used in the Calculator. By default, it will create a JideButton. Here is the code. You * can override it to create your own button. This method is used to create all buttons except the backspace and the * +/- button. So if you want to override it, it's better to override {@link #createButton(String, * javax.swing.Icon)} method. * * @param text the text on the button. * @return the button. */ protected AbstractButton createButton(String text) { return createButton(text, null); } /** * Creates the button that is used in the Calculator. By default, it will create a JideButton. Here is the code. You * can override it to create your own button. *

     * AbstractButton button = new JideButton(text, icon);
     * button.setOpaque(true);
     * button.setContentAreaFilled(true);
     * button.setRequestFocusEnabled(false);
     * button.setFocusable(false);
     * button.addActionListener(this);
     * return button;
     * 
* * @param text the text on the button. * @param icon the icon on the button. * @return the button. */ protected AbstractButton createButton(String text, Icon icon) { AbstractButton button = new JideButton(text, icon); button.setOpaque(true); button.setContentAreaFilled(true); button.setRequestFocusEnabled(false); button.setFocusable(false); button.addActionListener(this); return button; } /** * Checks if the calculator is in overflow state. * * @return true if overflow. */ public boolean isOverflow() { return _overflow; } /** * Sets the overflow flag. * * @param overflow the overflow flag. */ public void setOverflow(boolean overflow) { _overflow = overflow; } /** * Inputs a char to the calculator. Please note, not all chars are acceptable. Valid chars are defined in {@link * Calculator} class as CHAR_XXX constants. * * @param c the char input char. */ public void input(char c) { if (CHAR_CLEAR == Character.toLowerCase(c) || CHAR_CLEAR == Character.toUpperCase(c)) { clear(); return; } if (_overflow) { beep(); return; } if (Character.isDigit(c) || _actualCharPoint == c) { if (_clearOperatorPending) { setOperator(OPERATOR_NONE); _op1.setLength(0); _clearOperatorPending = false; } if (getOperator() == OPERATOR_NONE) { if (_actualCharPoint != c || _op1.indexOf("" + _actualCharPoint) == -1) { _op1.append(c); _backspaceOp1 = true; _backspaceOp2 = false; setDisplayText(_op1.toString()); } else { beep(); } } else { if (_actualCharPoint != c || _op2.indexOf("" + _actualCharPoint) == -1) { _op2.append(c); _backspaceOp2 = true; _backspaceOp1 = false; setDisplayText(_op2.toString()); } else { beep(); } } } else { switch (c) { case CHAR_ADD: operatorPressed(OPERATOR_ADD); break; case CHAR_MINUS: operatorPressed(OPERATOR_MINUS); break; case CHAR_MULTIPLY: operatorPressed(OPERATOR_MULTIPLY); break; case CHAR_DIVIDE: operatorPressed(OPERATOR_DIVIDE); break; case CHAR_EQUAL: calculateResult(true); _clearOperatorPending = true; break; case CHAR_NEGATIVE: if (_negationOp1) { negativePressed(_op1); setDisplayText(_op1.toString()); } else { negativePressed(_op2); setDisplayText(_op2.toString()); } break; case CHAR_BACKSPACE: if (_backspaceOp1) { backspacePressed(_op1); setDisplayText(_op1.toString()); } else if (_backspaceOp2) { backspacePressed(_op2); setDisplayText(_op2.toString()); } else { beep(); } break; } } } private void operatorPressed(int operator) { if (_op1.length() == 0) { // _op1 does not have input yet, make it 0 _op1.append("0"); } else if (getOperator() == OPERATOR_NONE || _clearOperatorPending) { // normal process or just pressed = _op2.setLength(0); calculateResult(false); } else { if (_op2.length() == 0) { // two operators input continuously beep(); return; } else { // enable 3+3+3 _isFakedEqualPressed = false; calculateResult(true); _op1.setLength(0); _op1.append(getDisplayFormat().format((Double) _result)); _op2.setLength(0); } } setOperator(operator); _negationOp1 = false; _clearOperatorPending = false; } protected void beep() { PortingUtils.notifyUser(); } private void negativePressed(StringBuffer buf) { if (buf.length() == 0) { return; } if (buf.charAt(0) == CHAR_MINUS) { buf.deleteCharAt(0); } else { buf.insert(0, CHAR_MINUS); } } private void backspacePressed(StringBuffer buf) { if (buf.length() == 0) { return; } buf.deleteCharAt(buf.length() - 1); } /** * Update the result as if the equal was pressed. This method can be used while Enter key is pressed and you need * keep the calculated result. */ public void updateResult() { _isFakedEqualPressed = false; calculateResult(true); } private void calculateResult(boolean equalPressed) { if (getOperator() == OPERATOR_NONE) { return; } if (_op1.length() == 0) { beep(); return; } if (equalPressed) { if (_op2.length() == 0) { _op2.append(_op1); } } else if (_op2.length() == 0) { return; } Double op1; Double op2; try { op1 = getDisplayFormat().parse(_op1.toString()).doubleValue(); op2 = getDisplayFormat().parse(_op2.toString()).doubleValue(); } catch (ParseException e) { op1 = 0.0; op2 = 0.0; } if (!_isFakedEqualPressed) { try { switch (getOperator()) { case OPERATOR_ADD: _result = op1 + op2; break; case OPERATOR_MINUS: _result = op1 - op2; break; case OPERATOR_MULTIPLY: _result = op1 * op2; break; case OPERATOR_DIVIDE: if (op2 == 0) { _result = Double.NaN; _overflow = true; } else { _result = op1 / op2; } break; } } catch (Exception e) { _overflow = true; } } if (_overflow) { setDisplayText("E"); } else { setResultCalculated(true); _op1.setLength(0); if (_displayFormat != null) { String displayText = _displayFormat.format(_result); setDisplayText(displayText); } else { setDisplayText("" + _result); } _op1.append(getDisplayText()); _negationOp1 = true; _backspaceOp1 = true; _backspaceOp2 = false; } } private void clearOps() { setOperator(OPERATOR_NONE); _op1.setLength(0); _op2.setLength(0); } /** * Clears the internal state and reset the calculator. */ public void clear() { clearOps(); _overflow = false; _clearOperatorPending = false; setDisplayText("0"); } /** * Gets the last calculated result. * * @return the last calculated result. */ public double getResult() { return _result; } /** * Gets the display text. * * @return the display text. */ public String getDisplayText() { return _displayText; } /** * Sets the display text and fire property change event on property named {@link #PROPERTY_DISPLAY_TEXT}. * * @param displayText the displayed text. */ public void setDisplayText(String displayText) { String old = _displayText; _displayText = displayText; firePropertyChange(PROPERTY_DISPLAY_TEXT, old, _displayText); } /** * Gets the current operator. * * @return the current operator. */ public int getOperator() { return _operator; } /** * Sets the operator and fire property change event on property named {@link #PROPERTY_OPERATOR}. * * @param operator the operator. */ public void setOperator(int operator) { int old = _operator; if (old != operator) { _operator = operator; firePropertyChange(PROPERTY_OPERATOR, new Integer(old), new Integer(operator)); } } private class CalculatorLayoutManager implements LayoutManager { public CalculatorLayoutManager() { } public void addLayoutComponent(String name, Component comp) { } public void removeLayoutComponent(Component comp) { } public Dimension preferredLayoutSize(Container parent) { return minimumLayoutSize(parent); } public Dimension minimumLayoutSize(Container parent) { return new Dimension(getButtonWidth() * 4 + getButtonGap() * 3, getButtonHeight() * 5 + getButtonGap() * 4); } public void layoutContainer(Container parent) { int x = 0; int y = 0; int w = getButtonWidth(); int h = getButtonHeight(); int gap = getButtonGap(); _numberButtons[7].setBounds(x, y, w, h); x += w + gap; _numberButtons[8].setBounds(x, y, w, h); x += w + gap; _numberButtons[9].setBounds(x, y, w, h); x += w + gap; _divideButton.setBounds(x, y, w, h); x = 0; y += h + gap; _numberButtons[4].setBounds(x, y, w, h); x += w + gap; _numberButtons[5].setBounds(x, y, w, h); x += w + gap; _numberButtons[6].setBounds(x, y, w, h); x += w + gap; _multiplyButton.setBounds(x, y, w, h); x = 0; y += h + gap; _numberButtons[1].setBounds(x, y, w, h); x += w + gap; _numberButtons[2].setBounds(x, y, w, h); x += w + gap; _numberButtons[3].setBounds(x, y, w, h); x += w + gap; _minusButton.setBounds(x, y, w, h); x = 0; y += h + gap; _numberButtons[0].setBounds(x, y, w, h); x += w + gap; _pointButton.setBounds(x, y, w, h); x += w + gap; _negativeButton.setBounds(x, y, w, h); x += w + gap; _addButton.setBounds(x, y, w, h); x = 0; y += h + gap; _clearButton.setBounds(x, y, w, h); x += w + gap; _backspaceButton.setBounds(x, y, w, h); x += w + gap; _equalButton.setBounds(x, y, w * 2 + gap, h); } } public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (_addButton == source) { input(CHAR_ADD); } else if (_minusButton == source) { input(CHAR_MINUS); } else if (_multiplyButton == source) { input(CHAR_MULTIPLY); } else if (_divideButton == source) { input(CHAR_DIVIDE); } else if (_equalButton == source) { _isFakedEqualPressed = e.getActionCommand() != null && e.getActionCommand().equals("Faked"); input(CHAR_EQUAL); } else if (_pointButton == source) { input(_actualCharPoint); } else if (_negativeButton == source) { input(CHAR_NEGATIVE); } else if (_backspaceButton == source) { input(CHAR_BACKSPACE); } else if (_clearButton == source) { input(CHAR_CLEAR); } else { boolean found = false; for (int i = 0; i <= 9; i++) { if (_numberButtons[i] == source) { input(("" + i).charAt(0)); found = true; break; } } if (!found) { if (e.getActionCommand() != null && e.getActionCommand().length() > 0) { fakePressButton(e.getActionCommand().charAt(0)); } else { fakePressButton(CHAR_EQUAL); } } } } /** * Press the button. By default, we will trigger the action directly on this button. However subclass can override * it to call doClick to mimic the user pressing the button. * * @param button the button */ protected void fakePressButton(AbstractButton button) { actionPerformed(new ActionEvent(button, 0, null)); } private void fakePressButton(char c) { if (c == _actualCharPoint) { fakePressButton(_pointButton); return; } switch (c) { case CHAR_CLEAR: fakePressButton(_clearButton); break; case CHAR_BACKSPACE: fakePressButton(_backspaceButton); break; case CHAR_EQUAL: fakePressButton(_equalButton); break; case CHAR_NEGATIVE: fakePressButton(_negativeButton); break; case CHAR_ADD: fakePressButton(_addButton); break; case CHAR_MINUS: fakePressButton(_minusButton); break; case CHAR_MULTIPLY: fakePressButton(_multiplyButton); break; case CHAR_DIVIDE: fakePressButton(_divideButton); break; case CHAR_0: fakePressButton(_numberButtons[0]); break; case CHAR_1: fakePressButton(_numberButtons[1]); break; case CHAR_2: fakePressButton(_numberButtons[2]); break; case CHAR_3: fakePressButton(_numberButtons[3]); break; case CHAR_4: fakePressButton(_numberButtons[4]); break; case CHAR_5: fakePressButton(_numberButtons[5]); break; case CHAR_6: fakePressButton(_numberButtons[6]); break; case CHAR_7: fakePressButton(_numberButtons[7]); break; case CHAR_8: fakePressButton(_numberButtons[8]); break; case CHAR_9: fakePressButton(_numberButtons[9]); break; } } /** * Gets the display format for the number. * * @return the display format for the number. */ public NumberFormat getDisplayFormat() { return _displayFormat; } /** * Sets the display format for the number. * * @param displayFormat the display format. */ public void setDisplayFormat(NumberFormat displayFormat) { _displayFormat = displayFormat; } /** * Calculates the pending calculation. If the Calculator has both operations and a valid operator, this method will * do the calculation and set the display text and result. */ public void commit() { if (!_clearOperatorPending) { actionPerformed(new ActionEvent(_equalButton, 0, "Faked")); } } /** * Gets the button width. * * @return the button width. */ public int getButtonWidth() { return _buttonWidth; } /** * Sets the button width. * * @param buttonWidth the new button width. */ public void setButtonWidth(int buttonWidth) { _buttonWidth = buttonWidth; } /** * Gets the button height. * * @return the button height. */ public int getButtonHeight() { return _buttonHeight; } /** * Sets the button height. * * @param buttonHeight the new button height. */ public void setButtonHeight(int buttonHeight) { _buttonHeight = buttonHeight; } /** * Gets the gap between buttons. Default is 2. * * @return the gap between buttons. */ public int getButtonGap() { return _buttonGap; } public void setButtonGap(int buttonGap) { _buttonGap = buttonGap; } /** * If this method return true, ENTER and ESCAPE key will be registered. Otherwise they will not be. The reason we do * so because the two keys are conflicted with keys in JTable. * * @return true or false. */ protected boolean isCellEditor() { return false; } public void setInitialValue(String value) { _op1.setLength(0); _op1.append(value); _backspaceOp1 = true; _backspaceOp2 = false; setDisplayText(_op1.toString()); } public static void main(String[] args) { Calculator calculator = new Calculator(); calculator.input('1'); calculator.input('0'); calculator.input('*'); calculator.input('2'); calculator.input('4'); calculator.input('='); // System.out.println("10 * 24 = " + calculator.getDisplayText()); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy