vars activity

This commit is contained in:
serso 2011-09-29 18:33:03 +04:00
parent 512e526713
commit 4306320cc1
11 changed files with 335 additions and 74 deletions

12
pom.xml
View File

@ -54,9 +54,15 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>de.congrace</groupId> <groupId>org.simpleframework</groupId>
<artifactId>exp4j</artifactId> <artifactId>simple-xml</artifactId>
<version>0.2.8</version> <version>2.6.1</version>
<exclusions>
<exclusion>
<artifactId>stax-api</artifactId>
<groupId>stax</groupId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -18,4 +18,6 @@
<string name="p_calc_color_display_key">org.solovyev.android.calculator.CalculatorModel_color_display</string> <string name="p_calc_color_display_key">org.solovyev.android.calculator.CalculatorModel_color_display</string>
<string name="p_calc_color_display">true</string> <string name="p_calc_color_display">true</string>
<string name="p_calc_vars">org.solovyev.android.calculator.CalculatorModel_vars</string>
</resources> </resources>

View File

@ -57,7 +57,8 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
setContentView(R.layout.main); setContentView(R.layout.main);
try { try {
this.calculatorModel = new CalculatorModel(); CalculatorModel.init(this);
this.calculatorModel = CalculatorModel.getInstance();
} catch (EvalError evalError) { } catch (EvalError evalError) {
// todo serso: create serso runtime exception // todo serso: create serso runtime exception
throw new RuntimeException("Could not initialize interpreter!"); throw new RuntimeException("Could not initialize interpreter!");
@ -258,8 +259,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, @Nullable String s) { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, @Nullable String s) {
dpclRegister.announce().onDragPreferencesChange(SimpleOnDragListener.getPreferences(CalculatorActivity.this)); dpclRegister.announce().onDragPreferencesChange(SimpleOnDragListener.getPreferences(CalculatorActivity.this));
final NumberMapper<Integer> integerNumberMapper = new NumberMapper<Integer>(Integer.class); this.calculatorModel.load(this);
this.calculatorModel.setNumberOfFractionDigits(integerNumberMapper.parseValue(sharedPreferences.getString(this.getString(R.string.p_calc_result_precision_key), this.getString(R.string.p_calc_result_precision))));
final Boolean colorExpressionsInBracketsDefault = new BooleanMapper().parseValue(this.getString(R.string.p_calc_color_display)); final Boolean colorExpressionsInBracketsDefault = new BooleanMapper().parseValue(this.getString(R.string.p_calc_color_display));
assert colorExpressionsInBracketsDefault != null; assert colorExpressionsInBracketsDefault != null;

View File

@ -5,9 +5,14 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import bsh.EvalError; import bsh.EvalError;
import bsh.Interpreter; import bsh.Interpreter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.common.NumberMapper;
import org.solovyev.common.exceptions.SersoException; import org.solovyev.common.exceptions.SersoException;
import org.solovyev.common.utils.MathUtils; import org.solovyev.common.utils.MathUtils;
import org.solovyev.util.math.Complex; import org.solovyev.util.math.Complex;
@ -21,16 +26,24 @@ import org.solovyev.util.math.Complex;
public class CalculatorModel { public class CalculatorModel {
@NotNull @NotNull
private Interpreter interpreter; private final Interpreter interpreter;
private int numberOfFractionDigits = 5; private int numberOfFractionDigits = 5;
@NotNull @NotNull
public Preprocessor preprocessor = new ToJsclPreprocessor(); public final Preprocessor preprocessor = new ToJsclPreprocessor();
@NotNull
private final VarsRegister varsRegister = new VarsRegister();
private static CalculatorModel instance;
private CalculatorModel(@Nullable Context context) throws EvalError {
if (context != null) {
load(context);
}
public CalculatorModel() throws EvalError {
interpreter = new Interpreter(); interpreter = new Interpreter();
interpreter.eval(ToJsclPreprocessor.wrap(JsclOperation.importCommands, "/jscl/editorengine/commands")); interpreter.eval(ToJsclPreprocessor.wrap(JsclOperation.importCommands, "/jscl/editorengine/commands"));
} }
@ -99,6 +112,15 @@ public class CalculatorModel {
return MathUtils.round(dResult, numberOfFractionDigits); return MathUtils.round(dResult, numberOfFractionDigits);
} }
public synchronized void load(@NotNull Context context) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
final NumberMapper<Integer> integerNumberMapper = new NumberMapper<Integer>(Integer.class);
this.setNumberOfFractionDigits(integerNumberMapper.parseValue(preferences.getString(context.getString(R.string.p_calc_result_precision_key), context.getString(R.string.p_calc_result_precision))));
varsRegister.load(context);
}
public static class ParseException extends SersoException { public static class ParseException extends SersoException {
public ParseException(Throwable cause) { public ParseException(Throwable cause) {
super(cause); super(cause);
@ -112,4 +134,25 @@ public class CalculatorModel {
public void setNumberOfFractionDigits(int numberOfFractionDigits) { public void setNumberOfFractionDigits(int numberOfFractionDigits) {
this.numberOfFractionDigits = numberOfFractionDigits; this.numberOfFractionDigits = numberOfFractionDigits;
} }
public static synchronized void init(@Nullable Context context) throws EvalError {
if ( instance == null ) {
instance = new CalculatorModel(context);
} else {
throw new RuntimeException("Calculator model already instantiated!");
}
}
public static CalculatorModel getInstance() {
if ( instance == null ) {
throw new RuntimeException("CalculatorModel must be instantiated!");
}
return instance;
}
@NotNull
public VarsRegister getVarsRegister() {
return varsRegister;
}
} }

View File

@ -30,10 +30,8 @@ public class CalculatorVarsActivity extends ListActivity {
setTheme(android.R.style.Theme_Dialog); setTheme(android.R.style.Theme_Dialog);
final List<VariableContainer> vars = new ArrayList<VariableContainer>(); final List<Var> vars = new ArrayList<Var>(CalculatorModel.getInstance().getVarsRegister().getVars());
vars.add(new VariableContainer("e", 2.71, true)); setListAdapter(new ArrayAdapter<Var>(this, R.layout.var, R.id.var_text, vars));
vars.add(new VariableContainer("π", 3.14, true));
setListAdapter(new ArrayAdapter<VariableContainer>(this, R.layout.var, R.id.var_text, vars));
final ListView lv = getListView(); final ListView lv = getListView();
lv.setTextFilterEnabled(true); lv.setTextFilterEnabled(true);
@ -42,7 +40,7 @@ public class CalculatorVarsActivity extends ListActivity {
public void onItemClick(AdapterView<?> parent, View view, public void onItemClick(AdapterView<?> parent, View view,
int position, long id) { int position, long id) {
final Intent intent = new Intent(CalculatorActivity.INSERT_TEXT_INTENT); final Intent intent = new Intent(CalculatorActivity.INSERT_TEXT_INTENT);
intent.putExtra(CalculatorActivity.INSERT_TEXT_INTENT_EXTRA_STRING, vars.get(position).getId()); intent.putExtra(CalculatorActivity.INSERT_TEXT_INTENT_EXTRA_STRING, vars.get(position).getName());
sendOrderedBroadcast(intent, null); sendOrderedBroadcast(intent, null);
CalculatorVarsActivity.this.finish(); CalculatorVarsActivity.this.finish();

View File

@ -0,0 +1,89 @@
/*
* 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
*/
package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
/**
* User: serso
* Date: 9/28/11
* Time: 11:22 PM
*/
@Root
public class Var {
@Element
@NotNull
private String name;
@Element
@NotNull
private String value;
private boolean system;
@Element(required = false)
@Nullable
private String description;
public Var() {
}
public Var(@NotNull String name, @NotNull Double value, boolean system) {
this(name, String.valueOf(value), system);
}
public Var(@NotNull String name, @NotNull String value, boolean system) {
this.name = name;
this.value = value;
this.system = system;
}
@NotNull
public String getValue() {
return value;
}
public void setValue(@NotNull String value) {
this.value = value;
}
public boolean isSystem() {
return system;
}
public void setSystem(boolean system) {
this.system = system;
}
@NotNull
public String getName() {
return name;
}
public void setName(@NotNull String name) {
this.name = name;
}
@Nullable
public String getDescription() {
return description;
}
public void setDescription(@Nullable String description) {
this.description = description;
}
@Override
public String toString() {
return getName() + " = " + value;
}
}

View File

@ -1,51 +0,0 @@
/*
* 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
*/
package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull;
import org.solovyev.common.definitions.Identity;
/**
* User: serso
* Date: 9/28/11
* Time: 11:22 PM
*/
public class VariableContainer extends Identity<String>{
@NotNull
private Double value;
private boolean system;
public VariableContainer(@NotNull String id, @NotNull Double value, boolean system) {
super(id);
this.value = value;
this.system = system;
}
@NotNull
public Double getValue() {
return value;
}
public void setValue(@NotNull Double value) {
this.value = value;
}
public boolean isSystem() {
return system;
}
public void setSystem(boolean system) {
this.system = system;
}
@Override
public String toString() {
return getId() + " = " + value;
}
}

View File

@ -0,0 +1,27 @@
package org.solovyev.android.calculator;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
import java.util.ArrayList;
import java.util.List;
/**
* User: serso
* Date: 9/29/11
* Time: 5:19 PM
*/
@Root
public class Vars {
@ElementList
private final List<Var> vars = new ArrayList<Var>();
public Vars() {
}
public List<Var> getVars() {
return vars;
}
}

View File

@ -0,0 +1,117 @@
package org.solovyev.android.calculator;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import org.solovyev.android.calculator.math.MathEntityType;
import org.solovyev.android.view.widgets.SimpleOnDragListener;
import org.solovyev.common.utils.CollectionsUtils;
import org.solovyev.common.utils.Finder;
import java.io.StringWriter;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* User: serso
* Date: 9/29/11
* Time: 4:57 PM
*/
public class VarsRegister {
@NotNull
private final Set<Var> vars = new HashSet<Var>();
@NotNull
private final Set<Var> systemVars = new HashSet<Var>();
@NotNull
public Set<Var> getVars() {
return Collections.unmodifiableSet(vars);
}
@NotNull
public Set<Var> getSystemVars() {
return Collections.unmodifiableSet(systemVars);
}
@Nullable
public Var getVar(@NotNull final String name) {
return CollectionsUtils.get(vars, new Finder<Var>() {
@Override
public boolean isFound(@Nullable Var var) {
return var != null && name.equals(var.getName());
}
});
}
public void merge(@NotNull final List<Var> varsParam) {
final Set<Var> result = new HashSet<Var>(varsParam);
for (Var systemVar : systemVars) {
if (!result.contains(systemVar)) {
result.add(systemVar);
}
}
vars.clear();
vars.addAll(result);
}
public synchronized void load(@NotNull Context context) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
this.vars.clear();
this.systemVars.clear();
final String value = preferences.getString(context.getString(R.string.p_calc_vars), null);
if (value != null) {
final Serializer serializer = new Persister();
try {
final Vars vars = serializer.read(Vars.class, value);
this.vars.addAll(vars.getVars());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
for (Var systemVar : MathEntityType.constants) {
systemVars.add(systemVar);
if (!vars.contains(systemVar)) {
vars.add(systemVar);
}
}
}
public synchronized void save(@NotNull Context context) {
final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
final SharedPreferences.Editor editor = settings.edit();
final Vars vars = new Vars();
for (Var var : this.vars) {
if (!var.isSystem()) {
vars.getVars().add(var);
}
}
final StringWriter sw = new StringWriter();
final Serializer serializer = new Persister();
try {
serializer.write(vars, sw);
} catch (Exception e) {
throw new RuntimeException(e);
}
editor.putString(context.getString(R.string.p_calc_vars),sw.toString());
editor.commit();
}
}

View File

@ -5,14 +5,18 @@
package org.solovyev.android.calculator.math; package org.solovyev.android.calculator.math;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.Var;
import org.solovyev.common.utils.CollectionsUtils;
import org.solovyev.common.utils.Finder;
import java.lang.reflect.Array;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public enum MathEntityType { public enum MathEntityType {
digit, digit,
@ -25,7 +29,14 @@ public enum MathEntityType {
group_symbols, group_symbols,
group_symbol; group_symbol;
public static final List<Character> constants = Arrays.asList('e', 'π', 'i'); public static final List<Var> constants;
static {
final List<Var> result = new ArrayList<Var>();
result.add(new Var("e", Math.exp(1), true));
result.add(new Var("π", Math.PI, true));
result.add(new Var("i", "√(-1)", true));
constants = Collections.unmodifiableList(result);
}
public static final List<Character> dots = Arrays.asList('.'); public static final List<Character> dots = Arrays.asList('.');
@ -72,7 +83,7 @@ public enum MathEntityType {
} }
@Nullable @Nullable
public static MathEntityType getType(char ch) { public static MathEntityType getType(final char ch) {
MathEntityType result = null; MathEntityType result = null;
if ( Character.isDigit(ch) ) { if ( Character.isDigit(ch) ) {
@ -85,11 +96,22 @@ public enum MathEntityType {
result = MathEntityType.binary_operation; result = MathEntityType.binary_operation;
} else if ( singleGroupSymbols.contains(ch) ) { } else if ( singleGroupSymbols.contains(ch) ) {
result = MathEntityType.group_symbol; result = MathEntityType.group_symbol;
} else if ( constants.contains(ch) ) { } else if (isConstant(ch)) {
result = MathEntityType.constant; result = MathEntityType.constant;
} else if ( dots.contains(ch) ) { } else if ( dots.contains(ch) ) {
result = MathEntityType.dot; result = MathEntityType.dot;
} }
return result; return result;
} }
private static boolean isConstant(final char ch) {
final String name = String.valueOf(ch);
return CollectionsUtils.get(constants, new Finder<Var>() {
@Override
public boolean isFound(@Nullable Var var) {
return var != null && var.getName().equals(name);
}
}) != null;
}
} }

View File

@ -6,6 +6,8 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
/** /**
@ -14,9 +16,15 @@ import org.junit.Test;
* Time: 9:47 PM * Time: 9:47 PM
*/ */
public class CalculatorModelTest { public class CalculatorModelTest {
@BeforeClass
public static void setUp() throws Exception {
CalculatorModel.init(null);
}
@Test @Test
public void testEvaluate() throws Exception { public void testEvaluate() throws Exception {
final CalculatorModel cm = new CalculatorModel(); final CalculatorModel cm = CalculatorModel.getInstance();
Assert.assertEquals("4.0", cm.evaluate(JsclOperation.numeric, "2+2")); Assert.assertEquals("4.0", cm.evaluate(JsclOperation.numeric, "2+2"));
Assert.assertEquals("-0.7568", cm.evaluate(JsclOperation.numeric, "sin(4)")); Assert.assertEquals("-0.7568", cm.evaluate(JsclOperation.numeric, "sin(4)"));
@ -43,7 +51,7 @@ public class CalculatorModelTest {
@Test @Test
public void testComplexNumbers() throws Exception { public void testComplexNumbers() throws Exception {
final CalculatorModel cm = new CalculatorModel(); final CalculatorModel cm = CalculatorModel.getInstance();
Assert.assertEquals("1.22133+23123.0i", cm.createResultForComplexNumber("1.22133232+23123*i")); Assert.assertEquals("1.22133+23123.0i", cm.createResultForComplexNumber("1.22133232+23123*i"));
Assert.assertEquals("1.22133+1.2i", cm.createResultForComplexNumber("1.22133232+1.2*i")); Assert.assertEquals("1.22133+1.2i", cm.createResultForComplexNumber("1.22133232+1.2*i"));