operators activity added

This commit is contained in:
Sergey Solovyev 2011-11-17 14:55:43 +04:00
parent 637c339e8c
commit 4d679ddb80
18 changed files with 228 additions and 36 deletions

View File

@ -42,6 +42,11 @@
a:configChanges="orientation|keyboardHidden"> a:configChanges="orientation|keyboardHidden">
</activity> </activity>
<activity a:name=".CalculatorOperatorsActivity"
a:label="@string/c_operators"
a:configChanges="orientation|keyboardHidden">
</activity>
<activity a:name=".CalculatorVarsActivity" <activity a:name=".CalculatorVarsActivity"
a:label="@string/c_vars_and_constants" a:label="@string/c_vars_and_constants"
a:configChanges="orientation|keyboardHidden"> a:configChanges="orientation|keyboardHidden">

View File

@ -99,7 +99,7 @@
<include layout="@layout/calc_six_digit_button"/> <include layout="@layout/calc_six_digit_button"/>
<include layout="@layout/calc_plus_button"/> <include layout="@layout/calc_plus_button"/>
<include layout="@layout/calc_subtraction_button"/> <include layout="@layout/calc_subtraction_button"/>
<include layout="@layout/calc_empty_button"/> <include layout="@layout/calc_operators_button"/>
</LinearLayout> </LinearLayout>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2009-2011. Created by serso aka se.solovyev.
~ For more information, please, contact se.solovyev@gmail.com
~ or visit http://se.solovyev.org
-->
<org.solovyev.android.view.widgets.DirectionDragButton xmlns:a="http://schemas.android.com/apk/res/android"
a:id="@+id/functionsButton"
a:text="∂,∫"
a:textStyle="italic"
a:onClick="operatorsButtonClickHandler"
style="?controlButtonStyle"/>

20
res/layout/operators.xml Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2009-2011. Created by serso aka se.solovyev.
~ For more information, please, contact se.solovyev@gmail.com
~ or visit http://se.solovyev.org
-->
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:orientation="vertical"
a:layout_width="fill_parent"
a:layout_height="fill_parent">
<ListView
a:layout_width="fill_parent"
a:layout_height="fill_parent"
a:layout_weight="1"
a:id="@android:id/list"/>
</LinearLayout>

View File

@ -145,5 +145,6 @@
<string name="c_empty_var_error">Невозможно создать пустую константу!</string> <string name="c_empty_var_error">Невозможно создать пустую константу!</string>
<string name="c_not_valid_result">Результат не допустим!</string> <string name="c_not_valid_result">Результат не допустим!</string>
<string name="c_operators">Операторы</string>
</resources> </resources>

View File

@ -146,5 +146,6 @@
<string name="c_empty_var_error">Unable to create empty constant!</string> <string name="c_empty_var_error">Unable to create empty constant!</string>
<string name="c_not_valid_result">Current result is not valid!</string> <string name="c_not_valid_result">Current result is not valid!</string>
<string name="c_operators">Operators</string>
</resources> </resources>

View File

