From 0e98409103f5ece721013bd00cf942875adfdb89 Mon Sep 17 00:00:00 2001 From: serso Date: Sun, 16 Oct 2011 15:11:33 +0400 Subject: [PATCH] fixes --- AndroidManifest.xml | 13 ++- res/layout-land/main.xml | 7 +- res/layout-port/main.xml | 8 +- res/menu/history_menu.xml | 14 +++ res/values-ru/strings.xml | 2 +- res/values/strings.xml | 1 + .../calculator/CalculatorActivity.java | 72 ++++++++------ .../CalculatorDisplayHistoryState.java | 8 ++ .../android/calculator/CalculatorEditor.java | 5 + .../android/calculator/CalculatorHistory.java | 5 + .../calculator/CalculatorHistoryActivity.java | 36 ++++++- .../calculator/CalculatorHistoryState.java | 8 ++ .../android/calculator/CalculatorView.java | 96 +++++++++++-------- .../calculator/EditorHistoryState.java | 8 ++ .../calculator/model/CalculatorModel.java | 14 +-- .../calculator/model/VarsRegisterImpl.java | 6 +- .../android/calculator/math/MathTypeTest.java | 2 +- .../calculator/model/CalculatorModelTest.java | 2 +- .../model/ToJsclTextProcessorTest.java | 3 +- 19 files changed, 205 insertions(+), 105 deletions(-) create mode 100644 res/menu/history_menu.xml 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