Ali Onur Cinar
Articles

eCalc Java Calculator

eCalc snapshot

Click to download eCalc.java.

/**
 * eCalc.java: An Abstract Java Based Calculator
 *
 * Copyright (c) 2000
 *    Ali Onur Cinar &060;cinar&064;zdo.com&062;
 *
 * License:
 *
 *   Permission  to  use,  copy, modify, and  distribute  this software and its
 *   documentation   for  educational   purposes  and  without  fee  is  hereby
 *   granted,  provided  that the  above  copyright notice appear in all copies
 *   and  that both  the  copyright  notice  and  this  permission  notice  and
 *   warranty  disclaimer appear in supporting documentation, and that the name
 *   of Ali Onur Cinar not be  used  in  advertising or publicity pertaining to
 *   distribution of the software without specific, written prior permission.
 *
 * To Compile:
 *
 *   $ javac eCalc.java
 *
 * To Run:
 *
 *   $ java eCalc
 *
 * @author     A. Onur Cinar &060;cinar&064;zdo.com&062;
 * @version    %W% %G% 
 * @version    $Id: eCalc.java,v 1.1 2004/08/17 21:31:25 cinar Exp $
 * @since      1.0
 */

import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;

public class eCalc
{
  /**
   * Internal keypad action listener class
   */
  public static class KeypadListener implements ActionListener
  {
    public void actionPerformed (ActionEvent e)
    {
      actionHandler(e.getActionCommand());
    }
  }

  /**
   * Internal memory keypad action listener class
   */
  public static class MemoryListener implements ActionListener
  {
    public void actionPerformed (ActionEvent e) 
    {
      String command = e.getActionCommand();          // get action command 

      int index = memoryl.getSelectedIndex();         // get mem list index

      if (index == -1)                                // return if empty 
        return;

      if ("Cut".equals(command))                      // cut
      {                 
        memory.removeElementAt(index);
      }
      else if ("Copy".equals(command))                // copy
      {
        display.setText((String) memory.getElementAt(index));
      }
      else if ("Clear".equals(command))               // clear
      {
        memory.clear();
      }
    }
  }

  /**
   * Internal keyboard listener class
   */
  public static class KeyboardListener implements KeyListener 
  {
    public void keyTyped (KeyEvent e) 
    {
      actionHandler(String.valueOf(e.getKeyChar()));
    }

    public void keyPressed (KeyEvent e) { }
    public void keyReleased (KeyEvent e) { }
  }

  /**
   * Internal list cell rendered class
   */
  public static class MemoryRenderer extends JLabel
   implements ListCellRenderer 
  {
    public Component getListCellRendererComponent (
     JList list, Object value, int index,
     boolean isSelected, boolean callHasFocus) 
    {
      String str = value.toString();

      // remove decimal part if not needed
      if (str.length() > 2
        && str.substring(str.length()-2).equals(".0"))
      {
        str = str.substring(0,str.length()-2);
      }

      setText(str);
      setHorizontalAlignment(RIGHT);
      setEnabled(list.isEnabled());
      setFont(list.getFont());
      setOpaque(true);

      if (isSelected) 
      {
        setBackground(list.getSelectionBackground());
        setForeground(list.getSelectionForeground());
      } 
      else 
      {
        setBackground(list.getBackground());
        setForeground(list.getForeground());
      }

      return this;
    }
  }

  /**
   * eCalc: constructor
   */
  public eCalc() 
  {
    init();
  }

  /**
   * init: initialize the GUI
   */
  protected static void init () 
  {
    JFrame frame = new JFrame("eCalc");

    frame.addWindowListener(new WindowAdapter () {
      public void windowClosing (WindowEvent e) { System.exit(0); }
    });

    frame.addKeyListener(new KeyboardListener());

    JPanel mpane = new JPanel();
    mpane.setBorder(BorderFactory.createEmptyBorder(4,4,4,4));
    frame.getContentPane().add(mpane,BorderLayout.CENTER);

    GridBagLayout gb = new GridBagLayout();
    GridBagConstraints gc = new GridBagConstraints();
    mpane.setLayout(gb);
    gc.weightx=0.0; gc.weighty=0.0;
    gc.anchor=GridBagConstraints.NORTH;
    gc.fill=GridBagConstraints.BOTH;

    JPanel p = initMemory();
    gc.gridx=0; gc.gridy=0; gc.gridwidth=2; gc.weightx=1.0;
    gb.setConstraints(p, gc);
    mpane.add(p);

    // add register pad
    JComponent r = initRegisterpad();
    gc.gridx=0; gc.gridy=1; 
    gc.gridwidth=1; gc.gridheight=2; gc.weightx=0.0;
    gb.setConstraints(r, gc);
    mpane.add(r);

    // add display
    JComponent c = initDisplay();
    gc.gridx=1; gc.gridy=1; 
    gc.gridwidth=1; gc.gridheight=1; gc.weightx=1.0;
    gb.setConstraints(c, gc);
    mpane.add(c);

    // add keypad to main pane
    p = initKeypads();
    gc.gridx=1; gc.gridy=2;
    gc.gridwidth=2; gc.weightx=1.0;
    gb.setConstraints(p, gc);
    mpane.add(p);

    frame.pack();
    frame.setVisible(true);
  }

