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