diff --git a/res/values/strings.xml b/res/values/strings.xml
index bd24f1e3..b5c123d4 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -269,5 +269,26 @@ Check the \'Round result\' preference in application settings - it should be tur
+ Arithmetic error occurred: {0}
+ Too complex expression
+ Too long execution time - check the expression
+ Evaluation was cancelled
+ No parameters are specified for function: {0}
+ Infinite loop is detected in expression
+
+ Premature end of processing
+ There is no operator with name: {0}
+ Operator name is not valid: {0}
+ Postfix function with name {0} doesn\'\'t exist
+ Constant name must start with character
+ Cannot be implicit function - usual function or operator with same name is defined: {0}
+ Digit is expected
+ Invalid number: {0}
+ First letter of number must be digit
+ Expected characters are {0} or {1}
+ Expected characters are {0}
+ Expected character is {0}
+ Function name is not valid: {0}
+ Expected number of parameters differs from actual {0}
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java b/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
index 6cd3f3fc..22f10133 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
@@ -22,13 +22,14 @@ import android.view.*;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
-import jscl.AngleUnits;
+import jscl.AngleUnit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.msg.AndroidMessageRegistry;
import org.solovyev.android.view.FontSizeAdjuster;
+import org.solovyev.android.view.prefs.ResourceCache;
import org.solovyev.android.view.widgets.*;
import org.solovyev.common.BooleanMapper;
import org.solovyev.common.utils.Announcer;
@@ -38,7 +39,10 @@ import org.solovyev.common.utils.history.HistoryAction;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.DecimalFormatSymbols;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
public class CalculatorActivity extends Activity implements FontSizeAdjuster, SharedPreferences.OnSharedPreferenceChangeListener {
@@ -58,12 +62,6 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
@NotNull
private String layoutName;
- // ids of drag buttons in R.class
- private List dragButtonIds = null;
-
- // ids of buttons in R.class
- private List buttonIds = null;
-
@Nullable
private Vibrator vibrator;
@@ -82,6 +80,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
super.onCreate(savedInstanceState);
setLayout(preferences);
+ ResourceCache.instance.initCaptions(R.string.class, this);
firstTimeInit(preferences);
vibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE);
@@ -150,7 +149,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
if ( directionText != null ) {
try {
- final AngleUnits angleUnits = AngleUnits.valueOf(directionText);
+ final AngleUnit angleUnits = AngleUnit.valueOf(directionText);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(CalculatorActivity.this);
final SharedPreferences.Editor editor = preferences.edit();
@@ -214,7 +213,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
private synchronized void setOnDragListeners(@NotNull SimpleOnDragListener.Preferences dragPreferences, @NotNull SharedPreferences preferences) {
final OnDragListener onDragListener = new OnDragListenerVibrator(newOnDragListener(new DigitButtonDragProcessor(calculatorModel), dragPreferences), vibrator, preferences);
- for (Integer dragButtonId : dragButtonIds) {
+ for (Integer dragButtonId : ResourceCache.instance.getDragButtonIds()) {
((DragButton) findViewById(dragButtonId)).setOnDragListener(onDragListener);
}
}
@@ -288,26 +287,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
private synchronized void firstTimeInit(@NotNull SharedPreferences preferences) {
if (!initialized) {
- dragButtonIds = new ArrayList();
- buttonIds = new ArrayList();
-
- for (Field field : R.id.class.getDeclaredFields()) {
- int modifiers = field.getModifiers();
- if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) {
- try {
- int viewId = field.getInt(R.id.class);
- final View view = findViewById(viewId);
- if (view instanceof DragButton) {
- dragButtonIds.add(viewId);
- }
- if (view instanceof Button) {
- buttonIds.add(viewId);
- }
- } catch (IllegalAccessException e) {
- Log.e(CalculatorActivity.class.getName(), e.getMessage());
- }
- }
- }
+ ResourceCache.instance.init(R.id.class, this);
CalculatorEngine.instance.init(this, preferences);
initialized = true;
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorDisplay.java b/src/main/java/org/solovyev/android/calculator/CalculatorDisplay.java
index 9ff202c7..662018cb 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorDisplay.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorDisplay.java
@@ -11,6 +11,7 @@ import android.text.Html;
import android.util.AttributeSet;
import android.util.Log;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.model.ParseException;
import org.solovyev.android.calculator.model.TextProcessor;
@@ -25,6 +26,9 @@ public class CalculatorDisplay extends AutoResizeTextView {
private boolean valid = true;
+ @Nullable
+ private String errorMessage;
+
@NotNull
private JsclOperation jsclOperation = JsclOperation.numeric;
@@ -49,6 +53,18 @@ public class CalculatorDisplay extends AutoResizeTextView {
public void setValid(boolean valid) {
this.valid = valid;
+ if (valid) {
+ errorMessage = null;
+ }
+ }
+
+ @Nullable
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setErrorMessage(@Nullable String errorMessage) {
+ this.errorMessage = errorMessage;
}
public void setJsclOperation(@NotNull JsclOperation jsclOperation) {
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorDisplayHistoryState.java b/src/main/java/org/solovyev/android/calculator/CalculatorDisplayHistoryState.java
index 8b059c72..d3fd0b81 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorDisplayHistoryState.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorDisplayHistoryState.java
@@ -6,6 +6,7 @@
package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.jscl.JsclOperation;
/**
@@ -17,6 +18,9 @@ public class CalculatorDisplayHistoryState {
private boolean valid = true;
+ @Nullable
+ private String errorMessage = null;
+
@NotNull
private EditorHistoryState editorHistoryState;
@@ -33,6 +37,7 @@ public class CalculatorDisplayHistoryState {
result.editorHistoryState = EditorHistoryState.newInstance(display);
result.valid = display.isValid();
result.jsclOperation = display.getJsclOperation();
+ result.errorMessage = display.getErrorMessage();
return result;
}
@@ -51,6 +56,11 @@ public class CalculatorDisplayHistoryState {
return jsclOperation;
}
+ @Nullable
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -60,6 +70,7 @@ public class CalculatorDisplayHistoryState {
if (valid != that.valid) return false;
if (!editorHistoryState.equals(that.editorHistoryState)) return false;
+ if (errorMessage != null ? !errorMessage.equals(that.errorMessage) : that.errorMessage != null) return false;
if (jsclOperation != that.jsclOperation) return false;
return true;
@@ -68,6 +79,7 @@ public class CalculatorDisplayHistoryState {
@Override
public int hashCode() {
int result = (valid ? 1 : 0);
+ result = 31 * result + (errorMessage != null ? errorMessage.hashCode() : 0);
result = 31 * result + editorHistoryState.hashCode();
result = 31 * result + jsclOperation.hashCode();
return result;
@@ -77,8 +89,9 @@ public class CalculatorDisplayHistoryState {
public String toString() {
return "CalculatorDisplayHistoryState{" +
"valid=" + valid +
- "jsclOperation=" + jsclOperation +
+ ", errorMessage='" + errorMessage + '\'' +
", editorHistoryState=" + editorHistoryState +
+ ", jsclOperation=" + jsclOperation +
'}';
}
}
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorModel.java b/src/main/java/org/solovyev/android/calculator/CalculatorModel.java
index 50091873..c2d2fb79 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorModel.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorModel.java
@@ -6,6 +6,7 @@
package org.solovyev.android.calculator;
import android.app.Activity;
+import android.app.AlertDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
@@ -63,7 +64,17 @@ public enum CalculatorModel implements CursorControl, HistoryControl {
result = createResultForComplexNumber(result.replace(MathType.IMAGINARY_NUMBER_JSCL, MathType.IMAGINARY_NUMBER));
} catch (NumberFormatException e1) {
// throw original one
- throw new ParseException(e);
+ throw new ParseException(new jscl.text.ParseException(Messages.msg_8, 0, result, result));
}
}
diff --git a/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java b/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java
index 19565aeb..8b2560d4 100644
--- a/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java
+++ b/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java
@@ -7,7 +7,7 @@ package org.solovyev.android.calculator.model;
import android.content.Context;
import android.content.SharedPreferences;
-import jscl.AngleUnits;
+import jscl.AngleUnit;
import jscl.JsclMathEngine;
import jscl.MathEngine;
import jscl.math.function.Function;
@@ -191,13 +191,13 @@ public enum CalculatorEngine {
calculationResult.setObject(finalOperation.evaluate(jsclExpression));
} catch (ArithmeticException e) {
//System.out.println(e.getMessage());
- exception.setObject(new ParseException(e.getMessage(), e));
+ exception.setObject(new ParseException(Messages.msg_1, jsclExpression, e.getMessage()));
} catch (StackOverflowError e) {
//System.out.println(StringUtils.fromStackTrace(e.getStackTrace()));
- exception.setObject(new ParseException(e.getMessage(), e));
+ exception.setObject(new ParseException(Messages.msg_2, jsclExpression));
} catch (jscl.text.ParseException e) {
//System.out.println(e.getMessage());
- exception.setObject(new ParseException(e.getMessage(), e));
+ exception.setObject(new ParseException(e));
} catch (ParseInterruptedException e) {
//System.out.println(e.getMessage());
// do nothing - we ourselves interrupt the calculations
@@ -232,11 +232,11 @@ public enum CalculatorEngine {
}
if (calculationResultLocal == null) {
- throw new ParseException("Too long calculation for: " + jsclExpression);
+ throw new ParseException(Messages.msg_3, jsclExpression);
}
} catch (InterruptedException e) {
- throw new ParseException(e);
+ throw new ParseException(Messages.msg_4, jsclExpression);
}
result = String.valueOf(calculationResult.getObject()).trim();
@@ -274,7 +274,7 @@ public enum CalculatorEngine {
//noinspection ConstantConditions
this.setPrecision(integerNumberMapper.parseValue(preferences.getString(RESULT_PRECISION_P_KEY, RESULT_PRECISION_DEFAULT)));
this.setRoundResult(preferences.getBoolean(ROUND_RESULT_P_KEY, ROUND_RESULT_DEFAULT));
- this.setDefaultAngleUnits(AngleUnits.valueOf(preferences.getString(ANGLE_UNITS_P_KEY, ANGLE_UNITS_DEFAULT)));
+ this.setDefaultAngleUnits(AngleUnit.valueOf(preferences.getString(ANGLE_UNITS_P_KEY, ANGLE_UNITS_DEFAULT)));
final String groupingSeparator = preferences.getString(GROUPING_SEPARATOR_P_KEY, GROUPING_SEPARATOR_DEFAULT);
if (StringUtils.isEmpty(groupingSeparator)) {
@@ -326,8 +326,8 @@ public enum CalculatorEngine {
this.timeout = timeout;
}
- public void setDefaultAngleUnits(@NotNull AngleUnits angleUnits) {
- getEngine().setDefaultAngleUnits(angleUnits);
+ public void setDefaultAngleUnits(@NotNull AngleUnit angleUnits) {
+ getEngine().setDefaultAngleUnit(angleUnits);
}
// for tests only
diff --git a/src/main/java/org/solovyev/android/calculator/model/Messages.java b/src/main/java/org/solovyev/android/calculator/model/Messages.java
new file mode 100644
index 00000000..d97b0b95
--- /dev/null
+++ b/src/main/java/org/solovyev/android/calculator/model/Messages.java
@@ -0,0 +1,34 @@
+package org.solovyev.android.calculator.model;
+
+/**
+ * User: serso
+ * Date: 11/25/11
+ * Time: 1:40 PM
+ */
+public final class Messages {
+
+
+ // not intended for instantiation
+ private Messages() {
+ throw new AssertionError();
+ }
+
+ /** Arithmetic error occurred: {0} */
+ public static final String msg_1 = "msg_1";
+
+ /** Too complex expression */
+ public static final String msg_2 = "msg_2";
+
+ /** Too long execution time - check the expression */
+ public static final String msg_3 = "msg_3";
+
+ /** Evaluation was cancelled */
+ public static final String msg_4 = "msg_4";
+
+ /** No parameters are specified for function: {0} */
+ public static final String msg_5 = "msg_5";
+
+ /** Infinite loop is detected in expression */
+ public static final String msg_6 = "msg_6";
+
+}
diff --git a/src/main/java/org/solovyev/android/calculator/model/ParseException.java b/src/main/java/org/solovyev/android/calculator/model/ParseException.java
index d886f54d..b39fdb3a 100644
--- a/src/main/java/org/solovyev/android/calculator/model/ParseException.java
+++ b/src/main/java/org/solovyev/android/calculator/model/ParseException.java
@@ -6,27 +6,94 @@
package org.solovyev.android.calculator.model;
+import android.content.Context;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.solovyev.android.view.prefs.ResourceCache;
import org.solovyev.common.exceptions.SersoException;
+import org.solovyev.common.utils.CollectionsUtils;
+
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
/**
-* User: serso
-* Date: 10/6/11
-* Time: 9:25 PM
-*/
+ * User: serso
+ * Date: 10/6/11
+ * Time: 9:25 PM
+ */
public class ParseException extends SersoException {
- public ParseException() {
+ @NotNull
+ private final String messageId;
+
+ @NotNull
+ private final List