【電卓アプリを作るvol.4】ソースコード2/2
Calc
メインの電卓クラス
アクティビティからnewして使います。
public class Calc implements Context { // ディスプレイ表示が変わるたびに、文字列をコールバックします public interface Callback{ void onTextChanged(String string); } Callback callback; // 最大表示可能桁数 private final int MAX_DIGIT = 12; static public final int KEY_00 = 10, KEY_DOT = 20, KEY_EQUAL = 21, KEY_TASU = 22, KEY_HIKU = 23, KEY_KAKERU = 24, KEY_WARU = 25, KEY_PERCENT = 26, KEY_SIGN_CHANGE = 27, KEY_C = 31, KEY_AC = 32, KEY_BACK_SPACE = 32; private StringBuilder stringBuilder; private double value1,value2; // 左辺、右辺保持 private int enzanshi; private State state; // コンストラクター。ACで初期化しています public Calc() { allClear(); } public void setListener(Callback callback){ this.callback = callback; } // 現在の表示をdoubleで取得 private double getValue(){ return Double.valueOf(stringBuilder.toString()); } // 文字列を表示用変数にセット private void set(String s){ stringBuilder = new StringBuilder(s); } // doubleを文字列に変換して、表示用変数にセット private void set(double d){ stringBuilder = new StringBuilder(String.valueOf(d)); } private boolean isENZAN_Key(int key) { if (key == KEY_TASU || key == KEY_HIKU || key == KEY_KAKERU || key == KEY_WARU){ return true; } return false; } private boolean isNumber_key(int key) { if (0 <= key && key <= 9 || key == KEY_DOT){ return true; } return false; } // 引数のキーを入力 public void input(int inputKey) { if (isNumber_key(inputKey)) state.inputNumber(this, inputKey); else if (inputKey == KEY_00) { state.inputNumber(this, 0); state.inputNumber(this, 0); } else if (isENZAN_Key(inputKey)) state.inputEnzanshi(this, inputKey); else if (inputKey == KEY_EQUAL) state.inputEqual(this); else if (inputKey == KEY_C) state.inputClear(this); else if (inputKey == KEY_AC) allClear(); else if (inputKey == KEY_BACK_SPACE) state.inputBackSpace(this); else if (inputKey == KEY_SIGN_CHANGE) signChange(); else if (inputKey == KEY_PERCENT) state.inputPercent(this); callback.onTextChanged(stringBuilder.toString()); } // 四則演算します private double calculation(double d1,int ope,double d2){ try { double ans = 0; switch (ope) { case KEY_TASU: ans = d1 + d2; break; case KEY_HIKU: ans = d1 - d2; break; case KEY_KAKERU: ans = d1 * d2; break; case KEY_WARU: if (d2 == 0){ // エラー return 0; } else { ans = d1 / d2; } break; } return ans; } catch (java.lang.IllegalArgumentException a){ // エラー } return 0; } // +/-の変換 private void signChange() { if (state.getStateValue(this) == State.STATE_B){ setLeftDouble(); set("-0"); changeState(StateC.getInstance()); } else { if (stringBuilder.indexOf("-") == -1){ stringBuilder.insert(0,"-"); } else { stringBuilder.deleteCharAt(0); } } } // 末尾に数字を追加 @Override public void addNum(int key) { if (stringBuilder.length() >= MAX_DIGIT)return; if (key == KEY_DOT) { if (stringBuilder.indexOf(".") == -1) stringBuilder.append("."); } else if (stringBuilder.length() == 1 && stringBuilder.charAt(0) == '0') { stringBuilder.replace(0, 1, "" + key); } else if (stringBuilder.toString().equals("-0")) { stringBuilder.replace(1, 2, "" + key); } else { stringBuilder.append("" + key); } } // 表示されている数値を左辺として保持 @Override public void setLeftDouble() { value1 = getValue(); } // 表示されている数値を右辺として保持 @Override public void setRightValue() { value2 = getValue(); } // 押された演算子を保持 @Override public void setEnzanshi(int key) { enzanshi = key; } @Override public void keisan() { double ans = calculation(value1,enzanshi,getValue()); set(ans); } // 表示の数値と、保持していた右辺・演算子で計算 @Override public void teisuKeisan() { double ans = calculation(getValue(),enzanshi,value2); set(ans); } // 演算子が+、-のときは左辺のxパーセント // ×、÷のときは右辺の100分の1をセット @Override public void percent() { if (enzanshi == KEY_TASU || enzanshi == KEY_HIKU){ set((getValue() * value1) / 100d); } else { set(getValue() / 100d); } } @Override public void dividedBy100() { set(getValue() / 100d); } // 1文字消す @Override public void backSpace() { if (stringBuilder.length() == 1){ set("0"); } else if (stringBuilder.length() == 2 && stringBuilder.indexOf("-") == 0){ set("0"); } else { stringBuilder.deleteCharAt(stringBuilder.length() - 1); set(stringBuilder.toString()); } } @Override public void clear() { if (stringBuilder.toString().equals("0")) { allClear(); } else { set("0"); } } @Override public void allClear() { set("0"); enzanshi = -1; value1 = 0; value2 = 0; changeState(StateA.getInstance()); } @Override public void dispZero() { set("0"); } // 状態を明示的に変更 @Override public void changeState(State instance) { this.state = instance; } }