  /**
   * initDisplay: initialize display
   * @return display as JComponent
   */
  protected static JComponent initDisplay() 
  {
    display = new JLabel("0",JLabel.RIGHT);
    display.setOpaque(true);
    display.setBackground(new Color(0xffffcc));
    display.setForeground(Color.black);
    display.setFont(new Font("Helvetica", Font.BOLD, 14));
    display.setBorder(new BevelBorder(BevelBorder.LOWERED));
   
    return display;
  }

  /**
   * initMemory: initialize memory pane
   * @return memory pane as JPanel
   */
  protected static JPanel initMemory() 
  {
    JPanel mpane = new JPanel();
    mpane.setBorder(BorderFactory.createEmptyBorder(0,0,2,0));

    MemoryListener mlistener = new MemoryListener();

    GridBagLayout gb = new GridBagLayout();
    GridBagConstraints gc = new GridBagConstraints();
    gc.weightx=1.0; gc.weighty=1.0;
    gc.anchor=GridBagConstraints.NORTH;
    gc.fill=GridBagConstraints.BOTH;
    mpane.setLayout(gb);

    // add the list
    memoryl = new JList(memory);
    memoryl.setVisibleRowCount(2);
    memoryl.setBackground(new Color(0xffffcc));
    memoryl.setForeground(Color.black);
    memoryl.setCellRenderer(new MemoryRenderer()); // set cell renderer
    JScrollPane memoryp = new JScrollPane(memoryl, 
     JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
     JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    gc.gridx=0; gc.gridy=0; gc.gridheight=3;
    gb.setConstraints(memoryp, gc);
    mpane.add(memoryp);

    // add 'clear' button
    gc.weightx=0.0;
    JButton b = new JButton("Clear");
    b.setOpaque(true);
    b.setMargin(BUTTON_MARGIN);
    b.setPreferredSize(LBUTTON_SIZE);
    b.addActionListener(mlistener);
    gc.gridx=1; gc.gridy=0; gc.gridheight=1;
    gb.setConstraints(b, gc);
    mpane.add(b);

    // add 'remove' button
    b = new JButton("Cut");
    b.setOpaque(true);
    b.setMargin(BUTTON_MARGIN);
    b.setPreferredSize(LBUTTON_SIZE);
    b.addActionListener(mlistener);
    gc.gridx=1; gc.gridy=1;
    gb.setConstraints(b, gc);
    mpane.add(b);

    // add 'copy' button
    b = new JButton("Copy");
    b.setOpaque(true);
    b.setMargin(BUTTON_MARGIN);
    b.setPreferredSize(LBUTTON_SIZE);
    b.addActionListener(mlistener);
    gc.gridx=1; gc.gridy=2;
    gb.setConstraints(b, gc);
    mpane.add(b);

    // return pane
    return mpane; 
  }

  /**
   * addKeys: add keys to given panel
   * @param panel as JPanel
   * @param list of keys as String[]
   */
  protected static void addKeys (JPanel panel, String[] keys) 
  {
    // add add keys to panel
    for (int i=0; i<keys.length; i++) 
    {
      JButton b = new JButton(keys[i]);
      b.setOpaque(true);
      b.setPreferredSize(BUTTON_SIZE);
      b.setMargin(BUTTON_MARGIN);
      b.addActionListener(alistener);
      panel.add(b);
    }
  }

  /**
   * initRegisterpad: initialize register pad
   * @return register pad as JPanel
   */
  protected static JPanel initRegisterpad () 
  {
    JPanel keypad = new JPanel();
    keypad.setBorder(new EtchedBorder());

    GridBagLayout gb = new GridBagLayout();
    GridBagConstraints gc = new GridBagConstraints();
    gc.weightx=0.0; gc.weighty=0.0;
    gc.anchor=GridBagConstraints.NORTH;
    gc.fill=GridBagConstraints.BOTH;
    keypad.setLayout(gb);

    rdisp = new JLabel("0",JLabel.RIGHT);
    rdisp.setOpaque(true);
    rdisp.setBackground(Color.lightGray);
    rdisp.setForeground(Color.black);
    rdisp.setFont(new Font("Helvetica", Font.BOLD, 14));
    rdisp.setBorder(new BevelBorder(BevelBorder.LOWERED));
    rdisp.setPreferredSize(BUTTON_SIZE);
    gc.gridx=0; gc.gridy=0;
    gb.setConstraints(rdisp, gc);
    keypad.add(rdisp);

    // keypad components
    String[] keypadcomp = 
    {
      "MC","MR","MS","M+"
    };

    // add keypad components
    JPanel keypad1 = new JPanel();
    keypad1.setBorder(BorderFactory.createEmptyBorder(4,4,4,4));
    keypad1.setLayout(new GridLayout(4,1));
    addKeys(keypad1,keypadcomp);
    gc.gridx=0; gc.gridy=1;
    gb.setConstraints(keypad1, gc);
    keypad.add(keypad1);

    // return 
    return keypad;
  }

  /**
   * initKeypads: initialize keypads
   * @return keypad object as JPanel
   */
  protected static JPanel initKeypads () 
  {
    // define the keypad 1
    JPanel keypad1 = new JPanel();
    keypad1.setBorder(BorderFactory.createEmptyBorder(4,4,4,4));
    keypad1.setLayout(new GridLayout(4,5));
   
    // keypad1 components
    String[] keypad1comp = 
    {
      "7","8","9","/","C",
      "4","5","6","*","CE",
      "1","2","3","-","DEL",
      "0","+/-",".","+","="
    };

    // add keypad1 components
    addKeys(keypad1,keypad1comp);
 
    // define the keypad 3
    JPanel keypad3 = new JPanel();
    keypad3.setBorder(BorderFactory.createEmptyBorder(4,4,4,4));
    keypad3.setLayout(new GridLayout(4,1));

    // keypad3 components
    String[] keypad3comp = { 
     "sin","cos","tan","Pi"
    };

    // add keypad3 components
    addKeys(keypad3,keypad3comp);

    // define the keypad 4
    JPanel keypad4 = new JPanel();
    keypad4.setBorder(BorderFactory.createEmptyBorder(4,4,4,4));
    keypad4.setLayout(new GridLayout(4,1));

    // keypad4 components
    String[] keypad4comp = { 
     "1/x","x^2","n!","sqrt"
    };

    // add keypad4 components
    addKeys(keypad4,keypad4comp);

    // create big keypad box
    JPanel keypad = new JPanel();
    keypad.setLayout(new BoxLayout(keypad, BoxLayout.X_AXIS));
    keypad.add(Box.createRigidArea (new Dimension (10,10)));
    keypad.add(keypad4);
    keypad.add(keypad3);
    keypad.add(Box.createRigidArea (new Dimension (10,10)));
    keypad.add(keypad1);

    // return the keypad
    return keypad;
  }

  /**
   * updateDisplay: updates and formats the display
   */
  protected static void updateDisplay (double d) 
  {
    // first convert to integer
    int i = new Double(d).intValue();

    // check to see if we realy need the decimal
    // part or not
    if (d > i)
    {
      display.setText(Double.toString(d));
    }
    else
    {
      display.setText(Integer.toString(i));
    }
  }

  /**
   * actionHandler: action handler
   * @param command as String
   */
  protected static void calc () 
  {
    // current display's value 
    double dval = Double.valueOf(display.getText()).doubleValue();

    // if operation is '='
    if (operator == '=') 
    {
      // simply copy display to total
      total = dval;
    }
    else if (operator == '/')                         // divide total
    {
      total = total / dval;
    }
    else if (operator == '*')                         // multiply total
    {
      total = total * dval;
    }
    else if (operator == '-')                         // substract total
    {
      total = total - dval;
    }
    else if (operator == '+')                         // add total
    {
      total = total + dval;
    }

    // update the display with
    // total's value
    updateDisplay(total);

    // don't need to keep display
    keep_display=false;

    // add total to memory list
    // if operator is not =
    if (operator != '=') 
    {
      memory.addElement(Double.toString(total));

      // make it visible
      memoryl.ensureIndexIsVisible(memory.size()-1);
    }

    // set operator to = to avoid
    // multiple presses
    operator = '=';
  }
 
  /**
   * actionHandler: action handler
   * @param command as String
   */
  protected static void actionHandler (String command) 
  {
    // current display's value (may be needed)
    double dval = Double.valueOf(display.getText()).doubleValue();

    // check for operations
    if ("sin".equals(command))                        // sin
    {
      // convert display to radian
      double d = dval * (Math.PI/180);

      // set display to sin(display)
      updateDisplay(Math.sin(d));

      // don't need to keep display
      keep_display=false;
    } 
    else if ("cos".equals(command))                   // cos
    {
      // convert display to radian
      double d = dval * (Math.PI/180);

      // set display to cos(display)
      updateDisplay(Math.cos(d));

      // don't need to keep display
      keep_display=false;
    }
    else if ("tan".equals(command))                   // tan
    {
      // convert display to radian
      double d = dval * (Math.PI/180);

      // set display to tan(display)
      updateDisplay(Math.tan(d));

      // don't need to keep display
      keep_display=false;
    }
    else if ("Pi".equals(command))                    // Pi
    {
      // set display to Pi
      display.setText(Double.toString(Math.PI));

      // don't need to keep display
      keep_display=false;
    }
    else if ("MC".equals(command)) 
    {
      // clean the register
      rdisp.setText(register = "0");
    }
    else if ("MR".equals(command))                    // MC
    {
      // restore register to display
      display.setText(register);

      // don't need to keep display
      keep_display=false;
    }
    else if ("MS".equals(command))                    // MS
    {
      // store the display in register
      rdisp.setText(register = display.getText());

      // don't need to keep display
      keep_display=false;
    }
    else if ("M+".equals(command))                    // M+
    {
      // if register is empty
      // then just return back
      if ("0".equals(register))
        return;

      // first calculate previous
      calc();

      // restore register to display
      display.setText(register);

      // set operator to +
      operator = '+';

      // calculate again
      calc();
    }
    else if ("+/-".equals(command))                   // +/-
    {
      // set display to its inverse
      updateDisplay(dval * -1.0);

      // don't need to keep display
      keep_display=false;
    }
    else if ("/".equals(command)                      // /
          || "*".equals(command)                      // *
          || "-".equals(command)                      // -
          || "+".equals(command)                      // +
          || "=".equals(command))                     // =
    {
      // calculate previous operation
      calc();

      // set new operator
      operator = command.charAt(0);

    } 
    else if ("1/x".equals(command))                   // 1/x
    { 
      // set display to 1/(display)
      updateDisplay(1/dval);

      // don't need to keep display
      keep_display=false;
    }
    else if ("x^2".equals(command))                   // x^2
    {
      // set display to (display)^2
      updateDisplay(dval*dval);

      // don't need to keep display
      keep_display=false;
    }
    else if ("n!".equals(command))                    // n!
    {
      // set display to (display)!
      updateDisplay(dval*(dval+1)/2);

      // don't need to keep display
      keep_display=false;
    }
    else if ("sqrt".equals(command))                  // sqrt
    {
      // set display to sqrt(display)
      updateDisplay(Math.sqrt(dval));

      // don't need to keep display
      keep_display=false;

    }
    else if ("C".equals(command))                     // C
    {
      // clear only display
      display.setText("0");

    }
    else if ("CE".equals(command))                    // CE
    { 
      // clear everything
      display.setText("0");
      rdisp.setText(register="0");

      // clear the memory
      memory.clear();
    }
    else if ("DEL".equals(command))                   // DEL
    {
      // delete the last number
      String str = display.getText();

      // if there is only 1 number then
      // set display to 0
      str = (str.length() == 1) ? 
       "0" : str.substring(0,str.length()-1);

      // set the display  
      display.setText(str);
    }
    else if (command.charAt(0) >= 46
     && command.charAt(0) <= 57) 
    {
      String str = display.getText();

      // can't write multiple 0s such as 0000
      if ("0".equals(command) && "0".equals(str)) 
      {
        return;
      }

      // can't write multiple .s such as 0.00.0
      if (".".equals(command) && str.indexOf('.') > -1) 
      {
       return;
      }

      // otherwise add the number
      // if it is the first number, or we don't need
      // to keep the display, then remove the 0
      // and add it, else concat it to existing display
      str = ("0".equals(str) || !keep_display) 
       ? command : str.concat(command);

      // if display is just . then make it 0.
      if (".".equals(str))
      {
        str = "0.";
      }

      // keep the display
      keep_display=true;

      // set the diplay
      display.setText(str);
    }
  }

  /**
   * main: main entance point
   * @param any arguments
   */
  public static void main (String[] args) 
  {
    new eCalc();
  }

  /** class constants */
  protected static final Dimension BUTTON_SIZE = new Dimension(40,20);
  protected static final Dimension LBUTTON_SIZE = new Dimension(40,15);
  protected static final Insets BUTTON_MARGIN = new Insets(2,2,2,2);
  protected static final DefaultListModel memory = new DefaultListModel();
  protected static ActionListener alistener = new KeypadListener();

  /** class data */
  protected static JLabel display;
  protected static JLabel rdisp;
  protected static JList memoryl;
  protected static boolean keep_display = true;
  protected static String register = new String("0");
  protected static char operator = '=';
  protected static double total = 0.0;
}


Your Comments


12/31/69 17:00

Name:
Comment:

Valid XHTML 1.0! Valid CSS! FuseBox Inside This is my Google PageRank. - SmE Rank free service Powered by Scriptme

This page was last updated on Sun January 21 2007 06:54:54 PM