fixes
This commit is contained in:
@@ -67,6 +67,8 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
||||
// ids of drag buttons in R.class
|
||||
private List<Integer> dragButtonIds = null;
|
||||
|
||||
@NotNull
|
||||
private final static Object broadcastReceiverLock = new Object();
|
||||
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
@@ -83,7 +85,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
||||
|
||||
firstTimeInit();
|
||||
|
||||
init();
|
||||
init(preferences);
|
||||
|
||||
dpclRegister.clear();
|
||||
|
||||
@@ -100,9 +102,9 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
||||
((DragButton) findViewById(R.id.leftButton)).setOnDragListener(toPositionOnDragListener);
|
||||
dpclRegister.addListener(toPositionOnDragListener);
|
||||
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
CalculatorModel.instance.reset(this, preferences);
|
||||
|
||||
this.onSharedPreferenceChanged(preferences, null);
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
private synchronized void setOnDragListeners(@NotNull SimpleOnDragListener.Preferences dragPreferences) {
|
||||
@@ -164,33 +166,40 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
||||
setTheme(styleId);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
private void init(@NotNull SharedPreferences preferences) {
|
||||
|
||||
calculatorView = new CalculatorView(this, CalculatorModel.instance);
|
||||
synchronized (broadcastReceiverLock) {
|
||||
calculatorView = new CalculatorView(this, preferences, CalculatorModel.instance);
|
||||
}
|
||||
|
||||
textReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (INSERT_TEXT_INTENT.equals(intent.getAction())) {
|
||||
final String s = intent.getStringExtra(INSERT_TEXT_INTENT_EXTRA_STRING);
|
||||
if (!StringUtils.isEmpty(s)) {
|
||||
calculatorView.doTextOperation(new CalculatorView.TextOperation() {
|
||||
@Override
|
||||
public void doOperation(@NotNull EditText editor) {
|
||||
editor.getText().insert(editor.getSelectionStart(), s);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (SET_TEXT_INTENT.equals(intent.getAction())) {
|
||||
final String s = intent.getStringExtra(SET_TEXT_INTENT_EXTRA_STRING);
|
||||
if (!StringUtils.isEmpty(s)) {
|
||||
calculatorView.doTextOperation(new CalculatorView.TextOperation() {
|
||||
@Override
|
||||
public void doOperation(@NotNull EditText editor) {
|
||||
editor.setText(s);
|
||||
calculatorView.setCursorOnEnd();
|
||||
}
|
||||
});
|
||||
synchronized (broadcastReceiverLock) {
|
||||
Log.d(this.getClass().getName(), "Intent received: " + intent.getAction());
|
||||
if (INSERT_TEXT_INTENT.equals(intent.getAction())) {
|
||||
final String s = intent.getStringExtra(INSERT_TEXT_INTENT_EXTRA_STRING);
|
||||
Log.d(this.getClass().getName(), "Extra data: " + s);
|
||||
if (!StringUtils.isEmpty(s)) {
|
||||
calculatorView.doTextOperation(new CalculatorView.TextOperation() {
|
||||
@Override
|
||||
public void doOperation(@NotNull EditText editor) {
|
||||
editor.getText().insert(editor.getSelectionStart(), s);
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
} else if (SET_TEXT_INTENT.equals(intent.getAction())) {
|
||||
final String s = intent.getStringExtra(SET_TEXT_INTENT_EXTRA_STRING);
|
||||
Log.d(this.getClass().getName(), "Extra data: " + s);
|
||||
if (!StringUtils.isEmpty(s)) {
|
||||
calculatorView.doTextOperation(new CalculatorView.TextOperation() {
|
||||
@Override
|
||||
public void doOperation(@NotNull EditText editor) {
|
||||
editor.setText(s);
|
||||
calculatorView.setCursorOnEnd();
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,7 +212,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
||||
private synchronized void firstTimeInit() {
|
||||
if (!initialized) {
|
||||
try {
|
||||
CalculatorModel.instance.init(this);
|
||||
CalculatorModel.instance.init(this, PreferenceManager.getDefaultSharedPreferences(this));
|
||||
} catch (EvalError evalError) {
|
||||
throw new RuntimeException("Could not initialize interpreter!");
|
||||
}
|
||||
@@ -409,22 +418,27 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
||||
super.onResume();
|
||||
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
final String newThemeName = preferences.getString(getString(R.string.p_calc_theme_key), getString(R.string.p_calc_theme));
|
||||
if (!newThemeName.equals(themeName)) {
|
||||
restart();
|
||||
}
|
||||
|
||||
synchronized (broadcastReceiverLock) {
|
||||
calculatorView = new CalculatorView(this, preferences, CalculatorModel.instance);
|
||||
}
|
||||
|
||||
this.calculatorView.evaluate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences preferences, @Nullable String s) {
|
||||
dpclRegister.announce().onDragPreferencesChange(SimpleOnDragListener.getPreferences(preferences, this));
|
||||
|
||||
CalculatorModel.instance.reset(this);
|
||||
CalculatorModel.instance.reset(this, preferences);
|
||||
|
||||
final Boolean colorExpressionsInBracketsDefault = new BooleanMapper().parseValue(this.getString(R.string.p_calc_color_display));
|
||||
assert colorExpressionsInBracketsDefault != null;
|
||||
this.calculatorView.getEditor().setHighlightText(preferences.getBoolean(this.getString(R.string.p_calc_color_display_key), colorExpressionsInBracketsDefault));
|
||||
|
||||
this.calculatorView.evaluate();
|
||||
}
|
||||
}
|
@@ -67,4 +67,12 @@ public class CalculatorDisplayHistoryState {
|
||||
result = 31 * result + (editorHistoryState != null ? editorHistoryState.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CalculatorDisplayHistoryState{" +
|
||||
"valid=" + valid +
|
||||
", editorHistoryState=" + editorHistoryState +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@@ -53,6 +53,11 @@ public class CalculatorEditor extends EditText {
|
||||
menu.removeItem(android.R.id.startSelectingText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(CharSequence text, BufferType type) {
|
||||
super.setText(text, type);
|
||||
}
|
||||
|
||||
public synchronized void redraw() {
|
||||
String text = getText().toString();
|
||||
|
||||
|
@@ -75,4 +75,9 @@ public enum CalculatorHistory implements HistoryHelper<CalculatorHistoryState> {
|
||||
public List<CalculatorHistoryState> getStates() {
|
||||
return historyHelper.getStates();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.historyHelper.clear();
|
||||
}
|
||||
}
|
||||
|
@@ -10,12 +10,13 @@ import android.app.ListActivity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.*;
|
||||
import android.widget.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.common.utils.*;
|
||||
import org.solovyev.common.utils.Filter;
|
||||
import org.solovyev.common.utils.FilterRule;
|
||||
import org.solovyev.common.utils.FilterRulesChain;
|
||||
import org.solovyev.common.utils.StringUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
@@ -103,4 +104,33 @@ public class CalculatorHistoryActivity extends ListActivity {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
final MenuInflater menuInflater = getMenuInflater();
|
||||
menuInflater.inflate(R.menu.history_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
boolean result;
|
||||
|
||||
switch (item.getItemId()) {
|
||||
case R.id.history_menu_clear_history:
|
||||
clearHistory();
|
||||
result = true;
|
||||
break;
|
||||
default:
|
||||
result = super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void clearHistory() {
|
||||
CalculatorHistory.instance.clear();
|
||||
Toast.makeText(this, R.string.c_history_is_empty, Toast.LENGTH_SHORT).show();
|
||||
this.finish();
|
||||
}
|
||||
}
|
||||
|
@@ -43,4 +43,12 @@ public class CalculatorHistoryState extends AbstractHistoryState{
|
||||
public void setDisplayState(@NotNull CalculatorDisplayHistoryState displayState) {
|
||||
this.displayState = displayState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CalculatorHistoryState{" +
|
||||
"editorState=" + editorState +
|
||||
", displayState=" + displayState +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@ package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Handler;
|
||||
import android.text.ClipboardManager;
|
||||
import android.util.Log;
|
||||
@@ -22,6 +23,7 @@ import org.solovyev.android.calculator.model.CalculatorModel;
|
||||
import org.solovyev.android.calculator.model.ParseException;
|
||||
import org.solovyev.android.view.CursorControl;
|
||||
import org.solovyev.android.view.HistoryControl;
|
||||
import org.solovyev.common.BooleanMapper;
|
||||
import org.solovyev.common.utils.MutableObject;
|
||||
import org.solovyev.common.utils.StringUtils;
|
||||
import org.solovyev.common.utils.history.HistoryAction;
|
||||
@@ -45,11 +47,15 @@ public class CalculatorView implements CursorControl, HistoryControl<CalculatorH
|
||||
@NotNull
|
||||
private final CalculatorModel calculatorModel;
|
||||
|
||||
public CalculatorView(@NotNull final Activity activity, @NotNull CalculatorModel calculator) {
|
||||
public CalculatorView(@NotNull final Activity activity, @NotNull SharedPreferences preferences, @NotNull CalculatorModel calculator) {
|
||||
this.calculatorModel = calculator;
|
||||
|
||||
this.editor = (CalculatorEditor) activity.findViewById(R.id.calculatorEditor);
|
||||
|
||||
final Boolean colorExpressionsInBracketsDefault = new BooleanMapper().parseValue(activity.getString(R.string.p_calc_color_display));
|
||||
assert colorExpressionsInBracketsDefault != null;
|
||||
this.editor.setHighlightText(preferences.getBoolean(activity.getString(R.string.p_calc_color_display_key), colorExpressionsInBracketsDefault));
|
||||
|
||||
this.display = (CalculatorDisplay) activity.findViewById(R.id.calculatorDisplay);
|
||||
this.display.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
@@ -60,7 +66,7 @@ public class CalculatorView implements CursorControl, HistoryControl<CalculatorH
|
||||
|
||||
|
||||
final CalculatorHistoryState lastState = CalculatorHistory.instance.getLastHistoryState();
|
||||
if ( lastState == null ) {
|
||||
if (lastState == null) {
|
||||
saveHistoryState();
|
||||
} else {
|
||||
setCurrentHistoryState(lastState);
|
||||
@@ -83,7 +89,6 @@ public class CalculatorView implements CursorControl, HistoryControl<CalculatorH
|
||||
CalculatorHistory.instance.addState(getCurrentHistoryState());
|
||||
}
|
||||
|
||||
|
||||
public void setCursorOnStart() {
|
||||
editor.setSelection(0);
|
||||
}
|
||||
@@ -104,61 +109,75 @@ public class CalculatorView implements CursorControl, HistoryControl<CalculatorH
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private final MutableObject<Runnable> currentRunner = new MutableObject<Runnable>();
|
||||
public void doTextOperation(@NotNull TextOperation operation) {
|
||||
doTextOperation(operation, true);
|
||||
}
|
||||
|
||||
public synchronized void doTextOperation(@NotNull TextOperation operation) {
|
||||
public void doTextOperation(@NotNull TextOperation operation, boolean delayEvaluate) {
|
||||
final String editorStateBefore = this.editor.getText().toString();
|
||||
|
||||
operation.doOperation(this.editor);
|
||||
//Log.d(CalculatorView.class.getName(), "Doing text operation" + StringUtils.fromStackTrace(Thread.currentThread().getStackTrace()));
|
||||
|
||||
final String editorStateAfter = this.editor.getText().toString();
|
||||
if (!editorStateBefore.equals(editorStateAfter)) {
|
||||
|
||||
editor.redraw();
|
||||
|
||||
currentRunner.setObject(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// allow only one runner at one time
|
||||
synchronized (currentRunner) {
|
||||
//lock all operations with history
|
||||
synchronized (CalculatorHistory.instance) {
|
||||
// do only if nothing was post delayed before current instance was posted
|
||||
if (currentRunner.getObject() == this) {
|
||||
// actually nothing shall be logged while text operations are done
|
||||
evaluate(editorStateAfter);
|
||||
|
||||
if (CalculatorHistory.instance.isUndoAvailable()) {
|
||||
CalculatorHistory.instance.undo(getCurrentHistoryState());
|
||||
}
|
||||
|
||||
saveHistoryState();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
new Handler().postDelayed(currentRunner.getObject(), EVAL_DELAY_MILLIS);
|
||||
|
||||
saveHistoryState();
|
||||
evaluate(delayEvaluate, editorStateAfter);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private final static MutableObject<Runnable> pendingOperation = new MutableObject<Runnable>();
|
||||
|
||||
private void evaluate(boolean delayEvaluate, @NotNull final String expression) {
|
||||
final CalculatorHistoryState historyState = getCurrentHistoryState();
|
||||
|
||||
pendingOperation.setObject(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// allow only one runner at one time
|
||||
synchronized (pendingOperation) {
|
||||
//lock all operations with history
|
||||
if (pendingOperation.getObject() == this) {
|
||||
// actually nothing shall be logged while text operations are done
|
||||
evaluate(expression);
|
||||
|
||||
historyState.setDisplayState(getCurrentHistoryState().getDisplayState());
|
||||
|
||||
pendingOperation.setObject(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (delayEvaluate) {
|
||||
CalculatorHistory.instance.addState(historyState);
|
||||
new Handler().postDelayed(pendingOperation.getObject(), EVAL_DELAY_MILLIS);
|
||||
} else {
|
||||
pendingOperation.getObject().run();
|
||||
CalculatorHistory.instance.addState(historyState);
|
||||
}
|
||||
}
|
||||
|
||||
public void evaluate() {
|
||||
evaluate(false, this.editor.getText().toString());
|
||||
}
|
||||
|
||||
private void evaluate(@Nullable final String expression) {
|
||||
final CalculatorDisplay localDisplay = display;
|
||||
if (!StringUtils.isEmpty(expression)) {
|
||||
|
||||
final CalculatorDisplay localDisplay = display;
|
||||
|
||||
try {
|
||||
Log.d(CalculatorView.class.getName(), "Trying to evaluate: " + expression);
|
||||
Log.d(CalculatorView.class.getName(), "Trying to evaluate: " + expression /*+ StringUtils.fromStackTrace(Thread.currentThread().getStackTrace())*/);
|
||||
localDisplay.setText(calculatorModel.evaluate(JsclOperation.numeric, expression));
|
||||
} catch (EvalError e) {
|
||||
handleEvaluationException(expression, localDisplay, e);
|
||||
} catch (ParseException e) {
|
||||
handleEvaluationException(expression, localDisplay, e);
|
||||
}
|
||||
} else {
|
||||
localDisplay.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,10 +195,6 @@ public class CalculatorView implements CursorControl, HistoryControl<CalculatorH
|
||||
}
|
||||
}
|
||||
|
||||
public void evaluate() {
|
||||
evaluate(editor.getText().toString());
|
||||
}
|
||||
|
||||
public void processDigitButtonAction(@Nullable final String text) {
|
||||
//Toast.makeText(CalculatorActivity.this, text, Toast.LENGTH_SHORT).show();
|
||||
|
||||
@@ -231,6 +246,7 @@ public class CalculatorView implements CursorControl, HistoryControl<CalculatorH
|
||||
@Override
|
||||
public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) {
|
||||
synchronized (CalculatorHistory.instance) {
|
||||
Log.d(this.getClass().getName(), "Saved history found: " + editorHistoryState);
|
||||
setValuesFromHistory(this.editor, editorHistoryState.getEditorState());
|
||||
setValuesFromHistory(this.display, editorHistoryState.getDisplayState());
|
||||
|
||||
|
@@ -58,4 +58,12 @@ public class EditorHistoryState {
|
||||
result = 31 * result + (text != null ? text.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EditorHistoryState{" +
|
||||
"cursorPosition=" + cursorPosition +
|
||||
", text='" + text + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@@ -7,14 +7,12 @@ package org.solovyev.android.calculator.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import bsh.EvalError;
|
||||
import bsh.Interpreter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.JsclOperation;
|
||||
import org.solovyev.common.NumberMapper;
|
||||
import org.solovyev.common.utils.MutableObject;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
@@ -68,24 +66,22 @@ public enum CalculatorModel {
|
||||
this.numberOfFractionDigits = numberOfFractionDigits;
|
||||
}
|
||||
|
||||
public void init(@Nullable Context context) throws EvalError {
|
||||
public void init(@Nullable Context context, @Nullable SharedPreferences preferences) throws EvalError {
|
||||
synchronized (lock) {
|
||||
reset(context);
|
||||
reset(context, preferences);
|
||||
resetInterpreter();
|
||||
}
|
||||
}
|
||||
|
||||
public void reset(@Nullable Context context) {
|
||||
public void reset(@Nullable Context context, @Nullable SharedPreferences preferences) {
|
||||
synchronized (lock) {
|
||||
if (context != null) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
if (preferences != null) {
|
||||
final NumberMapper<Integer> integerNumberMapper = new NumberMapper<Integer>(Integer.class);
|
||||
//noinspection ConstantConditions
|
||||
this.setNumberOfFractionDigits(integerNumberMapper.parseValue(preferences.getString(RESULT_PRECISION_P_KEY, RESULT_PRECISION_DEFAULT)));
|
||||
}
|
||||
|
||||
varsRegister.init(context);
|
||||
varsRegister.init(context, preferences);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -118,14 +118,12 @@ class VarsRegisterImpl implements VarsRegister {
|
||||
vars.addAll(result);
|
||||
}
|
||||
|
||||
synchronized void init(@Nullable Context context) {
|
||||
synchronized void init(@Nullable Context context, @Nullable SharedPreferences preferences) {
|
||||
|
||||
this.vars.clear();
|
||||
this.systemVars.clear();
|
||||
|
||||
if (context != null) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
if (context != null && preferences != null) {
|
||||
final String value = preferences.getString(context.getString(R.string.p_calc_vars), null);
|
||||
if (value != null) {
|
||||
final Serializer serializer = new Persister();
|
||||
|
@@ -20,7 +20,7 @@ public class MathTypeTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
CalculatorModel.instance.init(null);
|
||||
CalculatorModel.instance.init(null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -21,7 +21,7 @@ public class CalculatorModelTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
CalculatorModel.instance.init(null);
|
||||
CalculatorModel.instance.init(null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -9,7 +9,6 @@ package org.solovyev.android.calculator.model;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.solovyev.android.calculator.JsclOperation;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
@@ -20,7 +19,7 @@ public class ToJsclTextProcessorTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
CalculatorModel.instance.init(null);
|
||||
CalculatorModel.instance.init(null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Reference in New Issue
Block a user