User defined functions support
This commit is contained in:
parent
791eac433b
commit
357eed9f3e
@ -115,6 +115,16 @@ public enum CalculatorEventType {
|
||||
// @NotNull IConstant
|
||||
constant_removed,
|
||||
|
||||
|
||||
// @NotNull Function
|
||||
function_removed,
|
||||
|
||||
// @NotNull Function
|
||||
function_added,
|
||||
|
||||
// @NotNull Change<Function>
|
||||
function_changed,
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
|
@ -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<Function> registry,
|
||||
@NotNull MathEntityBuilder<? extends Function> 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<? extends Function> 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
|
||||
|
@ -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<String> 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<String> 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<String> parameterNames) {
|
||||
this.parameterNames = parameterNames;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String[] getParameterNamesAsArray() {
|
||||
final List<String> parameterNamesAsList = CollectionTransformations.split(parameterNames, ";");
|
||||
return parameterNamesAsList.toArray(new String[parameterNamesAsList.size()]);
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public static class Builder implements MathEntityBuilder<AFunction> {
|
||||
|
||||
@NotNull
|
||||
private String name;
|
||||
|
||||
@Nullable
|
||||
private String value;
|
||||
|
||||
private boolean system = false;
|
||||
|
||||
@Nullable
|
||||
private String description;
|
||||
|
||||
@Nullable
|
||||
private Integer id;
|
||||
|
||||
@NotNull
|
||||
private List<String> 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<String> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<AFunction> {
|
||||
|
||||
@ElementList(type = CustomFunction.class)
|
||||
@ElementList(type = AFunction.class)
|
||||
private List<AFunction> functions = new ArrayList<AFunction>();
|
||||
|
||||
public Functions() {
|
||||
|
14
calculatorpp/res/layout/function_add_param.xml
Normal file
14
calculatorpp/res/layout/function_add_param.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
|
||||
a:layout_height="wrap_content"
|
||||
a:layout_width="match_parent"
|
||||
a:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
a:id="@+id/function_add_param_button"
|
||||
a:layout_height="wrap_content"
|
||||
a:layout_width="wrap_content"
|
||||
a:text="+" />
|
||||
|
||||
</LinearLayout>
|
@ -33,15 +33,10 @@
|
||||
style="@style/default_text_size"
|
||||
a:text="@string/c_function_parameters"/>
|
||||
|
||||
<LinearLayout
|
||||
a:id="@+id/function_params_layout"
|
||||
<org.solovyev.android.calculator.function.FunctionParamsView
|
||||
a:id="@+id/function_params_layout"
|
||||
a:layout_height="wrap_content"
|
||||
a:layout_width="match_parent"
|
||||
a:orientation="vertical">
|
||||
|
||||
<include layout="@layout/function_edit_param" />
|
||||
|
||||
</LinearLayout>
|
||||
a:layout_width="match_parent"/>
|
||||
|
||||
<TextView a:layout_height="wrap_content"
|
||||
a:layout_width="match_parent"
|
||||
|
@ -5,21 +5,27 @@
|
||||
a:layout_width="match_parent"
|
||||
a:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
a:id="@+id/function_add_param_button"
|
||||
a:layout_height="wrap_content"
|
||||
a:layout_width="wrap_content"
|
||||
a:text="+" />
|
||||
|
||||
<Button
|
||||
a:id="@+id/function_remove_param_button"
|
||||
a:layout_height="wrap_content"
|
||||
a:layout_width="wrap_content"
|
||||
a:visibility="gone"
|
||||
a:text="-" />
|
||||
|
||||
<Button
|
||||
a:id="@+id/function_up_param_button"
|
||||
a:layout_height="wrap_content"
|
||||
a:layout_width="wrap_content"
|
||||
a:text="^" />
|
||||
|
||||
<Button
|
||||
a:id="@+id/function_down_param_button"
|
||||
a:layout_height="wrap_content"
|
||||
a:layout_width="wrap_content"
|
||||
a:text="v" />
|
||||
|
||||
<EditText
|
||||
a:layout_height="wrap_content"
|
||||
a:id="@+id/function_param_edit_text"
|
||||
a:layout_height="wrap_content"
|
||||
a:layout_width="match_parent"
|
||||
style="@style/default_text_size"
|
||||
a:inputType="text" />
|
||||
|
@ -239,4 +239,12 @@
|
||||
<string name="c_function_description">Description</string>
|
||||
<string name="c_function_parameters">Parameters</string>
|
||||
|
||||
<string name="function_create_function">Create function</string>
|
||||
<string name="function_edit_function">Edit function</string>
|
||||
<string name="function_name_is_not_valid">Name of function is not valid: name must start with letter, can contain letters, digits and underscore.</string>
|
||||
<string name="function_already_exists">Function with same name already exists!</string>
|
||||
<string name="function_name_clashes">Function name clashes with function name!</string>
|
||||
<string name="function_is_empty">Function body could not be empty!</string>
|
||||
<string name="function_param_not_empty">Function parameter should not be empty!</string>
|
||||
|
||||
</resources>
|
@ -1,6 +1,5 @@
|
||||
package org.solovyev.android.calculator.function;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
@ -8,10 +7,18 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import jscl.math.function.CustomFunction;
|
||||
import jscl.math.function.Function;
|
||||
import jscl.math.function.IFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.AndroidUtils2;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.CalculatorEventData;
|
||||
import org.solovyev.android.calculator.CalculatorEventListener;
|
||||
import org.solovyev.android.calculator.CalculatorEventType;
|
||||
import org.solovyev.android.calculator.CalculatorLocatorImpl;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.calculator.math.edit.MathEntityRemover;
|
||||
import org.solovyev.android.calculator.model.AFunction;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
@ -23,7 +30,10 @@ public class FunctionEditDialogFragment extends DialogFragment implements Calcul
|
||||
@NotNull
|
||||
private final Input input;
|
||||
|
||||
public FunctionEditDialogFragment() {
|
||||
@NotNull
|
||||
private FunctionParamsView paramsView;
|
||||
|
||||
public FunctionEditDialogFragment() {
|
||||
this(Input.newInstance());
|
||||
}
|
||||
|
||||
@ -40,26 +50,40 @@ public class FunctionEditDialogFragment extends DialogFragment implements Calcul
|
||||
public void onViewCreated(@NotNull View root, Bundle savedInstanceState) {
|
||||
super.onViewCreated(root, savedInstanceState);
|
||||
|
||||
final View addParamButton = root.findViewById(R.id.function_add_param_button);
|
||||
paramsView = (FunctionParamsView) root.findViewById(R.id.function_params_layout);
|
||||
|
||||
final ViewGroup functionParamsLayout = (ViewGroup) root.findViewById(R.id.function_params_layout);
|
||||
addParamButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
final View functionEditParamLayout = inflater.inflate(R.layout.function_edit_param, null);
|
||||
final AFunction.Builder builder;
|
||||
final IFunction function = input.getFunction();
|
||||
if (function != null) {
|
||||
builder = new AFunction.Builder(function);
|
||||
paramsView.init(function.getParameterNames());
|
||||
} else {
|
||||
builder = new AFunction.Builder();
|
||||
paramsView.init();
|
||||
}
|
||||
|
||||
final View addParamButton = functionEditParamLayout.findViewById(R.id.function_add_param_button);
|
||||
addParamButton.setVisibility(View.GONE);
|
||||
root.findViewById(R.id.cancel_button).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
final View removeParamButton = functionEditParamLayout.findViewById(R.id.function_remove_param_button);
|
||||
removeParamButton.setVisibility(View.VISIBLE);
|
||||
root.findViewById(R.id.save_button).setOnClickListener(new FunctionEditorSaver(builder, function, root, CalculatorLocatorImpl.getInstance().getEngine().getFunctionsRegistry(), this));
|
||||
|
||||
functionParamsLayout.addView(functionEditParamLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
});
|
||||
if ( function == null ) {
|
||||
// CREATE MODE
|
||||
getDialog().setTitle(R.string.function_create_function);
|
||||
|
||||
}
|
||||
root.findViewById(R.id.remove_button).setVisibility(View.GONE);
|
||||
} else {
|
||||
// EDIT MODE
|
||||
getDialog().setTitle(R.string.function_edit_function);
|
||||
|
||||
Function customFunction = new CustomFunction.Builder(function).create();
|
||||
root.findViewById(R.id.remove_button).setOnClickListener(new MathEntityRemover<Function>(customFunction, null, CalculatorLocatorImpl.getInstance().getEngine().getFunctionsRegistry(), getActivity(), this));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
@ -77,6 +101,16 @@ public class FunctionEditDialogFragment extends DialogFragment implements Calcul
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
switch (calculatorEventType) {
|
||||
case function_removed:
|
||||
case function_added:
|
||||
case function_changed:
|
||||
if ( calculatorEventData.getSource() == this ) {
|
||||
dismiss();
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -94,7 +128,7 @@ public class FunctionEditDialogFragment extends DialogFragment implements Calcul
|
||||
public static class Input {
|
||||
|
||||
@Nullable
|
||||
private CustomFunction function;
|
||||
private IFunction function;
|
||||
|
||||
@Nullable
|
||||
private String name;
|
||||
@ -114,7 +148,7 @@ public class FunctionEditDialogFragment extends DialogFragment implements Calcul
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Input newFromFunction(@NotNull CustomFunction function) {
|
||||
public static Input newFromFunction(@NotNull IFunction function) {
|
||||
final Input result = new Input();
|
||||
result.function = function;
|
||||
return result;
|
||||
@ -128,7 +162,7 @@ public class FunctionEditDialogFragment extends DialogFragment implements Calcul
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Input newInstance(@Nullable CustomFunction function, @Nullable String name, @Nullable String value, @Nullable String description) {
|
||||
public static Input newInstance(@Nullable IFunction function, @Nullable String name, @Nullable String value, @Nullable String description) {
|
||||
final Input result = new Input();
|
||||
result.function = function;
|
||||
result.name = name;
|
||||
@ -138,7 +172,7 @@ public class FunctionEditDialogFragment extends DialogFragment implements Calcul
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CustomFunction getFunction() {
|
||||
public IFunction getFunction() {
|
||||
return function;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,167 @@
|
||||
package org.solovyev.android.calculator.function;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import jscl.math.function.CustomFunction;
|
||||
import jscl.math.function.Function;
|
||||
import jscl.math.function.IFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.CalculatorFunctionsMathRegistry;
|
||||
import org.solovyev.android.calculator.CalculatorLocatorImpl;
|
||||
import org.solovyev.android.calculator.CalculatorMathRegistry;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.calculator.math.MathType;
|
||||
import org.solovyev.android.calculator.math.edit.VarEditorSaver;
|
||||
import org.solovyev.android.calculator.model.AFunction;
|
||||
import org.solovyev.android.calculator.model.MathEntityBuilder;
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class FunctionEditorSaver implements View.OnClickListener {
|
||||
|
||||
@NotNull
|
||||
private final Object source;
|
||||
|
||||
@NotNull
|
||||
private final AFunction.Builder builder;
|
||||
|
||||
@Nullable
|
||||
private final Function editedInstance;
|
||||
|
||||
@NotNull
|
||||
private final View view;
|
||||
|
||||
@NotNull
|
||||
private final CalculatorMathRegistry<Function> mathRegistry;
|
||||
|
||||
|
||||
public FunctionEditorSaver(@NotNull AFunction.Builder builder,
|
||||
@Nullable IFunction editedInstance,
|
||||
@NotNull View view,
|
||||
@NotNull CalculatorMathRegistry<Function> registry,
|
||||
@NotNull Object source) {
|
||||
|
||||
this.builder = builder;
|
||||
if (editedInstance instanceof Function || editedInstance == null) {
|
||||
this.editedInstance = (Function)editedInstance;
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.view = view;
|
||||
this.mathRegistry = registry;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final Integer error;
|
||||
|
||||
final EditText editName = (EditText) view.findViewById(R.id.function_edit_name);
|
||||
String name = editName.getText().toString();
|
||||
|
||||
final EditText editValue = (EditText) view.findViewById(R.id.function_edit_value);
|
||||
String content = editValue.getText().toString();
|
||||
|
||||
final EditText editDescription = (EditText) view.findViewById(R.id.function_edit_description);
|
||||
String description = editDescription.getText().toString();
|
||||
|
||||
final FunctionParamsView editParams = (FunctionParamsView) view.findViewById(R.id.function_params_layout);
|
||||
List<String> parameterNames = editParams.getParameterNames();
|
||||
|
||||
if (VarEditorSaver.isValidName(name)) {
|
||||
|
||||
boolean canBeSaved = false;
|
||||
|
||||
final Function entityFromRegistry = mathRegistry.get(name);
|
||||
if (entityFromRegistry == null) {
|
||||
canBeSaved = true;
|
||||
} else if (editedInstance != null && entityFromRegistry.getId().equals(editedInstance.getId())) {
|
||||
canBeSaved = true;
|
||||
}
|
||||
|
||||
if (canBeSaved) {
|
||||
if (validateParameters(parameterNames)) {
|
||||
final MathType.Result mathType = MathType.getType(name, 0, false);
|
||||
|
||||
if (mathType.getMathType() == MathType.text || mathType.getMathType() == MathType.function ) {
|
||||
|
||||
if (!StringUtils.isEmpty(content)) {
|
||||
builder.setParameterNames(parameterNames);
|
||||
builder.setName(name);
|
||||
builder.setDescription(description);
|
||||
builder.setValue(content);
|
||||
error = null;
|
||||
} else {
|
||||
error = R.string.function_is_empty;
|
||||
}
|
||||
} else {
|
||||
error = R.string.function_name_clashes;
|
||||
}
|
||||
} else {
|
||||
error = R.string.function_param_not_empty;
|
||||
}
|
||||
} else {
|
||||
error = R.string.function_already_exists;
|
||||
}
|
||||
} else {
|
||||
error = R.string.function_name_is_not_valid;
|
||||
}
|
||||
|
||||
if (error != null) {
|
||||
CalculatorLocatorImpl.getInstance().getNotifier().showMessage(error, MessageType.error);
|
||||
} else {
|
||||
CalculatorFunctionsMathRegistry.saveFunction(mathRegistry, new BuilderAdapter(builder), editedInstance, source, true);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean validateParameters(@NotNull List<String> parameterNames) {
|
||||
for (String parameterName : parameterNames) {
|
||||
if ( !VarEditorSaver.isValidName(parameterName) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final class BuilderAdapter implements MathEntityBuilder<Function> {
|
||||
|
||||
@NotNull
|
||||
private final AFunction.Builder nestedBuilder;
|
||||
|
||||
public BuilderAdapter(@NotNull AFunction.Builder nestedBuilder) {
|
||||
this.nestedBuilder = nestedBuilder;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public MathEntityBuilder<Function> setName(@NotNull String name) {
|
||||
nestedBuilder.setName(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public MathEntityBuilder<Function> setDescription(@Nullable String description) {
|
||||
nestedBuilder.setDescription(description);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public MathEntityBuilder<Function> setValue(@Nullable String value) {
|
||||
nestedBuilder.setValue(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Function create() {
|
||||
final AFunction function = nestedBuilder.create();
|
||||
return new CustomFunction.Builder(function).create();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,186 @@
|
||||
package org.solovyev.android.calculator.function;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import jscl.text.MutableInt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class FunctionParamsView extends LinearLayout {
|
||||
|
||||
@NotNull
|
||||
private final MutableInt paramsCount = new MutableInt(0);
|
||||
|
||||
@NotNull
|
||||
private final List<Integer> paramIds = new ArrayList<Integer>(10);
|
||||
|
||||
private static final String PARAM_TAG_PREFIX = "function_param_";
|
||||
|
||||
public FunctionParamsView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public FunctionParamsView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public FunctionParamsView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public void init() {
|
||||
init(Collections.<String>emptyList());
|
||||
}
|
||||
|
||||
public void init(@NotNull List<String> parameters) {
|
||||
this.setOrientation(VERTICAL);
|
||||
|
||||
final LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
|
||||
final View addParamView = inflater.inflate(R.layout.function_add_param, null);
|
||||
|
||||
final View addParamButton = addParamView.findViewById(R.id.function_add_param_button);
|
||||
|
||||
addParamButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
addParam(null);
|
||||
}
|
||||
});
|
||||
|
||||
this.addView(addParamView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
for (String parameter : parameters) {
|
||||
addParam(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
public void addParam(@Nullable String name) {
|
||||
synchronized (paramsCount) {
|
||||
final LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
|
||||
final Integer id = paramsCount.intValue();
|
||||
|
||||
final View editParamView = inflater.inflate(R.layout.function_edit_param, null);
|
||||
|
||||
editParamView.setTag(getParamTag(id));
|
||||
|
||||
final View removeParamButton = editParamView.findViewById(R.id.function_remove_param_button);
|
||||
removeParamButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
removeParam(id);
|
||||
}
|
||||
});
|
||||
|
||||
final View upParamButton = editParamView.findViewById(R.id.function_up_param_button);
|
||||
upParamButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
upParam(id);
|
||||
}
|
||||
});
|
||||
|
||||
final View downParamButton = editParamView.findViewById(R.id.function_down_param_button);
|
||||
downParamButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
downParam(id);
|
||||
}
|
||||
});
|
||||
|
||||
this.addView(editParamView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
paramIds.add(id);
|
||||
paramsCount.increment();
|
||||
}
|
||||
}
|
||||
|
||||
private void downParam(@NotNull Integer id) {
|
||||
synchronized (paramsCount) {
|
||||
int index = paramIds.indexOf(id);
|
||||
if (index < paramIds.size() - 1) {
|
||||
swap(index, index + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void upParam(@NotNull Integer id) {
|
||||
synchronized (paramsCount) {
|
||||
int index = paramIds.indexOf(id);
|
||||
if (index > 0) {
|
||||
swap(index, index - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void swap(int index1, int index2) {
|
||||
final View editParamView1 = getParamView(paramIds.get(index1));
|
||||
final View editParamView2 = getParamView(paramIds.get(index2));
|
||||
|
||||
if (editParamView1 != null && editParamView2 != null) {
|
||||
final EditText paramNameEditText1 = (EditText) editParamView1.findViewById(R.id.function_param_edit_text);
|
||||
final EditText paramNameEditText2 = (EditText) editParamView2.findViewById(R.id.function_param_edit_text);
|
||||
swap(paramNameEditText1, paramNameEditText2);
|
||||
}
|
||||
}
|
||||
|
||||
private void swap(@NotNull TextView first,
|
||||
@NotNull TextView second) {
|
||||
final CharSequence tmp = first.getText();
|
||||
first.setText(second.getText());
|
||||
second.setText(tmp);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private View getParamView(@NotNull Integer id) {
|
||||
final String tag = getParamTag(id);
|
||||
return this.findViewWithTag(tag);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getParamTag(@NotNull Integer index) {
|
||||
return PARAM_TAG_PREFIX + index;
|
||||
}
|
||||
|
||||
public void removeParam(@NotNull Integer id) {
|
||||
synchronized (paramsCount) {
|
||||
if (paramIds.contains(id)) {
|
||||
final View editParamView = getParamView(id);
|
||||
if (editParamView != null) {
|
||||
this.removeView(editParamView);
|
||||
paramIds.remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<String> getParameterNames() {
|
||||
synchronized (paramsCount) {
|
||||
final List<String> result = new ArrayList<String>(paramsCount.intValue());
|
||||
|
||||
for (Integer id : paramIds) {
|
||||
final View paramView = getParamView(id);
|
||||
if ( paramView != null ) {
|
||||
final EditText paramNameEditText = (EditText) paramView.findViewById(R.id.function_param_edit_text);
|
||||
result.add(paramNameEditText.getText().toString());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -16,6 +16,7 @@ import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
import jscl.math.function.CustomFunction;
|
||||
import jscl.math.function.Function;
|
||||
import jscl.math.function.IFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.CalculatorEventType;
|
||||
import org.solovyev.android.calculator.CalculatorLocatorImpl;
|
||||
@ -244,24 +245,24 @@ public class CalculatorFunctionsFragment extends AbstractMathEntityListFragment<
|
||||
private static enum LongClickMenuItem implements LabeledMenuItem<Function> {
|
||||
use(R.string.c_use) {
|
||||
@Override
|
||||
public void onClick(@NotNull Function data, @NotNull Context context) {
|
||||
CalculatorLocatorImpl.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.use_function, data);
|
||||
public void onClick(@NotNull Function function, @NotNull Context context) {
|
||||
CalculatorLocatorImpl.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.use_function, function);
|
||||
}
|
||||
},
|
||||
|
||||
edit(R.string.c_edit) {
|
||||
@Override
|
||||
public void onClick(@NotNull Function function, @NotNull Context context) {
|
||||
if (function instanceof CustomFunction) {
|
||||
FunctionEditDialogFragment.showDialog(FunctionEditDialogFragment.Input.newFromFunction((CustomFunction) function), ((SherlockFragmentActivity) context).getSupportFragmentManager());
|
||||
}
|
||||
}
|
||||
if (function instanceof IFunction) {
|
||||
FunctionEditDialogFragment.showDialog(FunctionEditDialogFragment.Input.newFromFunction((IFunction) function), ((SherlockFragmentActivity) context).getSupportFragmentManager());
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
copy_description(R.string.c_copy_description) {
|
||||
@Override
|
||||
public void onClick(@NotNull Function data, @NotNull Context context) {
|
||||
final String text = CalculatorLocatorImpl.getInstance().getEngine().getFunctionsRegistry().getDescription(data.getName());
|
||||
public void onClick(@NotNull Function function, @NotNull Context context) {
|
||||
final String text = CalculatorLocatorImpl.getInstance().getEngine().getFunctionsRegistry().getDescription(function.getName());
|
||||
if (!StringUtils.isEmpty(text)) {
|
||||
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
|
||||
clipboard.setText(text);
|
||||
|
@ -24,7 +24,7 @@ import org.solovyev.common.math.MathEntity;
|
||||
* Date: 12/22/11
|
||||
* Time: 9:36 PM
|
||||
*/
|
||||
class MathEntityRemover<T extends MathEntity> implements View.OnClickListener, DialogInterface.OnClickListener {
|
||||
public class MathEntityRemover<T extends MathEntity> implements View.OnClickListener, DialogInterface.OnClickListener {
|
||||
|
||||
@NotNull
|
||||
private final T mathEntity;
|
||||
|
@ -29,7 +29,7 @@ import org.solovyev.common.text.StringUtils;
|
||||
* Date: 12/22/11
|
||||
* Time: 9:52 PM
|
||||
*/
|
||||
class VarEditorSaver<T extends MathEntity> implements View.OnClickListener {
|
||||
public class VarEditorSaver<T extends MathEntity> implements View.OnClickListener {
|
||||
|
||||
@NotNull
|
||||
private final MathEntityBuilder<? extends T> varBuilder;
|
||||
@ -123,7 +123,7 @@ class VarEditorSaver<T extends MathEntity> implements View.OnClickListener {
|
||||
}
|
||||
}
|
||||
|
||||
boolean isValidName(@Nullable String name) {
|
||||
public static boolean isValidName(@Nullable String name) {
|
||||
boolean result = false;
|
||||
|
||||
if (!StringUtils.isEmpty(name)) {
|
||||
|
@ -17,7 +17,16 @@ import jscl.math.function.Function;
|
||||
import jscl.math.function.IConstant;
|
||||
import jscl.math.operator.Operator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.CalculatorEngine;
|
||||
import org.solovyev.android.calculator.CalculatorEngineImpl;
|
||||
import org.solovyev.android.calculator.CalculatorFunctionsMathRegistry;
|
||||
import org.solovyev.android.calculator.CalculatorMathEngine;
|
||||
import org.solovyev.android.calculator.CalculatorMathRegistry;
|
||||
import org.solovyev.android.calculator.CalculatorOperatorsMathRegistry;
|
||||
import org.solovyev.android.calculator.CalculatorPostfixFunctionsRegistry;
|
||||
import org.solovyev.android.calculator.CalculatorVarsRegistry;
|
||||
import org.solovyev.android.calculator.MathPersistenceEntity;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.prefs.BooleanPreference;
|
||||
import org.solovyev.android.prefs.Preference;
|
||||
import org.solovyev.android.prefs.StringPreference;
|
||||
|
Loading…
Reference in New Issue
Block a user