This commit is contained in:
Sergey Solovyev 2013-01-09 18:21:11 +04:00
parent 8c172bbd8a
commit 7da93282d0
21 changed files with 497 additions and 811 deletions

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:a="http://schemas.android.com/apk/res/android"
a:layout_width="match_parent"
a:layout_height="wrap_content"/>

View File

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

View File

@ -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<FunctionLineDef> CREATOR = new Creator<FunctionLineDef>() {
@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);
}
}

View File

@ -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<ParcelablePlotInput> CREATOR = new Creator<ParcelablePlotInput>() {
@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;
}
}

View File

@ -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<TextView> 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());
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:id="@+id/main_fragment_layout"
style="?cpp_fragment_layout_style"
a:layout_width="match_parent"
a:layout_height="match_parent">
<TextView a:id="@+id/fragment_title"
a:layout_height="wrap_content"
a:layout_width="match_parent"
style="?cpp_fragment_title_style"/>
<include layout="@layout/ad"/>
<ListView style="?cpp_fragment_list_view_style"/>
</LinearLayout>

View File

@ -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<Function> graphedFunction;
static Defs defs;
private ArrayList<Function> auxFuncs = new ArrayList<Function>();
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);
}
}

View File

@ -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<String> lines = new ArrayList<String>();
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);
}
}

View File

@ -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;
}

View File

@ -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<HistoryEntry> entries = new ArrayList<HistoryEntry>();
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;
}
}

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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),

View File

@ -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;
}
}
}

View File

@ -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<ParcelablePlotInput> functions = new ArrayList<ParcelablePlotInput>();
private CalculatorPlotFunctionsController() {
}
@NotNull
public static CalculatorPlotFunctionsController getInstance() {
return instance;
}
@NotNull
public List<ParcelablePlotInput> getFunctions() {
return Collections.unmodifiableList(functions);
}
public boolean addFunction(@NotNull ParcelablePlotInput function) {
if (!functions.contains(function)) {
return functions.add(function);
} else {
return false;
}
}
}

View File

@ -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<ParcelablePlotInputListItem> items = Lists.transform(CalculatorPlotFunctionsController.getInstance().getFunctions(), new Function<ParcelablePlotInput, ParcelablePlotInputListItem>() {
@Override
public ParcelablePlotInputListItem apply(@Nullable ParcelablePlotInput input) {
return new ParcelablePlotInputListItem(input);
}
});
ListItemArrayAdapter.createAndAttach(getListView(), this.getActivity(), items);
}
}

View File

@ -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<T> implements Mapper<List<T>> {
@NotNull
private final Mapper<T> nestedMapper;
private ListMapper(@NotNull Mapper<T> nestedMapper) {
this.nestedMapper = nestedMapper;
}
@NotNull
private static <T> Mapper<List<T>> newInstance(@NotNull Mapper<T> nestedMapper) {
return new ListMapper<T>(nestedMapper);
}
@Nullable
@Override
public String formatValue(@Nullable List<T> value) throws IllegalArgumentException {
return CollectionTransformations.formatValue(value, ";", nestedMapper);
}
@Nullable
@Override
public List<T> parseValue(@Nullable String value) throws IllegalArgumentException {
return CollectionTransformations.split(value, ";", nestedMapper);
}
}