@ -333,6 +333,11 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
CalculatorActivityLauncher.showFunctions(this); CalculatorActivityLauncher.showFunctions(this);
} }
@SuppressWarnings({"UnusedDeclaration"})
public void operatorsButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showOperators(this);
}
@SuppressWarnings({"UnusedDeclaration"}) @SuppressWarnings({"UnusedDeclaration"})
public void varsButtonClickHandler(@NotNull View v) { public void varsButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showVars(this); CalculatorActivityLauncher.showVars(this);

View File

@ -29,6 +29,10 @@ public class CalculatorActivityLauncher {
context.startActivity(new Intent(context, CalculatorFunctionsActivity.class)); 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) { public static void showVars(@NotNull final Context context) {
context.startActivity(new Intent(context, CalculatorVarsActivity.class)); context.startActivity(new Intent(context, CalculatorVarsActivity.class));
} }

View File

@ -265,6 +265,10 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
textToBeInserted.append("()"); textToBeInserted.append("()");
cursorPositionOffset = -1; cursorPositionOffset = -1;
break; break;
case operator:
textToBeInserted.append("()");
cursorPositionOffset = -1;
break;
} }
if (cursorPositionOffset == 0) { if (cursorPositionOffset == 0) {

View File

@ -0,0 +1,110 @@
package org.solovyev.android.calculator;
import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import jscl.math.function.Function;
import jscl.math.operator.Operator;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.common.utils.StringUtils;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
* User: serso
* Date: 11/17/11
* Time: 1:53 PM
*/
public class CalculatorOperatorsActivity extends ListActivity {
@NotNull
private OperatorsArrayAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.operators);
adapter = new OperatorsArrayAdapter(this, R.layout.var, R.id.var_text, new ArrayList<Operator>(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<Operator>() {
@Override
public int compare(Operator operator1, Operator operator2) {
return operator1.getName().compareTo(operator2.getName());
}
});
CalculatorOperatorsActivity.this.adapter.notifyDataSetChanged();
}
private class OperatorsArrayAdapter extends ArrayAdapter<Operator> {
private OperatorsArrayAdapter(Context context, int resource, int textViewResourceId, List<Operator> 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;
}
}
}

View File

@ -104,6 +104,7 @@ public class TextHighlighter implements TextProcessor<TextHighlighter.Result> {
numberOfOpenGroupSymbols--; numberOfOpenGroupSymbols--;
text1.append(text.charAt(i)); text1.append(text.charAt(i));
break; break;
case operator:
case function: case function:
i = processHighlightedText(text1, i, mathType.getMatch(), "i"); i = processHighlightedText(text1, i, mathType.getMatch(), "i");
break; break;

View File

@ -68,7 +68,7 @@ public enum MathType {
open_group_symbol(800, true, false, "[", "(", "{") { open_group_symbol(800, true, false, "[", "(", "{") {
@Override @Override
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) { public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != function; return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != function && mathTypeBefore != operator;
} }
@Override @Override
@ -97,6 +97,14 @@ public enum MathType {
} }
}, },
operator(1050, true, true) {
@NotNull
@Override
public List<String> getTokens() {
return CalculatorEngine.instance.getOperatorsRegistry().getNames();
}
},
constant(1100, true, true) { constant(1100, true, true) {
@NotNull @NotNull
@Override @Override

View File

@ -10,6 +10,7 @@ import android.content.Context;
import jscl.math.function.Function; import jscl.math.function.Function;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.common.math.MathEntity;
import org.solovyev.common.math.MathRegistry; import org.solovyev.common.math.MathRegistry;
/** /**
@ -17,7 +18,7 @@ import org.solovyev.common.math.MathRegistry;
* Date: 10/30/11 * Date: 10/30/11
* Time: 1:02 AM * Time: 1:02 AM
*/ */
public interface AndroidFunctionsRegistry extends MathRegistry<Function> { public interface AndroidMathRegistry<T extends MathEntity> extends MathRegistry<T> {
@Nullable @Nullable
String getDescription(@NotNull Context context, @NotNull String functionName); String getDescription(@NotNull Context context, @NotNull String functionName);

View File

@ -13,6 +13,7 @@ import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.RClassUtils; import org.solovyev.android.calculator.RClassUtils;
import org.solovyev.common.definitions.IBuilder; import org.solovyev.common.definitions.IBuilder;
import org.solovyev.common.math.MathEntity;
import org.solovyev.common.math.MathRegistry; import org.solovyev.common.math.MathRegistry;
import java.util.List; import java.util.List;
@ -23,15 +24,15 @@ import java.util.Map;
* Date: 10/30/11 * Date: 10/30/11
* Time: 1:03 AM * Time: 1:03 AM
*/ */
public class AndroidFunctionsRegistryImpl implements AndroidFunctionsRegistry { public class AndroidMathRegistryImpl<T extends MathEntity> implements AndroidMathRegistry<T> {
@NotNull @NotNull
private static final String FUNCTION_DESCRIPTION_PREFIX = "c_fun_description_"; private static final String FUNCTION_DESCRIPTION_PREFIX = "c_fun_description_";
@NotNull @NotNull
private final MathRegistry<Function> functionsRegistry; private final MathRegistry<T> functionsRegistry;
public AndroidFunctionsRegistryImpl(@NotNull MathRegistry<Function> functionsRegistry) { public AndroidMathRegistryImpl(@NotNull MathRegistry<T> functionsRegistry) {
this.functionsRegistry = functionsRegistry; this.functionsRegistry = functionsRegistry;
} }
@ -60,23 +61,23 @@ public class AndroidFunctionsRegistryImpl implements AndroidFunctionsRegistry {
@NotNull @NotNull
@Override @Override
public List<Function> getEntities() { public List<T> getEntities() {
return functionsRegistry.getEntities(); return functionsRegistry.getEntities();
} }
@NotNull @NotNull
@Override @Override
public List<Function> getSystemEntities() { public List<T> getSystemEntities() {
return functionsRegistry.getSystemEntities(); return functionsRegistry.getSystemEntities();
} }
@Override @Override
public Function add(@NotNull IBuilder<? extends Function> IBuilder) { public T add(@NotNull IBuilder<? extends T> IBuilder) {
return functionsRegistry.add(IBuilder); return functionsRegistry.add(IBuilder);
} }
@Override @Override
public void remove(@NotNull Function var) { public void remove(@NotNull T var) {
functionsRegistry.remove(var); functionsRegistry.remove(var);
} }
@ -92,12 +93,12 @@ public class AndroidFunctionsRegistryImpl implements AndroidFunctionsRegistry {
} }
@Override @Override
public Function get(@NotNull String name) { public T get(@NotNull String name) {
return functionsRegistry.get(name); return functionsRegistry.get(name);
} }
@Override @Override
public Function getById(@NotNull Integer id) { public T getById(@NotNull Integer id) {
return functionsRegistry.getById(id); return functionsRegistry.getById(id);
} }
} }

View File

@ -70,7 +70,10 @@ public enum CalculatorEngine {
private final AndroidVarsRegistry varsRegister = new AndroidVarsRegistryImpl(engine.getConstantsRegistry()); private final AndroidVarsRegistry varsRegister = new AndroidVarsRegistryImpl(engine.getConstantsRegistry());
@NotNull @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<Operator> postfixFunctionsRegistry = engine.getPostfixFunctionsRegistry(); private final MathRegistry<Operator> postfixFunctionsRegistry = engine.getPostfixFunctionsRegistry();
@ -156,7 +159,7 @@ public enum CalculatorEngine {
sb.append(preparedExpression); sb.append(preparedExpression);
//Log.d(CalculatorEngine.class.getName(), "Preprocessed expression: " + preprocessedExpression); //Log.d(CalculatorEngine.class.getName(), "Preprocessed expression: " + preprocessedExpression);
if (operation == JsclOperation.numeric && preparedExpression.isExistsUndefinedVar()) { /*if (operation == JsclOperation.numeric && preparedExpression.isExistsUndefinedVar()) {
operation = JsclOperation.simplify; operation = JsclOperation.simplify;
if (mr != null) { if (mr != null) {
@ -169,7 +172,7 @@ public enum CalculatorEngine {
mr.addMessage(new AndroidMessage(R.string.c_simplify_instead_of_numeric, MessageType.info, undefinedVars)); mr.addMessage(new AndroidMessage(R.string.c_simplify_instead_of_numeric, MessageType.info, undefinedVars));
} }
} }*/
final String jsclExpression = sb.toString(); final String jsclExpression = sb.toString();
final JsclOperation finalOperation = operation; final JsclOperation finalOperation = operation;
@ -224,6 +227,9 @@ public enum CalculatorEngine {
} }
if ( evalErrorLocal != null ) { if ( evalErrorLocal != null ) {
if ( finalOperation == JsclOperation.numeric && preparedExpression.isExistsUndefinedVar() ) {
return evaluate(JsclOperation.simplify, expression, mr);
}
throw evalErrorLocal; throw evalErrorLocal;
} }
@ -301,10 +307,15 @@ public enum CalculatorEngine {
} }
@NotNull @NotNull
public AndroidFunctionsRegistry getFunctionsRegistry() { public AndroidMathRegistry getFunctionsRegistry() {
return functionsRegistry; return functionsRegistry;
} }
@NotNull
public AndroidMathRegistry getOperatorsRegistry() {
return operatorsRegistry;
}
@NotNull @NotNull
public MathRegistry<Operator> getPostfixFunctionsRegistry() { public MathRegistry<Operator> getPostfixFunctionsRegistry() {
return postfixFunctionsRegistry; return postfixFunctionsRegistry;

View File

@ -62,7 +62,7 @@ public class FromJsclSimplifyTextProcessor implements TextProcessor<String> {
} }
} else { } 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()); sb.append(mathType.getMatch());
i += mathType.getMatch().length() - 1; i += mathType.getMatch().length() - 1;
} else { } else {

View File

@ -54,7 +54,7 @@ class ToJsclTextProcessor implements TextProcessor<PreparedExpression> {
} }
} }
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()); throw new ParseException("Empty function: " + mathTypeResult.getMatch());
} }
@ -80,28 +80,34 @@ class ToJsclTextProcessor implements TextProcessor<PreparedExpression> {
int offset = 0; int offset = 0;
String functionName = CollectionsUtils.find(MathType.function.getTokens(), startsWithFinder); String functionName = CollectionsUtils.find(MathType.function.getTokens(), startsWithFinder);
if (functionName == null) { if (functionName == null) {
String varName = CollectionsUtils.find(CalculatorEngine.instance.getVarsRegister().getNames(), startsWithFinder); String operatorName = CollectionsUtils.find(MathType.operator.getTokens(), startsWithFinder);
if (varName != null) { if (operatorName == null) {
final Var var = CalculatorEngine.instance.getVarsRegister().get(varName); String varName = CollectionsUtils.find(CalculatorEngine.instance.getVarsRegister().getNames(), startsWithFinder);
if (var != null) { if (varName != null) {
if (!var.isDefined()) { final Var var = CalculatorEngine.instance.getVarsRegister().get(varName);
undefinedVars.add(var); if (var != null) {
result.append(varName); if (!var.isDefined()) {
offset = varName.length(); undefinedVars.add(var);
} 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
result.append(varName); result.append(varName);
offset = varName.length();
} else { } 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 { } else {
result.append(functionName); result.append(functionName);

View File

@ -113,7 +113,7 @@ public class CalculatorEngineTest {
junit.framework.Assert.assertEquals("36.0", Expression.valueOf("3!^2").numeric().toString()); junit.framework.Assert.assertEquals("36.0", Expression.valueOf("3!^2").numeric().toString());
junit.framework.Assert.assertEquals("3.0", Expression.valueOf("cubic(27)").numeric().toString()); junit.framework.Assert.assertEquals("3.0", Expression.valueOf("cubic(27)").numeric().toString());
try { try {
junit.framework.Assert.assertEquals("i", cm.evaluate(JsclOperation.numeric, "i!").getResult()); junit.framework.Assert.assertEquals("√(-1)!", cm.evaluate(JsclOperation.numeric, "i!").getResult());
fail(); fail();
} catch (ParseException e) { } catch (ParseException e) {
} }