diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index dee85def..717d3dbe 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -42,6 +42,11 @@
a:configChanges="orientation|keyboardHidden">
+
+
+
diff --git a/res/layout-land/main_calculator.xml b/res/layout-land/main_calculator.xml
index 2390e6d9..5ea43f97 100644
--- a/res/layout-land/main_calculator.xml
+++ b/res/layout-land/main_calculator.xml
@@ -99,7 +99,7 @@
-
+
diff --git a/res/layout/calc_operators_button.xml b/res/layout/calc_operators_button.xml
new file mode 100644
index 00000000..ffb943fc
--- /dev/null
+++ b/res/layout/calc_operators_button.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/operators.xml b/res/layout/operators.xml
new file mode 100644
index 00000000..c0165d13
--- /dev/null
+++ b/res/layout/operators.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 522edd12..8c9534d2 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -145,5 +145,6 @@
Невозможно создать пустую константу!
Результат не допустим!
+ Операторы
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9ffadc12..a741d9cf 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -146,5 +146,6 @@
Unable to create empty constant!
Current result is not valid!
+ Operators
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java b/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
index 94e1cb6f..330cb048 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
@@ -333,6 +333,11 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
CalculatorActivityLauncher.showFunctions(this);
}
+ @SuppressWarnings({"UnusedDeclaration"})
+ public void operatorsButtonClickHandler(@NotNull View v) {
+ CalculatorActivityLauncher.showOperators(this);
+ }
+
@SuppressWarnings({"UnusedDeclaration"})
public void varsButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showVars(this);
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorActivityLauncher.java b/src/main/java/org/solovyev/android/calculator/CalculatorActivityLauncher.java
index d9a60845..23036374 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorActivityLauncher.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorActivityLauncher.java
@@ -29,6 +29,10 @@ public class CalculatorActivityLauncher {
context.startActivity(new Intent(context, CalculatorFunctionsActivity.class));
}
+ public static void showOperators(@NotNull final Context context) {
+ context.startActivity(new Intent(context, CalculatorOperatorsActivity.class));
+ }
+
public static void showVars(@NotNull final Context context) {
context.startActivity(new Intent(context, CalculatorVarsActivity.class));
}
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorModel.java b/src/main/java/org/solovyev/android/calculator/CalculatorModel.java
index 49f5ecb6..76c68d9d 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorModel.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorModel.java
@@ -265,6 +265,10 @@ public enum CalculatorModel implements CursorControl, HistoryControl(CalculatorEngine.instance.getOperatorsRegistry().getEntities()));
+ setListAdapter(adapter);
+
+ final ListView lv = getListView();
+ lv.setTextFilterEnabled(true);
+
+ lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ public void onItemClick(final AdapterView> parent,
+ final View view,
+ final int position,
+ final long id) {
+
+ CalculatorModel.instance.processDigitButtonAction(((Operator) parent.getItemAtPosition(position)).getName(), false);
+
+ CalculatorOperatorsActivity.this.finish();
+ }
+ });
+
+ sort();
+
+ }
+
+ private void sort() {
+ CalculatorOperatorsActivity.this.adapter.sort(new Comparator() {
+ @Override
+ public int compare(Operator operator1, Operator operator2) {
+ return operator1.getName().compareTo(operator2.getName());
+ }
+ });
+
+ CalculatorOperatorsActivity.this.adapter.notifyDataSetChanged();
+ }
+
+ private class OperatorsArrayAdapter extends ArrayAdapter {
+
+ private OperatorsArrayAdapter(Context context, int resource, int textViewResourceId, List objects) {
+ super(context, resource, textViewResourceId, objects);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ final ViewGroup result = (ViewGroup) super.getView(position, convertView, parent);
+
+ final Operator operator = getItem(position);
+
+ final String operatorDescription = CalculatorEngine.instance.getOperatorsRegistry().getDescription(getContext(), operator.getName());
+ if (!StringUtils.isEmpty(operatorDescription)) {
+ TextView description = (TextView) result.findViewById(R.id.var_description);
+ if (description == null) {
+ final LayoutInflater layoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
+ final ViewGroup itemView = (ViewGroup) layoutInflater.inflate(R.layout.var, null);
+ description = (TextView) itemView.findViewById(R.id.var_description);
+ itemView.removeView(description);
+ result.addView(description);
+ }
+ description.setText(operatorDescription);
+ } else {
+ TextView description = (TextView) result.findViewById(R.id.var_description);
+ if (description != null) {
+ result.removeView(description);
+ }
+ }
+
+
+ return result;
+ }
+ }
+
+
+}
+
diff --git a/src/main/java/org/solovyev/android/calculator/TextHighlighter.java b/src/main/java/org/solovyev/android/calculator/TextHighlighter.java
index dae13291..34ccca9e 100644
--- a/src/main/java/org/solovyev/android/calculator/TextHighlighter.java
+++ b/src/main/java/org/solovyev/android/calculator/TextHighlighter.java
@@ -104,6 +104,7 @@ public class TextHighlighter implements TextProcessor {
numberOfOpenGroupSymbols--;
text1.append(text.charAt(i));
break;
+ case operator:
case function:
i = processHighlightedText(text1, i, mathType.getMatch(), "i");
break;
diff --git a/src/main/java/org/solovyev/android/calculator/math/MathType.java b/src/main/java/org/solovyev/android/calculator/math/MathType.java
index 3a4cc2dd..0fd4da6b 100644
--- a/src/main/java/org/solovyev/android/calculator/math/MathType.java
+++ b/src/main/java/org/solovyev/android/calculator/math/MathType.java
@@ -68,7 +68,7 @@ public enum MathType {
open_group_symbol(800, true, false, "[", "(", "{") {
@Override
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
- return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != function;
+ return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != function && mathTypeBefore != operator;
}
@Override
@@ -97,6 +97,14 @@ public enum MathType {
}
},
+ operator(1050, true, true) {
+ @NotNull
+ @Override
+ public List getTokens() {
+ return CalculatorEngine.instance.getOperatorsRegistry().getNames();
+ }
+ },
+
constant(1100, true, true) {
@NotNull
@Override
diff --git a/src/main/java/org/solovyev/android/calculator/model/AndroidFunctionsRegistry.java b/src/main/java/org/solovyev/android/calculator/model/AndroidMathRegistry.java
similarity index 81%
rename from src/main/java/org/solovyev/android/calculator/model/AndroidFunctionsRegistry.java
rename to src/main/java/org/solovyev/android/calculator/model/AndroidMathRegistry.java
index d5f687db..70e762c5 100644
--- a/src/main/java/org/solovyev/android/calculator/model/AndroidFunctionsRegistry.java
+++ b/src/main/java/org/solovyev/android/calculator/model/AndroidMathRegistry.java
@@ -10,6 +10,7 @@ import android.content.Context;
import jscl.math.function.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.solovyev.common.math.MathEntity;
import org.solovyev.common.math.MathRegistry;
/**
@@ -17,7 +18,7 @@ import org.solovyev.common.math.MathRegistry;
* Date: 10/30/11
* Time: 1:02 AM
*/
-public interface AndroidFunctionsRegistry extends MathRegistry {
+public interface AndroidMathRegistry extends MathRegistry {
@Nullable
String getDescription(@NotNull Context context, @NotNull String functionName);
diff --git a/src/main/java/org/solovyev/android/calculator/model/AndroidFunctionsRegistryImpl.java b/src/main/java/org/solovyev/android/calculator/model/AndroidMathRegistryImpl.java
similarity index 79%
rename from src/main/java/org/solovyev/android/calculator/model/AndroidFunctionsRegistryImpl.java
rename to src/main/java/org/solovyev/android/calculator/model/AndroidMathRegistryImpl.java
index b4eb234c..5a362fc3 100644
--- a/src/main/java/org/solovyev/android/calculator/model/AndroidFunctionsRegistryImpl.java
+++ b/src/main/java/org/solovyev/android/calculator/model/AndroidMathRegistryImpl.java
@@ -13,6 +13,7 @@ import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.RClassUtils;
import org.solovyev.common.definitions.IBuilder;
+import org.solovyev.common.math.MathEntity;
import org.solovyev.common.math.MathRegistry;
import java.util.List;
@@ -23,15 +24,15 @@ import java.util.Map;
* Date: 10/30/11
* Time: 1:03 AM
*/
-public class AndroidFunctionsRegistryImpl implements AndroidFunctionsRegistry {
+public class AndroidMathRegistryImpl implements AndroidMathRegistry {
@NotNull
private static final String FUNCTION_DESCRIPTION_PREFIX = "c_fun_description_";
@NotNull
- private final MathRegistry functionsRegistry;
+ private final MathRegistry functionsRegistry;
- public AndroidFunctionsRegistryImpl(@NotNull MathRegistry functionsRegistry) {
+ public AndroidMathRegistryImpl(@NotNull MathRegistry functionsRegistry) {
this.functionsRegistry = functionsRegistry;
}
@@ -60,23 +61,23 @@ public class AndroidFunctionsRegistryImpl implements AndroidFunctionsRegistry {
@NotNull
@Override
- public List getEntities() {
+ public List getEntities() {
return functionsRegistry.getEntities();
}
@NotNull
@Override
- public List getSystemEntities() {
+ public List getSystemEntities() {
return functionsRegistry.getSystemEntities();
}
@Override
- public Function add(@NotNull IBuilder extends Function> IBuilder) {
+ public T add(@NotNull IBuilder extends T> IBuilder) {
return functionsRegistry.add(IBuilder);
}
@Override
- public void remove(@NotNull Function var) {
+ public void remove(@NotNull T var) {
functionsRegistry.remove(var);
}
@@ -92,12 +93,12 @@ public class AndroidFunctionsRegistryImpl implements AndroidFunctionsRegistry {
}
@Override
- public Function get(@NotNull String name) {
+ public T get(@NotNull String name) {
return functionsRegistry.get(name);
}
@Override
- public Function getById(@NotNull Integer id) {
+ public T getById(@NotNull Integer id) {
return functionsRegistry.getById(id);
}
}
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 a40fab6a..625e18ee 100644
--- a/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java
+++ b/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java
@@ -70,7 +70,10 @@ public enum CalculatorEngine {
private final AndroidVarsRegistry varsRegister = new AndroidVarsRegistryImpl(engine.getConstantsRegistry());
@NotNull
- private final AndroidFunctionsRegistry functionsRegistry = new AndroidFunctionsRegistryImpl(engine.getFunctionsRegistry());
+ private final AndroidMathRegistry functionsRegistry = new AndroidMathRegistryImpl(engine.getFunctionsRegistry());
+
+ @NotNull
+ private final AndroidMathRegistry operatorsRegistry = new AndroidMathRegistryImpl(engine.getOperatorsRegistry());
private final MathRegistry postfixFunctionsRegistry = engine.getPostfixFunctionsRegistry();
@@ -156,7 +159,7 @@ public enum CalculatorEngine {
sb.append(preparedExpression);
//Log.d(CalculatorEngine.class.getName(), "Preprocessed expression: " + preprocessedExpression);
- if (operation == JsclOperation.numeric && preparedExpression.isExistsUndefinedVar()) {
+ /*if (operation == JsclOperation.numeric && preparedExpression.isExistsUndefinedVar()) {
operation = JsclOperation.simplify;
if (mr != null) {
@@ -169,7 +172,7 @@ public enum CalculatorEngine {
mr.addMessage(new AndroidMessage(R.string.c_simplify_instead_of_numeric, MessageType.info, undefinedVars));
}
- }
+ }*/
final String jsclExpression = sb.toString();
final JsclOperation finalOperation = operation;
@@ -224,6 +227,9 @@ public enum CalculatorEngine {
}
if ( evalErrorLocal != null ) {
+ if ( finalOperation == JsclOperation.numeric && preparedExpression.isExistsUndefinedVar() ) {
+ return evaluate(JsclOperation.simplify, expression, mr);
+ }
throw evalErrorLocal;
}
@@ -301,10 +307,15 @@ public enum CalculatorEngine {
}
@NotNull
- public AndroidFunctionsRegistry getFunctionsRegistry() {
+ public AndroidMathRegistry getFunctionsRegistry() {
return functionsRegistry;
}
+ @NotNull
+ public AndroidMathRegistry getOperatorsRegistry() {
+ return operatorsRegistry;
+ }
+
@NotNull
public MathRegistry getPostfixFunctionsRegistry() {
return postfixFunctionsRegistry;
diff --git a/src/main/java/org/solovyev/android/calculator/model/FromJsclSimplifyTextProcessor.java b/src/main/java/org/solovyev/android/calculator/model/FromJsclSimplifyTextProcessor.java
index 58ab385a..feec68c0 100644
--- a/src/main/java/org/solovyev/android/calculator/model/FromJsclSimplifyTextProcessor.java
+++ b/src/main/java/org/solovyev/android/calculator/model/FromJsclSimplifyTextProcessor.java
@@ -62,7 +62,7 @@ public class FromJsclSimplifyTextProcessor implements TextProcessor {
}
} else {
- if (mathType.getMathType() == MathType.constant || mathType.getMathType() == MathType.function) {
+ if (mathType.getMathType() == MathType.constant || mathType.getMathType() == MathType.function || mathType.getMathType() == MathType.operator) {
sb.append(mathType.getMatch());
i += mathType.getMatch().length() - 1;
} else {
diff --git a/src/main/java/org/solovyev/android/calculator/model/ToJsclTextProcessor.java b/src/main/java/org/solovyev/android/calculator/model/ToJsclTextProcessor.java
index 209adea6..1d8a44fe 100644
--- a/src/main/java/org/solovyev/android/calculator/model/ToJsclTextProcessor.java
+++ b/src/main/java/org/solovyev/android/calculator/model/ToJsclTextProcessor.java
@@ -54,7 +54,7 @@ class ToJsclTextProcessor implements TextProcessor {
}
}
- if (mathTypeBefore == MathType.function && CollectionsUtils.find(MathType.openGroupSymbols, startsWithFinder) != null) {
+ if ((mathTypeBefore == MathType.function || mathTypeBefore == MathType.operator) && CollectionsUtils.find(MathType.openGroupSymbols, startsWithFinder) != null) {
throw new ParseException("Empty function: " + mathTypeResult.getMatch());
}
@@ -80,28 +80,34 @@ class ToJsclTextProcessor implements TextProcessor {
int offset = 0;
String functionName = CollectionsUtils.find(MathType.function.getTokens(), startsWithFinder);
if (functionName == null) {
- String varName = CollectionsUtils.find(CalculatorEngine.instance.getVarsRegister().getNames(), startsWithFinder);
- if (varName != null) {
- final Var var = CalculatorEngine.instance.getVarsRegister().get(varName);
- if (var != null) {
- if (!var.isDefined()) {
- undefinedVars.add(var);
- result.append(varName);
- offset = varName.length();
- } else {
- final String value = var.getValue();
- assert value != null;
-
- if ( var.getDoubleValue() != null ) {
- //result.append(value);
- // NOTE: append varName as JSCL engine will convert it to double if needed
+ String operatorName = CollectionsUtils.find(MathType.operator.getTokens(), startsWithFinder);
+ if (operatorName == null) {
+ String varName = CollectionsUtils.find(CalculatorEngine.instance.getVarsRegister().getNames(), startsWithFinder);
+ if (varName != null) {
+ final Var var = CalculatorEngine.instance.getVarsRegister().get(varName);
+ if (var != null) {
+ if (!var.isDefined()) {
+ undefinedVars.add(var);
result.append(varName);
+ offset = varName.length();
} else {
- result.append("(").append(processWithDepth(value, depth, undefinedVars)).append(")");
+ final String value = var.getValue();
+ assert value != null;
+
+ if ( var.getDoubleValue() != null ) {
+ //result.append(value);
+ // NOTE: append varName as JSCL engine will convert it to double if needed
+ result.append(varName);
+ } else {
+ result.append("(").append(processWithDepth(value, depth, undefinedVars)).append(")");
+ }
+ offset = varName.length();
}
- offset = varName.length();
}
}
+ } else {
+ result.append(operatorName);
+ offset = operatorName.length();
}
} else {
result.append(functionName);
diff --git a/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java b/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java
index b8e30ef8..58bf8ff3 100644
--- a/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java
+++ b/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java
@@ -113,7 +113,7 @@ public class CalculatorEngineTest {
junit.framework.Assert.assertEquals("36.0", Expression.valueOf("3!^2").numeric().toString());
junit.framework.Assert.assertEquals("3.0", Expression.valueOf("cubic(27)").numeric().toString());
try {
- junit.framework.Assert.assertEquals("i", cm.evaluate(JsclOperation.numeric, "i!").getResult());
+ junit.framework.Assert.assertEquals("√(-1)!", cm.evaluate(JsclOperation.numeric, "i!").getResult());
fail();
} catch (ParseException e) {
}