/** * Created : Mar 27, 2012 * * @author pquiring */ import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import javaforce.*; public class Backend implements KeyEventDispatcher { public Display display; public ArrayList<String> formula = new ArrayList<String>(); public int radix = 10; public int fidx = 0; //formula index public int mode = 0; //0=Basic 1=Scientific 2=Programmer public boolean inDialog = false; private boolean error = false; private boolean deg = true; //degrees (else radians) public Backend() { KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this); } private boolean isNumber(int idx) { return formula.get(idx).startsWith("#"); } private boolean isOperation(int idx) { char ch = formula.get(idx).charAt(0); if (ch == '#') return false; if (ch == '(') return false; if (ch == ')') return false; return true; } private boolean isOpen(int idx) { return formula.get(idx).charAt(0) == '('; } private boolean isClose(int idx) { return formula.get(idx).charAt(0) == ')'; } private boolean eqOperation(int idx, String op) { return formula.get(idx).equals(op); } private long getLong(int idx) { String str = formula.get(idx); int stridx = str.indexOf(","); if (stridx == -1) return Long.valueOf(str.substring(1), radix); //assume current radix else return Long.valueOf(str.substring(1, stridx), Integer.valueOf(str.substring(stridx+1))); } private double getDouble(int idx) { return Double.valueOf(formula.get(idx).substring(1)); } private double toRadians(double value) { if (!deg) return value; return Math.toRadians(value); } private void doEquals() { //calc formula boolean cont; double d1, d2, dr; long l1, l2, lr; System.out.println("doEquals"); for(int a=0;a<formula.size();a++) { System.out.println(formula.get(a)); if (formula.get(a).equals("pi")) { formula.set(a, "#" + Math.PI); } } while (formula.size() > 1) { int size = formula.size(); cont = false; //look for 2 argument type functions (functions are backwards) for(int a=0;a<size-1;a++) { if (isNumber(a) && eqOperation(a+1, "x^2")) { formula.set(a, "#" + (Math.pow(getDouble(a), 2.0))); formula.remove(a+1); cont = true; break; } if (isNumber(a) && eqOperation(a+1, "x^3")) { formula.set(a, "#" + (Math.pow(getDouble(a), 3.0))); formula.remove(a+1); cont = true; break; } if (isNumber(a) && eqOperation(a+1, "sqrt")) { formula.set(a, "#" + (Math.sqrt(getDouble(a)))); formula.remove(a+1); cont = true; break; } if (isNumber(a) && eqOperation(a+1, "sin")) { formula.set(a, "#" + (Math.sin(toRadians(getDouble(a))))); formula.remove(a+1); cont = true; break; } if (isNumber(a) && eqOperation(a+1, "cos")) { formula.set(a, "#" + (Math.cos(toRadians(getDouble(a))))); formula.remove(a+1); cont = true; break; } if (isNumber(a) && eqOperation(a+1, "tan")) { formula.set(a, "#" + (Math.tan(toRadians(getDouble(a))))); formula.remove(a+1); cont = true; break; } if (isNumber(a) && eqOperation(a+1, "log")) { //or lg() formula.set(a, "#" + (Math.log10(toRadians(getDouble(a))))); formula.remove(a+1); cont = true; break; } if (isNumber(a) && eqOperation(a+1, "ln")) { formula.set(a, "#" + (Math.log(toRadians(getDouble(a))))); formula.remove(a+1); cont = true; break; } if (isNumber(a) && eqOperation(a+1, "1/x")) { formula.set(a, "#" + (1.0 / getDouble(a))); formula.remove(a+1); cont = true; break; } } if (cont) continue; //look for 3 argument type operations in order of precedence for(int a=0;a<size-2;a++) { if (isNumber(a) && eqOperation(a+1, "x^y") && isNumber(a+2)) { formula.set(a, "#" + (Math.pow(getDouble(a), getDouble(a+2)))); formula.remove(a+1); formula.remove(a+1); cont = true; break; } if (isNumber(a) && eqOperation(a+1, "x") && isNumber(a+2)) { if (mode == 2) { formula.set(a, "#" + (getLong(a) * getLong(a+2)) + ",10"); } else { formula.set(a, "#" + (getDouble(a) * getDouble(a+2))); } formula.remove(a+1); formula.remove(a+1); cont = true; break; } if (isNumber(a) && eqOperation(a+1, "\u00f7") && isNumber(a+2)) { if (mode == 2) { formula.set(a, "#" + (getLong(a) / getLong(a+2)) + ",10"); } else { formula.set(a, "#" + (getDouble(a) / getDouble(a+2))); } formula.remove(a+1); formula.remove(a+1); cont = true; break; } if (isNumber(a) && eqOperation(a+1, "+") && isNumber(a+2)) { if (mode == 2) { formula.set(a, "#" + (getLong(a) + getLong(a+2)) + ",10"); } else { formula.set(a, "#" + (getDouble(a) + getDouble(a+2))); } formula.remove(a+1); formula.remove(a+1); cont = true; break; } if (isNumber(a) && eqOperation(a+1, "-") && isNumber(a+2)) { if (mode == 2) { formula.set(a, "#" + (getLong(a) - getLong(a+2)) + ",10"); } else { formula.set(a, "#" + (getDouble(a) - getDouble(a+2))); } formula.remove(a+1); formula.remove(a+1); cont = true; break; } if (isNumber(a) && eqOperation(a+1, "AND") && isNumber(a+2)) { formula.set(a, "#" + (getLong(a) & getLong(a+2)) + ",10"); formula.remove(a+1); formula.remove(a+1); cont = true; break; } if (isNumber(a) && eqOperation(a+1, "OR") && isNumber(a+2)) { formula.set(a, "#" + (getLong(a) | getLong(a+2)) + ",10"); formula.remove(a+1); formula.remove(a+1); cont = true; break; } if (isNumber(a) && eqOperation(a+1, "XOR") && isNumber(a+2)) { formula.set(a, "#" + (getLong(a) ^ getLong(a+2)) + ",10"); formula.remove(a+1); formula.remove(a+1); cont = true; break; } if (isNumber(a) && eqOperation(a+1, "MOD") && isNumber(a+2)) { formula.set(a, "#" + (getLong(a) % getLong(a+2)) + ",10"); formula.remove(a+1); formula.remove(a+1); cont = true; break; } if (isOpen(a) && isNumber(a+1) && isClose(a+2)) { formula.remove(a); formula.remove(a+1); cont = true; break; } } if (cont) continue; //ERROR - formula not solveable formula.clear(); display.setDisplay("Error:Bad formula"); error = true; System.out.println("Error(1)"); return; } if (formula.isEmpty()) formula.add("#0"); if (!isNumber(0)) { formula.clear(); display.setDisplay("Error:Bad formula"); error = true; System.out.println("Error(2)"); return; } String str = formula.get(0); if (mode == 2) { if (radix != 10) { str = "#" + Long.toString(getLong(0), radix).toUpperCase() + "," + radix; } } else { if (str.endsWith(".0")) { str = str.substring(0, str.length()-2); } } formula.set(0, str); System.out.println("=" + formula.get(0)); display.setDisplay(formula.get(0).substring(1)); } private void addDigit2(char digit) { if ((fidx == 1) && (isNumber(0))) { formula.remove(0); //remove last result fidx--; } formula.set(fidx, formula.get(fidx) + digit); } public void addDigit(char digit) { if (error) return; if ((digit >= 'A') && (digit <= 'F') && mode != 2) return; //keyboard if (mode == 2) { int value = 0; if ((digit >= 'A') && (digit <= 'F')) value = digit - 'A' + 10; if ((digit >= '0') && (digit <= '9')) value = digit - '0'; if (value >= radix) return; } String str = formula.get(fidx); if (str.length() == 0) addDigit2('#'); if (digit == '.') { if (mode == 2) return; //keyboard if (str.indexOf(".") != -1) return; addDigit2('.'); } else { addDigit2(digit); } display.setDisplay(formula.get(fidx).substring(1)); } public void endEntry() { if (isNumber(fidx)) { String str = formula.get(fidx); if ((mode == 2) && (str.charAt(0) == '#') && (str.indexOf(",") == -1)) { //add radix if needed formula.set(fidx, formula.get(fidx) + "," + radix); } fidx++; formula.add(""); } } public void addOperation(String op) { if (op.equals("AC")) {doAllClear(); return;} if (error) return; if ((fidx == 0) && (op.equals("-")) && formula.get(fidx).length() == 0) { op = "+/-"; } if (op.equals("+/-")) { String str = formula.get(fidx); if (str.length() == 0) { addDigit2('#'); str = "#"; } if (str.length() == 1) { addDigit2('-'); display.setDisplay(formula.get(fidx).substring(1)); return; } if (str.length() > 1 && str.charAt(1) == '-') { str = "#" + str.substring(2); formula.set(fidx, str); display.setDisplay(formula.get(fidx).substring(1)); } else { str = "#-" + str.substring(1); formula.set(fidx, str); display.setDisplay(formula.get(fidx).substring(1)); } return; } endEntry(); if (op.equals("=")) { try { if (formula.get(fidx).equals("")) formula.remove(fidx); doEquals(); fidx = 1; formula.add(""); } catch (Exception e) { System.out.println("" + e); e.printStackTrace(); error = true; display.setDisplay("Error:" + e); } } else { formula.set(fidx, op); display.setDisplay(op); fidx++; formula.add(""); } } public void doAllClear() { error = false; formula.clear(); formula.add(""); display.setDisplay(""); fidx = 0; } public void doErase() { String txt = formula.get(fidx); int len = txt.length(); if (len < 2) return; if (txt.charAt(0) != '#') return; txt = txt.substring(0, len-1); formula.set(fidx, txt); display.setDisplay(txt.substring(1)); } public void paste() { JTextField tf = new JTextField(); tf.paste(); char ca[] = tf.getText().toCharArray(); for(int a=0;a<ca.length;a++) { addDigit(ca[a]); } } public void setRadix(int newRadix) { if ((formula.size() == 2) && (formula.get(1).length() == 0)) formula.remove(1); if ((formula.size() == 1) && (formula.get(0).length() == 0)) formula.remove(0); if ((formula.size() != 1) || !isNumber(0)) { doAllClear(); } else { formula.set(0, "#" + Long.toString(getLong(0), newRadix).toUpperCase() + "," + newRadix); display.setDisplay(formula.get(0).substring(1)); fidx = 1; formula.add(""); } radix = newRadix; } public void setDeg(boolean deg) { this.deg = deg; } public void about() { inDialog = true; JF.showMessage("About", "jfcalc/" + CalculatorApp.version + "\n"); inDialog = false; } public boolean dispatchKeyEvent(KeyEvent e) { if (inDialog) return false; int id = e.getID(); char ch = e.getKeyChar(); int cc = e.getKeyCode(); int mod = e.getModifiers(); //JFLog.log("key:" + ch + "," + cc + "," + mod + ":" + inDialog); if (mod == KeyEvent.SHIFT_MASK) { switch (id) { case KeyEvent.KEY_TYPED: switch (ch) { case '+': addOperation("+"); break; case '(': addOperation("("); break; case ')': addOperation(")"); break; case '*': addOperation("x"); break; } } } if (mod != 0) return false; switch (id) { case KeyEvent.KEY_TYPED: switch (ch) { case 'a': addDigit('A'); break; case 'b': addDigit('B'); break; case 'c': addDigit('C'); break; case 'd': addDigit('D'); break; case 'e': addDigit('E'); break; case 'f': addDigit('F'); break; case '0': addDigit('0'); break; case '1': addDigit('1'); break; case '2': addDigit('2'); break; case '3': addDigit('3'); break; case '4': addDigit('4'); break; case '5': addDigit('5'); break; case '6': addDigit('6'); break; case '7': addDigit('7'); break; case '8': addDigit('8'); break; case '9': addDigit('9'); break; case '.': addDigit('.'); break; case '*': addOperation("x"); break; case '/': addOperation("\u00f7"); break; case '-': addOperation("-"); break; case '=': addOperation("="); break; case '+': addOperation("+"); break; //keypad } break; case KeyEvent.KEY_PRESSED: switch (cc) { case KeyEvent.VK_ENTER: addOperation("="); break; case KeyEvent.VK_F1: about(); break; case KeyEvent.VK_F5: if (mode == 2) display.setRadix(16); break; case KeyEvent.VK_F6: if (mode == 2) display.setRadix(10); break; case KeyEvent.VK_F7: if (mode == 2) display.setRadix(8); break; case KeyEvent.VK_F8: if (mode == 2) display.setRadix(2); break; case KeyEvent.VK_ESCAPE: doAllClear(); break; case KeyEvent.VK_BACK_SPACE: doErase(); break; } break; case KeyEvent.KEY_RELEASED: break; } return false; } }