From 357eed9f3eff585c2f8e4ba0e628b5b10cf056b7 Mon Sep 17 00:00:00 2001 From: Sergey Solovyev Date: Wed, 14 Nov 2012 18:24:08 +0400 Subject: [PATCH] User defined functions support --- .../calculator/CalculatorEventType.java | 10 + .../CalculatorFunctionsMathRegistry.java | 26 +- .../android/calculator/model/AFunction.java | 224 ++++++++++++++++-- .../android/calculator/model/Functions.java | 3 +- .../res/layout/function_add_param.xml | 14 ++ calculatorpp/res/layout/function_edit.xml | 11 +- .../res/layout/function_edit_param.xml | 22 +- calculatorpp/res/values/text_strings.xml | 8 + .../function/FunctionEditDialogFragment.java | 78 ++++-- .../function/FunctionEditorSaver.java | 167 +++++++++++++ .../function/FunctionParamsView.java | 186 +++++++++++++++ .../edit/CalculatorFunctionsFragment.java | 17 +- .../math/edit/MathEntityRemover.java | 2 +- .../calculator/math/edit/VarEditorSaver.java | 4 +- .../model/AndroidCalculatorEngine.java | 11 +- 15 files changed, 713 insertions(+), 70 deletions(-) create mode 100644 calculatorpp/res/layout/function_add_param.xml create mode 100644 calculatorpp/src/main/java/org/solovyev/android/calculator/function/FunctionEditorSaver.java create mode 100644 calculatorpp/src/main/java/org/solovyev/android/calculator/function/FunctionParamsView.java diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java index 34a71f50..24c7a9d3 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java @@ -115,6 +115,16 @@ public enum CalculatorEventType { // @NotNull IConstant constant_removed, + + // @NotNull Function + function_removed, + + // @NotNull Function + function_added, + + // @NotNull Change + function_changed, + /* ********************************************************************** * diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorFunctionsMathRegistry.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorFunctionsMathRegistry.java index 20757ae1..9c57ac93 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorFunctionsMathRegistry.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorFunctionsMathRegistry.java @@ -9,11 +9,14 @@ package org.solovyev.android.calculator; import jscl.math.function.CustomFunction; import jscl.math.function.Function; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.solovyev.android.calculator.model.AFunction; import org.solovyev.android.calculator.model.Functions; +import org.solovyev.android.calculator.model.MathEntityBuilder; import org.solovyev.common.JBuilder; import org.solovyev.common.math.MathRegistry; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -42,7 +45,24 @@ public class CalculatorFunctionsMathRegistry extends AbstractCalculatorMathRegis public void load() { super.load(); - add(new CustomFunction.Builder(true, "log", new String[]{"base", "x"}, "ln(x)/ln(base)")); + add(new CustomFunction.Builder(true, "log", Arrays.asList("base", "x"), "ln(x)/ln(base)")); + } + + public static void saveFunction(@NotNull CalculatorMathRegistry registry, + @NotNull MathEntityBuilder builder, + @Nullable Function editedInstance, + @NotNull Object source, boolean save) { + final Function addedFunction = registry.add(builder); + + if (save) { + registry.save(); + } + + if (editedInstance == null) { + CalculatorLocatorImpl.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.function_added, addedFunction, source); + } else { + CalculatorLocatorImpl.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.function_changed, ChangeImpl.newInstance(editedInstance, addedFunction), source); + } } @NotNull @@ -65,7 +85,9 @@ public class CalculatorFunctionsMathRegistry extends AbstractCalculatorMathRegis @NotNull @Override protected JBuilder createBuilder(@NotNull AFunction entity) { - return new CustomFunction.Builder(entity.getName(), entity.getParameterNamesAsArray(), entity.getContent()); + CustomFunction.Builder builder = new CustomFunction.Builder(entity.getName(), entity.getParameterNames(), entity.getContent()); + builder.setDescription(entity.getDescription()); + return builder; } @Override diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/model/AFunction.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/model/AFunction.java index 24df6db6..9b2e68a8 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/model/AFunction.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/model/AFunction.java @@ -6,15 +6,17 @@ package org.solovyev.android.calculator.model; +import jscl.math.function.IConstant; +import jscl.math.function.IFunction; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.simpleframework.xml.Element; import org.simpleframework.xml.Root; +import org.simpleframework.xml.Transient; import org.solovyev.android.calculator.MathPersistenceEntity; -import org.solovyev.common.collections.CollectionsUtils; -import org.solovyev.common.text.CollectionTransformations; -import org.solovyev.common.text.StringMapper; +import org.solovyev.common.math.MathEntity; +import java.util.Collections; import java.util.List; /** @@ -24,7 +26,17 @@ import java.util.List; */ @Root -public class AFunction implements MathPersistenceEntity { +public class AFunction implements IFunction, MathPersistenceEntity { + + /* + ********************************************************************** + * + * FIELDS + * + ********************************************************************** + */ + @Transient + private Integer id; @Element @NotNull @@ -34,17 +46,95 @@ public class AFunction implements MathPersistenceEntity { @NotNull private String content; + @Element(required = false) + @NotNull + private List parameterNames = Collections.emptyList(); + + @Element + private boolean system; @Element(required = false) @Nullable - private String parameterNames; + private String description; + /* + ********************************************************************** + * + * CONSTRUCTORS + * + ********************************************************************** + */ + + public AFunction() { + } + + public AFunction(Integer id) { + this.id = id; + } + + /* + ********************************************************************** + * + * METHODS + * + ********************************************************************** + */ + + @Override + public void copy(@NotNull MathEntity mathEntity) { + if (mathEntity instanceof IFunction) { + final IFunction that = ((IFunction) mathEntity); + this.name = that.getName(); + this.content = that.getContent(); + this.description = this.getContent(); + this.system = that.isSystem(); + if (that.isIdDefined()) { + this.id = that.getId(); + } + } else { + throw new IllegalArgumentException("Trying to make a copy of unsupported type: " + mathEntity.getClass()); + } + } + + @Override + public String toJava() { + return String.valueOf(this.content); + } + + /* + ********************************************************************** + * + * GETTERS/SEETTERS + * + ********************************************************************** + */ @NotNull public String getName() { return name; } + @Override + public boolean isSystem() { + return system; + } + + @NotNull + @Override + public Integer getId() { + return this.id; + } + + @Override + public boolean isIdDefined() { + return this.id != null; + } + + @Override + public void setId(@NotNull Integer id) { + this.id = id; + } + public void setName(@NotNull String name) { this.name = name; } @@ -54,26 +144,128 @@ public class AFunction implements MathPersistenceEntity { return content; } + @Nullable + @Override + public String getDescription() { + return this.description; + } + public void setContent(@NotNull String content) { this.content = content; } - @Nullable - public String getParameterNames() { + @NotNull + public List getParameterNames() { return parameterNames; } - public void setParameterNames(@Nullable String[] parameterNames) { - this.parameterNames = CollectionTransformations.formatValue(CollectionsUtils.asList(parameterNames), ";", new StringMapper()); - } - - public void setParameterNames(@Nullable String parameterNames) { + public void setParameterNames(@NotNull List parameterNames) { this.parameterNames = parameterNames; } - @NotNull - public String[] getParameterNamesAsArray() { - final List parameterNamesAsList = CollectionTransformations.split(parameterNames, ";"); - return parameterNamesAsList.toArray(new String[parameterNamesAsList.size()]); + /* + ********************************************************************** + * + * STATIC + * + ********************************************************************** + */ + + public static class Builder implements MathEntityBuilder { + + @NotNull + private String name; + + @Nullable + private String value; + + private boolean system = false; + + @Nullable + private String description; + + @Nullable + private Integer id; + + @NotNull + private List parameterNames = Collections.emptyList(); + + public Builder() { + } + + public Builder(@NotNull IFunction function) { + this.name = function.getName(); + this.value = function.getContent(); + this.system = function.isSystem(); + this.description = function.getDescription(); + this.id = function.getId(); + } + + public Builder(@NotNull IConstant function) { + this.name = function.getName(); + + this.value = function.getValue(); + + this.system = function.isSystem(); + this.description = function.getDescription(); + if (function.isIdDefined()) { + this.id = function.getId(); + } + } + + public Builder(@NotNull String name, @NotNull Double value) { + this(name, String.valueOf(value)); + } + + public Builder(@NotNull String name, @Nullable String value) { + this.name = name; + this.value = value; + } + + + @NotNull + public Builder setName(@NotNull String name) { + this.name = name; + return this; + } + + @NotNull + public Builder setValue(@Nullable String value) { + this.value = value; + return this; + } + + protected Builder setSystem(boolean system) { + this.system = system; + return this; + } + + public void setParameterNames(@NotNull List parameterNames) { + this.parameterNames = parameterNames; + } + + @NotNull + public Builder setDescription(@Nullable String description) { + this.description = description; + return this; + } + + @NotNull + public AFunction create() { + final AFunction result; + if (id != null) { + result = new AFunction(id); + } else { + result = new AFunction(); + } + + result.name = name; + result.content = value; + result.system = system; + result.description = description; + result.parameterNames = parameterNames; + + return result; + } } } diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/model/Functions.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/model/Functions.java index fd674f98..59d6a951 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/model/Functions.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/model/Functions.java @@ -1,6 +1,5 @@ package org.solovyev.android.calculator.model; -import jscl.math.function.CustomFunction; import org.simpleframework.xml.ElementList; import org.simpleframework.xml.Root; import org.solovyev.android.calculator.MathEntityPersistenceContainer; @@ -16,7 +15,7 @@ import java.util.List; @Root public class Functions implements MathEntityPersistenceContainer { - @ElementList(type = CustomFunction.class) + @ElementList(type = AFunction.class) private List functions = new ArrayList(); public Functions() { diff --git a/calculatorpp/res/layout/function_add_param.xml b/calculatorpp/res/layout/function_add_param.xml new file mode 100644 index 00000000..9846a28e --- /dev/null +++ b/calculatorpp/res/layout/function_add_param.xml @@ -0,0 +1,14 @@ + + + + +