diff --git a/android-app-core/res/layout/plot_functions_fragment_list_item.xml b/android-app-core/res/layout/plot_functions_fragment_list_item.xml new file mode 100644 index 00000000..26375b48 --- /dev/null +++ b/android-app-core/res/layout/plot_functions_fragment_list_item.xml @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/android-app-core/src/main/java/org/solovyev/android/calculator/CalculatorPreferences.java b/android-app-core/src/main/java/org/solovyev/android/calculator/CalculatorPreferences.java index 5eb97b3e..1f643e84 100644 --- a/android-app-core/src/main/java/org/solovyev/android/calculator/CalculatorPreferences.java +++ b/android-app-core/src/main/java/org/solovyev/android/calculator/CalculatorPreferences.java @@ -8,10 +8,18 @@ import org.solovyev.android.AndroidUtils; import org.solovyev.android.calculator.math.MathType; import org.solovyev.android.calculator.model.AndroidCalculatorEngine; import org.solovyev.android.calculator.plot.GraphLineColor; -import org.solovyev.android.prefs.*; +import org.solovyev.android.calculator.plot.ParcelablePlotInput; +import org.solovyev.android.prefs.BooleanPreference; +import org.solovyev.android.prefs.IntegerPreference; +import org.solovyev.android.prefs.LongPreference; +import org.solovyev.android.prefs.Preference; +import org.solovyev.android.prefs.R; +import org.solovyev.android.prefs.StringPreference; import org.solovyev.android.view.VibratorContainer; +import org.solovyev.common.ListMapper; import java.text.DecimalFormatSymbols; +import java.util.List; import java.util.Locale; /** diff --git a/android-app/src/main/java/org/solovyev/android/calculator/plot/FunctionLineColorType.java b/android-app-core/src/main/java/org/solovyev/android/calculator/plot/FunctionLineColorType.java similarity index 100% rename from android-app/src/main/java/org/solovyev/android/calculator/plot/FunctionLineColorType.java rename to android-app-core/src/main/java/org/solovyev/android/calculator/plot/FunctionLineColorType.java diff --git a/android-app/src/main/java/org/solovyev/android/calculator/plot/FunctionLineDef.java b/android-app-core/src/main/java/org/solovyev/android/calculator/plot/FunctionLineDef.java similarity index 69% rename from android-app/src/main/java/org/solovyev/android/calculator/plot/FunctionLineDef.java rename to android-app-core/src/main/java/org/solovyev/android/calculator/plot/FunctionLineDef.java index 2924c1fb..94f010b4 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/plot/FunctionLineDef.java +++ b/android-app-core/src/main/java/org/solovyev/android/calculator/plot/FunctionLineDef.java @@ -2,6 +2,8 @@ package org.solovyev.android.calculator.plot; import android.graphics.Color; import android.graphics.Paint; +import android.os.Parcel; +import android.os.Parcelable; import org.jetbrains.annotations.NotNull; /** @@ -9,7 +11,7 @@ import org.jetbrains.annotations.NotNull; * Date: 1/5/13 * Time: 7:41 PM */ -public class FunctionLineDef { +public class FunctionLineDef implements Parcelable { /* ********************************************************************** @@ -22,6 +24,26 @@ public class FunctionLineDef { @NotNull private static final Float DEFAULT_LINE_WIDTH = -1f; + /* + ********************************************************************** + * + * STATIC + * + ********************************************************************** + */ + + private static final Creator CREATOR = new Creator() { + @Override + public FunctionLineDef createFromParcel(@NotNull Parcel in) { + return fromParcel(in); + } + + @Override + public FunctionLineDef[] newArray(int size) { + return new FunctionLineDef[size]; + } + }; + /* ********************************************************************** * @@ -70,6 +92,18 @@ public class FunctionLineDef { return result; } + public static FunctionLineDef fromParcel(@NotNull Parcel in) { + final FunctionLineDef result = new FunctionLineDef(); + + result.lineColorType = (FunctionLineColorType) in.readSerializable(); + result.lineColor = in.readInt(); + result.lineStyle = (FunctionLineStyle) in.readSerializable(); + result.lineWidth = in.readFloat(); + + return result; + } + + @NotNull public static FunctionLineDef newDefaultInstance() { return new FunctionLineDef(); @@ -106,4 +140,17 @@ public class FunctionLineDef { lineStyle.applyToPaint(paint); } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NotNull Parcel out, int flags) { + out.writeSerializable(lineColorType); + out.writeInt(lineColor); + out.writeSerializable(lineStyle); + out.writeFloat(lineWidth); + } } diff --git a/android-app/src/main/java/org/solovyev/android/calculator/plot/FunctionLineStyle.java b/android-app-core/src/main/java/org/solovyev/android/calculator/plot/FunctionLineStyle.java similarity index 100% rename from android-app/src/main/java/org/solovyev/android/calculator/plot/FunctionLineStyle.java rename to android-app-core/src/main/java/org/solovyev/android/calculator/plot/FunctionLineStyle.java diff --git a/android-app-core/src/main/java/org/solovyev/android/calculator/plot/ParcelablePlotInput.java b/android-app-core/src/main/java/org/solovyev/android/calculator/plot/ParcelablePlotInput.java new file mode 100644 index 00000000..b33deab5 --- /dev/null +++ b/android-app-core/src/main/java/org/solovyev/android/calculator/plot/ParcelablePlotInput.java @@ -0,0 +1,131 @@ +package org.solovyev.android.calculator.plot; + +import android.os.Parcel; +import android.os.Parcelable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ParcelablePlotInput implements Parcelable { + + /* + ********************************************************************** + * + * STATIC + * + ********************************************************************** + */ + @NotNull + public static Creator CREATOR = new Creator() { + @Override + public ParcelablePlotInput createFromParcel(@NotNull Parcel in) { + return fromParcel(in); + } + + @Override + public ParcelablePlotInput[] newArray(int size) { + return new ParcelablePlotInput[size]; + } + }; + + /* + ********************************************************************** + * + * FIELDS + * + ********************************************************************** + */ + + @NotNull + private String expression; + + @Nullable + private String xVariableName; + + @Nullable + private String yVariableName; + + @Nullable + private FunctionLineDef lineDef; + + public ParcelablePlotInput(@NotNull String expression, + @Nullable String xVariableName, + @Nullable String yVariableName) { + this(expression, xVariableName, yVariableName, null); + } + + public ParcelablePlotInput(@NotNull String expression, + @Nullable String xVariableName, + @Nullable String yVariableName, + @Nullable FunctionLineDef lineDef) { + this.expression = expression; + this.xVariableName = xVariableName; + this.yVariableName = yVariableName; + this.lineDef = lineDef; + } + + @NotNull + public static ParcelablePlotInput fromParcel(@NotNull Parcel in) { + final String expression = in.readString(); + final String xVariableName = in.readString(); + final String yVariableName = in.readString(); + final FunctionLineDef lineDef = in.readParcelable(Thread.currentThread().getContextClassLoader()); + return new ParcelablePlotInput(expression, xVariableName, yVariableName, lineDef); + } + + @NotNull + public String getExpression() { + return expression; + } + + @Nullable + public String getXVariableName() { + return xVariableName; + } + + @Nullable + public String getYVariableName() { + return yVariableName; + } + + @Nullable + public FunctionLineDef getLineDef() { + return lineDef; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NotNull Parcel out, int flags) { + out.writeString(expression); + out.writeString(xVariableName); + out.writeString(yVariableName); + out.writeParcelable(lineDef, 0); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ParcelablePlotInput)) return false; + + final ParcelablePlotInput that = (ParcelablePlotInput) o; + + if (!expression.equals(that.expression)) return false; + if (xVariableName != null ? !xVariableName.equals(that.xVariableName) : that.xVariableName != null) + return false; + if (yVariableName != null ? !yVariableName.equals(that.yVariableName) : that.yVariableName != null) + return false; + + return true; + } + + @Override + public int hashCode() { + int result = expression.hashCode(); + result = 31 * result + (xVariableName != null ? xVariableName.hashCode() : 0); + result = 31 * result + (yVariableName != null ? yVariableName.hashCode() : 0); + return result; + } +} diff --git a/android-app-core/src/main/java/org/solovyev/android/calculator/plot/ParcelablePlotInputListItem.java b/android-app-core/src/main/java/org/solovyev/android/calculator/plot/ParcelablePlotInputListItem.java new file mode 100644 index 00000000..86d74b3c --- /dev/null +++ b/android-app-core/src/main/java/org/solovyev/android/calculator/plot/ParcelablePlotInputListItem.java @@ -0,0 +1,57 @@ +package org.solovyev.android.calculator.plot; + +import android.content.Context; +import android.view.View; +import android.widget.TextView; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.core.R; +import org.solovyev.android.list.ListItem; +import org.solovyev.android.view.TextViewBuilder; +import org.solovyev.android.view.UpdatableViewBuilder; + +public class ParcelablePlotInputListItem implements ListItem { + + @NotNull + private ParcelablePlotInput plotInput; + + @NotNull + private UpdatableViewBuilder viewBuilder; + + public ParcelablePlotInputListItem(@NotNull ParcelablePlotInput plotInput) { + this.plotInput = plotInput; + // todo serso: use correct tag + this.viewBuilder = TextViewBuilder.newInstance(R.layout.plot_functions_fragment_list_item, null); + } + + @Nullable + @Override + public OnClickAction getOnClickAction() { + return null; + } + + @Nullable + @Override + public OnClickAction getOnLongClickAction() { + return null; + } + + @NotNull + @Override + public View updateView(@NotNull Context context, @NotNull View view) { + // todo serso: optimize + return build(context); + } + + @NotNull + @Override + public View build(@NotNull Context context) { + TextView textView = viewBuilder.build(context); + fill(textView); + return textView; + } + + private void fill(@NotNull TextView textView) { + textView.setText(plotInput.getExpression()); + } +} diff --git a/android-app/res/layout/plot_functions_fragment.xml b/android-app/res/layout/plot_functions_fragment.xml new file mode 100644 index 00000000..30263ec4 --- /dev/null +++ b/android-app/res/layout/plot_functions_fragment.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/android-app/src/main/java/arity/calculator/Calculator.java b/android-app/src/main/java/arity/calculator/Calculator.java deleted file mode 100755 index 07a34704..00000000 --- a/android-app/src/main/java/arity/calculator/Calculator.java +++ /dev/null @@ -1,493 +0,0 @@ -// Copyright (C) 2009 Mihai Preda - -package arity.calculator; - -import android.app.Activity; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.KeyEvent; -import android.view.View; -import android.widget.AdapterView; -import android.widget.EditText; -import android.widget.ListView; -import android.widget.TextView; -import org.javia.arity.*; -import org.solovyev.android.calculator.Locator; -import org.solovyev.android.calculator.plot.Graph2dView; -import org.solovyev.android.calculator.plot.Graph3dView; - -import java.util.ArrayList; - -public class Calculator extends Activity implements TextWatcher, - View.OnKeyListener, - View.OnClickListener, - AdapterView.OnItemClickListener, - SharedPreferences.OnSharedPreferenceChangeListener -{ - static final char MINUS = '\u2212', TIMES = '\u00d7', DIV = '\u00f7', SQRT = '\u221a', PI = '\u03c0', - UP_ARROW = '\u21e7', DN_ARROW = '\u21e9', ARROW = '\u21f3'; - - private static final int MSG_INPUT_CHANGED = 1; - private static final String INFINITY = "Infinity"; - private static final String INFINITY_UNICODE = "\u221e"; - - static Symbols symbols = new Symbols(); - static Function function; - - private TextView result; - private EditText input; - private ListView historyView; - private Graph2dView graphView; - private Graph3dView graph3dView; - private History history; - private int nDigits = 0; - private boolean pendingClearResult; - private boolean isAlphaVisible; - static ArrayList graphedFunction; - static Defs defs; - private ArrayList auxFuncs = new ArrayList(); - static boolean useHighQuality3d = true; - - private static final char[][] ALPHA = { - {'q', 'w', '=', ',', ';', SQRT, '!', '\''}, - {'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'}, - {'a', 's', 'd', 'f', 'g', 'h', 'j', 'k'}, - {'z', 'x', 'c', 'v', 'b', 'n', 'm', 'l'}, - }; - - private static final char[][] DIGITS = { - {'7', '8', '9', '%', '^', ARROW}, - {'4', '5', '6','(', ')', 'C'}, - {'1', '2', '3', TIMES, DIV, 'E'}, - {'0', '0', '.', '+', MINUS, 'E'}, - }; - - private static final char[][] DIGITS2 = { - {'0', '.', '+', MINUS, TIMES, DIV, '^', '(', ')', 'C'}, - {'1', '2', '3', '4', '5', '6', '7', '8', '9', 'E'}, - }; - - /* - private static final char[][] DIGITS3 = { - {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'}, - {'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', PI}, - {'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '=', '%'}, - {'0', '.', '+', MINUS, TIMES, DIV, '^', '(', ')', 'C'}, - {'1', '2', '3', '4', '5', '6', '7', '8', '9', 'E'}, - }; - */ - - public void onConfigurationChanged(Configuration config) { - super.onConfigurationChanged(config); - internalConfigChange(config); - } - - private void internalConfigChange(Configuration config) { - /*setContentView(R.layout.main); - graphView = (GraphView) findViewById(R.id.graph); - graph3dView = (Graph3dView) findViewById(R.id.graph3d); - historyView = (ListView) findViewById(R.id.history); - - final boolean isLandscape = config.orientation == Configuration.ORIENTATION_LANDSCAPE; - // final boolean hasKeyboard = config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO; - - alpha = (KeyboardView) findViewById(R.id.alpha); - digits = (KeyboardView) findViewById(R.id.digits); - if (isLandscape) { - digits.init(DIGITS2, false, true); - isAlphaVisible = false; - } else { - alpha.init(ALPHA, false, false); - digits.init(DIGITS, true, true); - updateAlpha(); - } - - result = (TextView) findViewById(R.id.result); - - Editable oldText = input != null ? input.getText() : null; - input = (EditText) findViewById(R.id.input); - input.setOnKeyListener(this); - input.addTextChangedListener(this); - input.setEditableFactory(new CalculatorEditable.Factory()); - input.setInputType(0); - changeInput(history.getText()); - if (oldText != null) { - input.setText(oldText); - } - input.requestFocus(); - graphView.setOnClickListener(this); - graph3dView.setOnClickListener(this); - if (historyView != null) { - historyView.setAdapter(adapter); - historyView.setOnItemClickListener(this); - }*/ - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - history = new History(this); - internalConfigChange(getResources().getConfiguration()); - - defs = new Defs(this, symbols); - if (history.fileNotFound) { - String[] init = { - "sqrt(pi)\u00f70.5!", - "e^(i\u00d7pi)", - "ln(e^100)", - "sin(x)", - "x^2" - }; - nDigits = 10; - for (String s : init) { - onEnter(s); - } - nDigits = 0; - } - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - prefs.registerOnSharedPreferenceChangeListener(this); - String value = prefs.getString("quality", null); - if (value == null) { - useHighQuality3d = Build.VERSION.SDK_INT >= 5; - prefs.edit().putString("quality", useHighQuality3d ? "high" : "low").commit(); - } else { - useHighQuality3d = value.equals("high"); - } - } - - public void onPause() { - super.onPause(); - graph3dView.onPause(); - history.updateEdited(input.getText().toString()); - history.save(); - defs.save(); - } - - public void onResume() { - super.onResume(); - graph3dView.onResume(); - } - - //OnSharedPreferenceChangeListener - public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { - if (key.equals("quality")) { - useHighQuality3d = prefs.getString(key, "high").equals("high"); - // Calculator.log("useHigh quality changed to " + useHighQuality3d); - } - } - - //OnClickListener - public void onClick(View target) { - } - - // OnItemClickListener - public void onItemClick(AdapterView parent, View view, int pos, long id) { - history.moveToPos(pos, input.getText().toString()); - changeInput(history.getText()); - } - - // TextWatcher - public void afterTextChanged(Editable s) { - // handler.removeMessages(MSG_INPUT_CHANGED); - // handler.sendEmptyMessageDelayed(MSG_INPUT_CHANGED, 250); - evaluate(); - /* - if (pendingClearResult && s.length() != 0) { - if (!(s.length() == 4 && s.toString().startsWith("ans"))) { - result.setText(null); - } - showGraph(null); - pendingClearResult = false; - } - */ - } - - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - public void onTextChanged(CharSequence s, int start, int before, int count) { - } - - - // OnKeyListener - public boolean onKey(View v, int keyCode, KeyEvent event) { - int action = event.getAction(); - if (action == KeyEvent.ACTION_DOWN) { - switch (keyCode) { - case KeyEvent.KEYCODE_ENTER: - case KeyEvent.KEYCODE_DPAD_CENTER: - doEnter(); - break; - - case KeyEvent.KEYCODE_DPAD_UP: - onUp(); - break; - - case KeyEvent.KEYCODE_DPAD_DOWN: - onDown(); - break; - default: - return false; - } - return true; - } else { - switch (keyCode) { - case KeyEvent.KEYCODE_ENTER: - case KeyEvent.KEYCODE_DPAD_CENTER: - case KeyEvent.KEYCODE_DPAD_UP: - case KeyEvent.KEYCODE_DPAD_DOWN: - return true; - } - return false; - } - } - - /* - private Handler handler = new Handler() { - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_INPUT_CHANGED: - // String text = input.getText().toString(); - evaluate(); - } - } - }; - */ - - static void log(String mes) { - if (mes != null) { - Locator.getInstance().getLogger().debug(null, mes); - } - } - - void evaluate() { - evaluate(input.getText().toString()); - } - - private String formatEval(Complex value) { - if (nDigits == 0) { - nDigits = getResultSpace(); - } - String res = Util.complexToString(value, nDigits, 2); - return res.replace(INFINITY, INFINITY_UNICODE); - } - - private void evaluate(String text) { - // log("evaluate " + text); - if (text.length() == 0) { - result.setEnabled(false); - return; - } - - auxFuncs.clear(); - int end = -1; - do { - text = text.substring(end+1); - end = text.indexOf(';'); - String slice = end == -1 ? text : text.substring(0, end); - try { - Function f = symbols.compile(slice); - auxFuncs.add(f); - } catch (SyntaxException e) { - continue; - } - } while (end != -1); - - graphedFunction = auxFuncs; - int size = auxFuncs.size(); - if (size == 0) { - result.setEnabled(false); - return; - } else if (size == 1) { - Function f = auxFuncs.get(0); - int arity = f.arity(); - // Calculator.log("res " + f); - if (arity == 1 || arity == 2) { - result.setText(null); - showGraph(f); - } else if (arity == 0) { - result.setText(formatEval(f.evalComplex())); - result.setEnabled(true); - showGraph(null); - } else { - result.setText("function"); - result.setEnabled(true); - showGraph(null); - } - } else { - //graphView.setFunctionPlotDefs(auxFuncs); - if (graphView.getVisibility() != View.VISIBLE) { - if (isAlphaVisible) { - isAlphaVisible = false; - updateAlpha(); - } - result.setVisibility(View.GONE); - historyView.setVisibility(View.GONE); - graph3dView.setVisibility(View.GONE); - graph3dView.onPause(); - graphView.setVisibility(View.VISIBLE); - } - } - } - - private int getResultSpace() { - int width = result.getWidth() - result.getTotalPaddingLeft() - result.getTotalPaddingRight(); - float oneDigitWidth = result.getPaint().measureText("5555555555") / 10f; - return (int) (width / oneDigitWidth); - } - - private void updateAlpha() { - - } - - private StringBuilder oneChar = new StringBuilder(" "); - void onKey(char key) { - if (key == 'E') { - doEnter(); - } else if (key == 'C') { - doBackspace(); - } else if (key == ARROW) { - isAlphaVisible = !isAlphaVisible; - updateAlpha(); - } else { - int cursor = input.getSelectionStart(); - oneChar.setCharAt(0, key); - input.getText().insert(cursor, oneChar); - } - } - - private void showGraph(Function f) { - if (f == null) { - if (historyView.getVisibility() != View.VISIBLE) { - graphView.setVisibility(View.GONE); - graph3dView.setVisibility(View.GONE); - graph3dView.onPause(); - historyView.setVisibility(View.VISIBLE); - result.setVisibility(View.VISIBLE); - } - } else { - // graphedFunction = f; - if (f.arity() == 1) { - //graphView.setFunctionPlotDefs(Arrays.asList(f)); - if (graphView.getVisibility() != View.VISIBLE) { - if (isAlphaVisible) { - isAlphaVisible = false; - updateAlpha(); - } - result.setVisibility(View.GONE); - historyView.setVisibility(View.GONE); - graph3dView.setVisibility(View.GONE); - graph3dView.onPause(); - graphView.setVisibility(View.VISIBLE); - } - } else { - //graph3dView.setFunctionPlotDefs(Arrays.asList(f)); - if (graph3dView.getVisibility() != View.VISIBLE) { - if (isAlphaVisible) { - isAlphaVisible = false; - updateAlpha(); - } - result.setVisibility(View.GONE); - historyView.setVisibility(View.GONE); - graphView.setVisibility(View.GONE); - graph3dView.setVisibility(View.VISIBLE); - graph3dView.onResume(); - } - } - } - } - - void onEnter() { - onEnter(input.getText().toString()); - } - - void onEnter(String text) { - boolean historyChanged = false; - try { - FunctionAndName fan = symbols.compileWithName(text); - if (fan.name != null) { - symbols.define(fan); - defs.add(text); - } - Function f = fan.function; - int arity = f.arity(); - Complex value = null; - if (arity == 0) { - value = f.evalComplex(); - symbols.define("ans", value); - } - historyChanged = arity == 0 ? - history.onEnter(text, formatEval(value)) : - history.onEnter(text, null); - } catch (SyntaxException e) { - historyChanged = history.onEnter(text, null); - } - showGraph(null); - - if (text.length() == 0) { - result.setText(null); - } - changeInput(history.getText()); - } - - private void changeInput(String newInput) { - input.setText(newInput); - input.setSelection(newInput.length()); - /* - if (newInput.length() > 0) { - result.setText(null); - } else { - pendingClearResult = true; - } - */ - /* - if (result.getText().equals("function")) { - result.setText(null); - } - */ - } - - /* - private void updateChecked() { - int pos = history.getListPos(); - if (pos >= 0) { - log("check " + pos); - historyView.setItemChecked(pos, true); - adapter.notifyDataSetInvalidated(); - } - } - */ - - void onUp() { - if (history.moveUp(input.getText().toString())) { - changeInput(history.getText()); - // updateChecked(); - } - } - - void onDown() { - if (history.moveDown(input.getText().toString())) { - changeInput(history.getText()); - // updateChecked(); - } - } - - private static final KeyEvent - KEY_DEL = new KeyEvent(0, KeyEvent.KEYCODE_DEL), - KEY_ENTER = new KeyEvent(0, KeyEvent.KEYCODE_ENTER); - - void doEnter() { - onEnter(); - } - - void doBackspace() { - input.dispatchKeyEvent(KEY_DEL); - } - - -} diff --git a/android-app/src/main/java/arity/calculator/Defs.java b/android-app/src/main/java/arity/calculator/Defs.java deleted file mode 100755 index dfa3ae76..00000000 --- a/android-app/src/main/java/arity/calculator/Defs.java +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (C) 2009 Mihai Preda - -package arity.calculator; - -import android.content.Context; -import org.javia.arity.Symbols; -import org.javia.arity.SyntaxException; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.ArrayList; - -class Defs extends FileHandler { - private static final int SIZE_LIMIT = 50; - ArrayList lines = new ArrayList(); - private Symbols symbols; - - Defs(Context context, Symbols symbols) { - super(context, "defs", 1); - this.symbols = symbols; - symbols.pushFrame(); - load(); - } - - void clear() { - lines.clear(); - symbols.popFrame(); - symbols.pushFrame(); - } - - int size() { - return lines.size(); - } - - void doRead(DataInputStream is) throws IOException { - int size = is.readInt(); - for (int i = 0; i < size; ++i) { - String line = is.readUTF(); - lines.add(line); - try { - symbols.define(symbols.compileWithName(line)); - } catch (SyntaxException e) { - // ignore - } - } - } - - void doWrite(DataOutputStream os) throws IOException { - os.writeInt(lines.size()); - for (String s : lines) { - os.writeUTF(s); - } - } - - void add(String text) { - if (lines.size() >= SIZE_LIMIT) { - lines.remove(0); - } - lines.add(text); - } -} diff --git a/android-app/src/main/java/arity/calculator/FileHandler.java b/android-app/src/main/java/arity/calculator/FileHandler.java deleted file mode 100755 index f520d982..00000000 --- a/android-app/src/main/java/arity/calculator/FileHandler.java +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (C) 2009 Mihai Preda - -package arity.calculator; - -import android.content.Context; -import java.io.*; - -abstract class FileHandler { - private String fileName; - private Context context; - private int version; - boolean fileNotFound; - - private DataInputStream openInput() throws IOException { - try { - return new DataInputStream(new BufferedInputStream(context.openFileInput(fileName), 256)); - } catch (FileNotFoundException e) { - fileNotFound = true; - return null; - } - } - - private DataOutputStream openOutput() throws IOException { - return new DataOutputStream(new BufferedOutputStream(context.openFileOutput(fileName, 0), 256)); - } - - FileHandler(Context context, String fileName, int version) { - this.context = context; - this.fileName = fileName; - this.version = version; - } - - void load() { - try { - DataInputStream is = openInput(); - if (is != null) { - int readVersion = is.readInt(); - if (readVersion != version) { - throw new IllegalStateException("invalid version " + readVersion); - } - doRead(is); - is.close(); - } - } catch (IOException e) { - throw new RuntimeException("" + e); - } - } - - void save() { - try { - DataOutputStream os = openOutput(); - os.writeInt(version); - doWrite(os); - os.close(); - } catch (IOException e) { - throw new RuntimeException("" + e); - } - } - - abstract void doRead(DataInputStream is) throws IOException; - abstract void doWrite(DataOutputStream os) throws IOException; -} diff --git a/android-app/src/main/java/arity/calculator/History.java b/android-app/src/main/java/arity/calculator/History.java deleted file mode 100755 index 3bda9c8f..00000000 --- a/android-app/src/main/java/arity/calculator/History.java +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (C) 2009 Mihai Preda - -package arity.calculator; - -import android.content.Context; -import java.io.*; -import java.util.ArrayList; - -class History extends FileHandler { - private static final int SIZE_LIMIT = 30; - ArrayList entries = new ArrayList(); - int pos; - HistoryEntry aboveTop = new HistoryEntry("", ""); - - - History(Context context) { - super(context, "history", 1); - load(); - } - - void clear() { - entries.clear(); - pos = 0; - } - - int size() { - return entries.size(); - } - - void doRead(DataInputStream is) throws IOException { - aboveTop = new HistoryEntry(is); - int loadSize = is.readInt(); - for (int i = 0; i < loadSize; ++i) { - entries.add(new HistoryEntry(is)); - } - pos = entries.size(); - } - - void doWrite(DataOutputStream os) throws IOException { - aboveTop.save(os); - os.writeInt(entries.size()); - for (HistoryEntry entry : entries) { - entry.save(os); - } - } - - private HistoryEntry currentEntry() { - if (pos < entries.size()) { - return entries.get(pos); - } else { - return aboveTop; - } - } - - int getListPos() { - return entries.size() - 1 - pos; - } - - boolean onEnter(String text, String result) { - if (result == null) { - result = ""; - } - currentEntry().onEnter(); - pos = entries.size(); - if (text.length() == 0) { - return false; - } - if (entries.size() > 0) { - HistoryEntry top = entries.get(entries.size()-1); - if (text.equals(top.line) && result.equals(top.result)) { - return false; - } - } - if (entries.size() > SIZE_LIMIT) { - entries.remove(0); - } - entries.add(new HistoryEntry(text, result)); - pos = entries.size(); - return true; - } - - void moveToPos(int listPos, String text) { - currentEntry().editLine = text; - pos = entries.size() - listPos - 1; - } - - void updateEdited(String text) { - currentEntry().editLine = text; - } - - boolean moveUp(String text) { - updateEdited(text); - if (pos >= entries.size()) { - return false; - } - ++pos; - return true; - } - - boolean moveDown(String text) { - updateEdited(text); - if (pos <= 0) { - return false; - } - --pos; - return true; - } - - String getText() { - return currentEntry().editLine; - } -} diff --git a/android-app/src/main/java/arity/calculator/HistoryEntry.java b/android-app/src/main/java/arity/calculator/HistoryEntry.java deleted file mode 100755 index 7a6079ef..00000000 --- a/android-app/src/main/java/arity/calculator/HistoryEntry.java +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (C) 2009 Mihai Preda - -package arity.calculator; - -import java.io.*; - -class HistoryEntry { - String line, editLine, result; - - HistoryEntry(DataInputStream is) throws IOException { - line = is.readUTF(); - editLine = is.readUTF(); - if (editLine.length() == 0) { - editLine = line; - } - result = is.readUTF(); - } - - HistoryEntry(String text, String result) { - line = text; - editLine = text; - this.result = result == null ? "" : result; - } - - void save(DataOutputStream os) throws IOException { - os.writeUTF(line); - os.writeUTF(editLine.equals(line) ? "" : editLine); - os.writeUTF(result); - } - - void onEnter() { - editLine = line; - } -} diff --git a/android-app/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java b/android-app/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java index adb76513..1aa1cfcd 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java @@ -64,6 +64,7 @@ public class CalculatorActivity extends SherlockFragmentActivity implements Shar activityHelper.addTab(this, CalculatorFragmentType.variables, null, R.id.main_second_pane); activityHelper.addTab(this, CalculatorFragmentType.functions, null, R.id.main_second_pane); activityHelper.addTab(this, CalculatorFragmentType.operators, null, R.id.main_second_pane); + activityHelper.addTab(this, CalculatorFragmentType.plotter_functions, null, R.id.main_second_pane); activityHelper.addTab(this, CalculatorPlotActivity.getPlotterFragmentType(), null, R.id.main_second_pane); activityHelper.addTab(this, CalculatorFragmentType.faq, null, R.id.main_second_pane); } else { diff --git a/android-app/src/main/java/org/solovyev/android/calculator/CalculatorActivityLauncher.java b/android-app/src/main/java/org/solovyev/android/calculator/CalculatorActivityLauncher.java index 6de8517f..45ec9bc5 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/CalculatorActivityLauncher.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/CalculatorActivityLauncher.java @@ -21,11 +21,15 @@ import org.solovyev.android.calculator.about.CalculatorAboutActivity; import org.solovyev.android.calculator.function.FunctionEditDialogFragment; import org.solovyev.android.calculator.help.CalculatorHelpActivity; import org.solovyev.android.calculator.history.CalculatorHistoryActivity; -import org.solovyev.android.calculator.math.edit.*; +import org.solovyev.android.calculator.math.edit.CalculatorFunctionsActivity; +import org.solovyev.android.calculator.math.edit.CalculatorOperatorsActivity; +import org.solovyev.android.calculator.math.edit.CalculatorVarsActivity; +import org.solovyev.android.calculator.math.edit.CalculatorVarsFragment; +import org.solovyev.android.calculator.math.edit.VarEditDialogFragment; import org.solovyev.android.calculator.matrix.CalculatorMatrixActivity; -import org.solovyev.android.calculator.plot.AbstractCalculatorPlotFragment; import org.solovyev.android.calculator.plot.CalculatorPlotActivity; import org.solovyev.android.calculator.plot.CalculatorPlotFragment; +import org.solovyev.android.calculator.plot.ParcelablePlotInput; import org.solovyev.android.calculator.plot.PlotInput; import org.solovyev.common.msg.Message; import org.solovyev.common.msg.MessageType; @@ -106,7 +110,7 @@ public final class CalculatorActivityLauncher implements CalculatorEventListener @Nullable Constant yVariable){ final Intent intent = new Intent(); intent.putExtra(ChartFactory.TITLE, context.getString(R.string.c_graph)); - final AbstractCalculatorPlotFragment.Input input = new CalculatorPlotFragment.Input(generic.toString(), xVariable == null ? null : xVariable.getName(), yVariable == null ? null : yVariable.getName()); + final ParcelablePlotInput input = new ParcelablePlotInput(generic.toString(), xVariable == null ? null : xVariable.getName(), yVariable == null ? null : yVariable.getName()); intent.putExtra(CalculatorPlotFragment.INPUT, input); intent.setClass(context, CalculatorPlotActivity.class); AndroidUtils2.addFlags(intent, false, context); diff --git a/android-app/src/main/java/org/solovyev/android/calculator/CalculatorListFragment.java b/android-app/src/main/java/org/solovyev/android/calculator/CalculatorListFragment.java new file mode 100644 index 00000000..e5a0bfa5 --- /dev/null +++ b/android-app/src/main/java/org/solovyev/android/calculator/CalculatorListFragment.java @@ -0,0 +1,88 @@ +package org.solovyev.android.calculator; + +import android.app.Activity; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import com.actionbarsherlock.app.SherlockListFragment; +import org.jetbrains.annotations.NotNull; +import org.solovyev.android.calculator.about.CalculatorFragmentType; + +/** + * User: Solovyev_S + * Date: 03.10.12 + * Time: 14:18 + */ +public abstract class CalculatorListFragment extends SherlockListFragment { + + @NotNull + private final CalculatorFragmentHelper fragmentHelper; + + protected CalculatorListFragment(int layoutResId, int titleResId) { + fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(layoutResId, titleResId); + } + + protected CalculatorListFragment(@NotNull CalculatorFragmentType fragmentType) { + fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(fragmentType.getDefaultLayoutId(), fragmentType.getDefaultTitleResId()); + } + + protected CalculatorListFragment(@NotNull CalculatorFragmentHelper fragmentHelper) { + this.fragmentHelper = fragmentHelper; + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + fragmentHelper.onCreate(this); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return fragmentHelper.onCreateView(this, inflater, container); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + fragmentHelper.onViewCreated(this, view); + } + + @Override + public void onResume() { + super.onResume(); + + this.fragmentHelper.onResume(this); + } + + @Override + public void onPause() { + this.fragmentHelper.onPause(this); + + super.onPause(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + } + + @Override + public void onDestroy() { + fragmentHelper.onDestroy(this); + super.onDestroy(); + } + + @Override + public void onDetach() { + super.onDetach(); + } +} + diff --git a/android-app/src/main/java/org/solovyev/android/calculator/about/CalculatorFragmentType.java b/android-app/src/main/java/org/solovyev/android/calculator/about/CalculatorFragmentType.java index 2f48afdb..8cbe9267 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/about/CalculatorFragmentType.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/about/CalculatorFragmentType.java @@ -15,6 +15,7 @@ import org.solovyev.android.calculator.math.edit.CalculatorVarsFragment; import org.solovyev.android.calculator.matrix.CalculatorMatrixEditFragment; import org.solovyev.android.calculator.plot.CalculatorArityPlotFragment; import org.solovyev.android.calculator.plot.CalculatorPlotFragment; +import org.solovyev.android.calculator.plot.CalculatorPlotFunctionsFragment; /** * User: Solovyev_S @@ -33,6 +34,9 @@ public enum CalculatorFragmentType { operators(CalculatorOperatorsFragment.class, R.layout.math_entities_fragment, R.string.c_operators), plotter(CalculatorPlotFragment.class, R.layout.plot_fragment, R.string.c_graph), plotter_2(CalculatorArityPlotFragment.class, R.layout.plot_fragment, R.string.c_graph), + + // todo serso: strings + plotter_functions(CalculatorPlotFunctionsFragment.class, R.layout.plot_functions_fragment, R.string.c_graph), about(CalculatorAboutFragment.class, R.layout.about_fragment, R.string.c_about), faq(CalculatorHelpFaqFragment.class, R.layout.help_faq_fragment, R.string.c_faq), hints(CalculatorHelpHintsFragment.class, R.layout.help_hints_fragment, R.string.c_hints), diff --git a/android-app/src/main/java/org/solovyev/android/calculator/plot/AbstractCalculatorPlotFragment.java b/android-app/src/main/java/org/solovyev/android/calculator/plot/AbstractCalculatorPlotFragment.java index 68ad6236..b7840d33 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/plot/AbstractCalculatorPlotFragment.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/plot/AbstractCalculatorPlotFragment.java @@ -17,7 +17,20 @@ import jscl.text.ParseException; import org.achartengine.renderer.XYMultipleSeriesRenderer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.*; +import org.solovyev.android.calculator.CalculatorApplication; +import org.solovyev.android.calculator.CalculatorDisplayChangeEventData; +import org.solovyev.android.calculator.CalculatorDisplayViewState; +import org.solovyev.android.calculator.CalculatorEventData; +import org.solovyev.android.calculator.CalculatorEventHolder; +import org.solovyev.android.calculator.CalculatorEventListener; +import org.solovyev.android.calculator.CalculatorEventType; +import org.solovyev.android.calculator.CalculatorFragment; +import org.solovyev.android.calculator.CalculatorParseException; +import org.solovyev.android.calculator.CalculatorUtils; +import org.solovyev.android.calculator.Locator; +import org.solovyev.android.calculator.PreparedExpression; +import org.solovyev.android.calculator.R; +import org.solovyev.android.calculator.ToJsclTextProcessor; import org.solovyev.android.menu.ActivityMenu; import org.solovyev.android.menu.IdentifiableMenuItem; import org.solovyev.android.menu.ListActivityMenu; @@ -46,7 +59,7 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment protected static final String TAG = "CalculatorPlotFragment"; - public static final String INPUT = "plotter_input"; + public static final String INPUT = "plot_input"; protected static final String PLOT_BOUNDARIES = "plot_boundaries"; @@ -63,7 +76,7 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment */ @Nullable - private Input input; + private ParcelablePlotInput input; private int bgColor; @@ -97,7 +110,7 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment final Bundle arguments = getArguments(); if (arguments != null) { - input = (CalculatorPlotFragment.Input) arguments.getSerializable(INPUT); + input = (ParcelablePlotInput) arguments.getParcelable(INPUT); } if (input == null) { @@ -303,7 +316,7 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment yVariable = null; } - final Input input = new Input(expression.toString(), xVariable == null ? null : xVariable.getName(), yVariable == null ? null : yVariable.getName()); + final ParcelablePlotInput input = new ParcelablePlotInput(expression.toString(), xVariable == null ? null : xVariable.getName(), yVariable == null ? null : yVariable.getName()); return prepareInput(input, false, savedInstanceState); } } @@ -315,7 +328,7 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment } @NotNull - private static PreparedInput prepareInput(@NotNull Input input, boolean fromInputArgs, @Nullable Bundle savedInstanceState) { + private static PreparedInput prepareInput(@NotNull ParcelablePlotInput input, boolean fromInputArgs, @Nullable Bundle savedInstanceState) { PreparedInput result; try { @@ -437,7 +450,7 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment public static class PreparedInput { @Nullable - private Input input; + private ParcelablePlotInput input; @Nullable private Generic expression; @@ -459,7 +472,7 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment } @NotNull - public static PreparedInput newInstance(@NotNull Input input, + public static PreparedInput newInstance(@NotNull ParcelablePlotInput input, @NotNull Generic expression, @Nullable Constant xVariable, @Nullable Constant yVariable, @@ -506,7 +519,7 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment } @Nullable - public Input getInput() { + public ParcelablePlotInput getInput() { return input; } @@ -539,38 +552,4 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment } } - public static class Input implements Serializable { - - @NotNull - private String expression; - - @Nullable - private String xVariableName; - - @Nullable - private String yVariableName; - - public Input(@NotNull String expression, - @Nullable String xVariableName, - @Nullable String yVariableName) { - this.expression = expression; - this.xVariableName = xVariableName; - this.yVariableName = yVariableName; - } - - @NotNull - public String getExpression() { - return expression; - } - - @Nullable - public String getXVariableName() { - return xVariableName; - } - - @Nullable - public String getYVariableName() { - return yVariableName; - } - } } diff --git a/android-app/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotFunctionsController.java b/android-app/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotFunctionsController.java new file mode 100644 index 00000000..3825f721 --- /dev/null +++ b/android-app/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotFunctionsController.java @@ -0,0 +1,37 @@ +package org.solovyev.android.calculator.plot; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +final class CalculatorPlotFunctionsController { + + @NotNull + private static final CalculatorPlotFunctionsController instance = new CalculatorPlotFunctionsController(); + + @NotNull + private final List functions = new ArrayList(); + + private CalculatorPlotFunctionsController() { + } + + @NotNull + public static CalculatorPlotFunctionsController getInstance() { + return instance; + } + + @NotNull + public List getFunctions() { + return Collections.unmodifiableList(functions); + } + + public boolean addFunction(@NotNull ParcelablePlotInput function) { + if (!functions.contains(function)) { + return functions.add(function); + } else { + return false; + } + } +} diff --git a/android-app/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotFunctionsFragment.java b/android-app/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotFunctionsFragment.java new file mode 100644 index 00000000..9e395bb7 --- /dev/null +++ b/android-app/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotFunctionsFragment.java @@ -0,0 +1,35 @@ +package org.solovyev.android.calculator.plot; + +import com.google.common.base.Function; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; +import org.solovyev.android.calculator.CalculatorListFragment; +import org.solovyev.android.calculator.about.CalculatorFragmentType; +import org.solovyev.android.list.ListItemArrayAdapter; + +import javax.annotation.Nullable; +import java.util.List; + +public class CalculatorPlotFunctionsFragment extends CalculatorListFragment { + + @NotNull + public static final String INPUT = "plot_input"; + + public CalculatorPlotFunctionsFragment() { + super(CalculatorFragmentType.plotter_functions); + } + + @Override + public void onResume() { + super.onResume(); + + final List items = Lists.transform(CalculatorPlotFunctionsController.getInstance().getFunctions(), new Function() { + @Override + public ParcelablePlotInputListItem apply(@Nullable ParcelablePlotInput input) { + return new ParcelablePlotInputListItem(input); + } + }); + + ListItemArrayAdapter.createAndAttach(getListView(), this.getActivity(), items); + } +} diff --git a/core/src/main/java/org/solovyev/common/ListMapper.java b/core/src/main/java/org/solovyev/common/ListMapper.java new file mode 100644 index 00000000..ff448c64 --- /dev/null +++ b/core/src/main/java/org/solovyev/common/ListMapper.java @@ -0,0 +1,35 @@ +package org.solovyev.common; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.common.text.CollectionTransformations; +import org.solovyev.common.text.Mapper; + +import java.util.List; + +public class ListMapper implements Mapper> { + + @NotNull + private final Mapper nestedMapper; + + private ListMapper(@NotNull Mapper nestedMapper) { + this.nestedMapper = nestedMapper; + } + + @NotNull + private static Mapper> newInstance(@NotNull Mapper nestedMapper) { + return new ListMapper(nestedMapper); + } + + @Nullable + @Override + public String formatValue(@Nullable List value) throws IllegalArgumentException { + return CollectionTransformations.formatValue(value, ";", nestedMapper); + } + + @Nullable + @Override + public List parseValue(@Nullable String value) throws IllegalArgumentException { + return CollectionTransformations.split(value, ";", nestedMapper); + } +}