diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f16cdb54..844c8d54 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -21,17 +21,22 @@
+ a:label="@string/c_app_settings"
+ a:configChanges="orientation|keyboardHidden"/>
+ a:label="@string/c_app_history"
+ a:configChanges="orientation|keyboardHidden">
+
+ a:label="@string/c_about"
+ a:configChanges="orientation|keyboardHidden"/>
+ a:configChanges="orientation|keyboardHidden">
+
\ No newline at end of file
diff --git a/res/layout-land/main.xml b/res/layout-land/main.xml
index 81c635c3..06014743 100644
--- a/res/layout-land/main.xml
+++ b/res/layout-land/main.xml
@@ -73,7 +73,7 @@
-
+
@@ -85,7 +85,7 @@
-
+
@@ -93,12 +93,11 @@
-
-
+
diff --git a/res/layout-port/main.xml b/res/layout-port/main.xml
index 47c6a53d..fb94f8ec 100644
--- a/res/layout-port/main.xml
+++ b/res/layout-port/main.xml
@@ -17,15 +17,9 @@
-
-
+ a:layout_height="match_parent"/>
diff --git a/res/menu/history_menu.xml b/res/menu/history_menu.xml
new file mode 100644
index 00000000..d092ef2f
--- /dev/null
+++ b/res/menu/history_menu.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 6a7c99f2..c7268b3c 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -82,5 +82,5 @@
Точность результата(все вычисления производятся максимально точно)
Включает/выключает подсветку синтаксиса в поле редактирования калькулятора
Устанавливает тему оформления приложения
-
+ Очистить историю
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f61e1a53..a275833a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -82,4 +82,5 @@
Precision of result value (all calculations are done with maximum precision regardless of the value of this option)
Enables/disables colouring and styling in calculator editor
Sets the theme for calculator
+ Clear history
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java b/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
index 07f9fd17..4d816ba0 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
@@ -67,6 +67,8 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
// ids of drag buttons in R.class
private List 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();
}
}
\ No newline at end of file
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorDisplayHistoryState.java b/src/main/java/org/solovyev/android/calculator/CalculatorDisplayHistoryState.java
index da058f3e..a4dcf0c7 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorDisplayHistoryState.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorDisplayHistoryState.java
@@ -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 +
+ '}';
+ }
}
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorEditor.java b/src/main/java/org/solovyev/android/calculator/CalculatorEditor.java
index 2eebe0a8..5f21212c 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorEditor.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorEditor.java
@@ -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();
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorHistory.java b/src/main/java/org/solovyev/android/calculator/CalculatorHistory.java
index 0aaa110f..af285c06 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorHistory.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorHistory.java
@@ -75,4 +75,9 @@ public enum CalculatorHistory implements HistoryHelper {
public List getStates() {
return historyHelper.getStates();
}
+
+ @Override
+ public void clear() {
+ this.historyHelper.clear();
+ }
}
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorHistoryActivity.java b/src/main/java/org/solovyev/android/calculator/CalculatorHistoryActivity.java
index 788a4ba3..32f9975b 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorHistoryActivity.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorHistoryActivity.java
@@ -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();
+ }
}
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorHistoryState.java b/src/main/java/org/solovyev/android/calculator/CalculatorHistoryState.java
index 545d2b02..7fe27eea 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorHistoryState.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorHistoryState.java
@@ -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 +
+ '}';
+ }
}
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorView.java b/src/main/java/org/solovyev/android/calculator/CalculatorView.java
index 9b115868..70072f74 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorView.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorView.java
@@ -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 currentRunner = new MutableObject();
+ 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 pendingOperation = new MutableObject();
+
+ 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 integerNumberMapper = new NumberMapper(Integer.class);
//noinspection ConstantConditions
this.setNumberOfFractionDigits(integerNumberMapper.parseValue(preferences.getString(RESULT_PRECISION_P_KEY, RESULT_PRECISION_DEFAULT)));
}
- varsRegister.init(context);
+ varsRegister.init(context, preferences);
}
}
diff --git a/src/main/java/org/solovyev/android/calculator/model/VarsRegisterImpl.java b/src/main/java/org/solovyev/android/calculator/model/VarsRegisterImpl.java
index 2d15524d..bd5fd353 100644
--- a/src/main/java/org/solovyev/android/calculator/model/VarsRegisterImpl.java
+++ b/src/main/java/org/solovyev/android/calculator/model/VarsRegisterImpl.java
@@ -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();
diff --git a/src/test/java/org/solovyev/android/calculator/math/MathTypeTest.java b/src/test/java/org/solovyev/android/calculator/math/MathTypeTest.java
index 9d128782..bef479fd 100644
--- a/src/test/java/org/solovyev/android/calculator/math/MathTypeTest.java
+++ b/src/test/java/org/solovyev/android/calculator/math/MathTypeTest.java
@@ -20,7 +20,7 @@ public class MathTypeTest {
@BeforeClass
public static void setUp() throws Exception {
- CalculatorModel.instance.init(null);
+ CalculatorModel.instance.init(null, null);
}
@Test
diff --git a/src/test/java/org/solovyev/android/calculator/model/CalculatorModelTest.java b/src/test/java/org/solovyev/android/calculator/model/CalculatorModelTest.java
index 2fb5266e..1b8fac85 100644
--- a/src/test/java/org/solovyev/android/calculator/model/CalculatorModelTest.java
+++ b/src/test/java/org/solovyev/android/calculator/model/CalculatorModelTest.java
@@ -21,7 +21,7 @@ public class CalculatorModelTest {
@BeforeClass
public static void setUp() throws Exception {
- CalculatorModel.instance.init(null);
+ CalculatorModel.instance.init(null, null);
}
@Test
diff --git a/src/test/java/org/solovyev/android/calculator/model/ToJsclTextProcessorTest.java b/src/test/java/org/solovyev/android/calculator/model/ToJsclTextProcessorTest.java
index b2bfb204..7685a1b4 100644
--- a/src/test/java/org/solovyev/android/calculator/model/ToJsclTextProcessorTest.java
+++ b/src/test/java/org/solovyev/android/calculator/model/ToJsclTextProcessorTest.java
@@ -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