diff --git a/app/build.gradle b/app/build.gradle index 03487e05..917e684b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -60,6 +60,7 @@ dependencies { compile 'org.solovyev:common-core:1.0.7' compile 'org.solovyev:common-text:1.0.7' compile 'org.solovyev:common-security:1.0.7' + compile 'org.solovyev:common-msg:1.0.7' compile 'com.android.support:support-v4:23.1.1' compile 'com.android.support:appcompat-v7:23.1.1' compile 'com.android.support:design:23.1.1' @@ -73,7 +74,7 @@ dependencies { compile 'org.solovyev.android:android-common-views:1.1.18@aar' compile 'org.solovyev.android:android-common-menus:1.1.18@aar' compile 'org.solovyev.android:android-common-preferences:1.1.18@aar' - compile('org.solovyev:jscl:1.0.8') { + compile('org.solovyev:jscl:1.0.12') { exclude(module: 'xercesImpl') } compile 'org.solovyev.android:checkout:0.7.2@aar' diff --git a/app/misc/libs/jscl-1.0.12.jar b/app/misc/libs/jscl-1.0.12.jar new file mode 100644 index 00000000..2c2cc5c7 Binary files /dev/null and b/app/misc/libs/jscl-1.0.12.jar differ diff --git a/app/src/main/java/org/solovyev/android/calculator/AppComponent.java b/app/src/main/java/org/solovyev/android/calculator/AppComponent.java index 678eb5e1..8881d3c3 100644 --- a/app/src/main/java/org/solovyev/android/calculator/AppComponent.java +++ b/app/src/main/java/org/solovyev/android/calculator/AppComponent.java @@ -1,7 +1,9 @@ package org.solovyev.android.calculator; +import org.solovyev.android.calculator.function.EditFunctionFragment; import org.solovyev.android.calculator.history.BaseHistoryFragment; import org.solovyev.android.calculator.history.EditHistoryFragment; +import org.solovyev.android.calculator.math.edit.FunctionsFragment; import org.solovyev.android.calculator.onscreen.CalculatorOnscreenService; import javax.inject.Singleton; @@ -17,5 +19,7 @@ public interface AppComponent { void inject(CalculatorOnscreenService service); void inject(BaseHistoryFragment fragment); void inject(BaseDialogFragment fragment); + void inject(EditFunctionFragment fragment); void inject(EditHistoryFragment fragment); + void inject(FunctionsFragment fragment); } diff --git a/app/src/main/java/org/solovyev/android/calculator/CalculatorActivityLauncher.java b/app/src/main/java/org/solovyev/android/calculator/CalculatorActivityLauncher.java index ce669c0a..75acea0a 100644 --- a/app/src/main/java/org/solovyev/android/calculator/CalculatorActivityLauncher.java +++ b/app/src/main/java/org/solovyev/android/calculator/CalculatorActivityLauncher.java @@ -33,12 +33,17 @@ import android.support.v7.app.AppCompatActivity; import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; -import jscl.math.Generic; + import org.solovyev.android.Activities; import org.solovyev.android.calculator.about.CalculatorAboutActivity; +import org.solovyev.android.calculator.function.CppFunction; import org.solovyev.android.calculator.function.EditFunctionFragment; import org.solovyev.android.calculator.history.CalculatorHistoryActivity; -import org.solovyev.android.calculator.math.edit.*; +import org.solovyev.android.calculator.math.edit.CalculatorFunctionsActivity; +import org.solovyev.android.calculator.math.edit.CalculatorOperatorsActivity; +import org.solovyev.android.calculator.math.edit.CalculatorVarsActivity; +import org.solovyev.android.calculator.math.edit.VarEditDialogFragment; +import org.solovyev.android.calculator.math.edit.VarsFragment; import org.solovyev.android.calculator.matrix.CalculatorMatrixActivity; import org.solovyev.android.calculator.plot.CalculatorPlotActivity; import org.solovyev.android.calculator.plot.CalculatorPlotter; @@ -47,9 +52,14 @@ import org.solovyev.common.msg.Message; import org.solovyev.common.msg.MessageType; import org.solovyev.common.text.Strings; +import java.util.List; +import java.util.Set; + import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.List; + +import jscl.math.Generic; +import jscl.math.function.Constant; /** * User: serso @@ -159,9 +169,17 @@ public final class CalculatorActivityLauncher implements CalculatorEventListener final DisplayState viewState = display.getState(); if (viewState.valid) { - final String functionValue = viewState.text; - if (!Strings.isEmpty(functionValue)) { - EditFunctionFragment.showDialog(EditFunctionFragment.Input.newFromDisplay(viewState), context); + final String functionBody = viewState.text; + if (!Strings.isEmpty(functionBody)) { + final CppFunction.Builder builder = CppFunction.builder("", functionBody); + final Generic generic = viewState.getResult(); + if (generic != null) { + final Set constants = CalculatorUtils.getNotSystemConstants(generic); + for (Constant constant : constants) { + builder.withParameter(constant.getName()); + } + } + EditFunctionFragment.showDialog(builder.build(), context); } else { getNotifier().showMessage(R.string.empty_function_error, MessageType.error); } diff --git a/app/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java b/app/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java index d3efe39c..e1f526be 100644 --- a/app/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java +++ b/app/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java @@ -81,9 +81,6 @@ public enum CalculatorEventType { // @Nonnull IConstant use_constant, - // @Nonnull Function - use_function, - // @Nonnull Operator use_operator, @@ -100,12 +97,6 @@ public enum CalculatorEventType { // @Nonnull Function function_removed, - // @Nonnull Function - function_added, - - // @Nonnull Change - function_changed, - /* ********************************************************************** * diff --git a/app/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java b/app/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java index 68768352..8c79ed19 100644 --- a/app/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java +++ b/app/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java @@ -54,7 +54,6 @@ import jscl.MathEngine; import jscl.NumeralBase; import jscl.NumeralBaseException; import jscl.math.Generic; -import jscl.math.function.Function; import jscl.math.function.IConstant; import jscl.math.operator.Operator; import jscl.text.ParseInterruptedException; @@ -489,6 +488,15 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener { VarsRegistry.saveVariable(varsRegistry, builder, ansVar, this, false); } + @Subscribe + public void onFunctionAdded(@Nonnull FunctionsRegistry.AddedEvent event) { + evaluate(); + } + @Subscribe + public void onFunctionsChanged(@Nonnull FunctionsRegistry.ChangedEvent event) { + evaluate(); + } + @Override public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) { @@ -502,8 +510,6 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener { case constant_added: case constant_removed: - case function_added: - case function_changed: case function_removed: evaluate(); break; @@ -517,11 +523,6 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener { Locator.getInstance().getKeyboard().buttonPressed(operator.getName()); break; - case use_function: - final Function function = (Function) data; - Locator.getInstance().getKeyboard().buttonPressed(function.getName()); - break; - } } diff --git a/app/src/main/java/org/solovyev/android/calculator/Engine.java b/app/src/main/java/org/solovyev/android/calculator/Engine.java index 8489cb9e..258a699d 100644 --- a/app/src/main/java/org/solovyev/android/calculator/Engine.java +++ b/app/src/main/java/org/solovyev/android/calculator/Engine.java @@ -23,13 +23,10 @@ package org.solovyev.android.calculator; import android.content.SharedPreferences; + import com.squareup.otto.Bus; -import jscl.AngleUnit; -import jscl.JsclMathEngine; -import jscl.MathEngine; -import jscl.NumeralBase; -import jscl.math.function.IConstant; -import jscl.math.operator.Operator; + +import org.solovyev.android.Check; import org.solovyev.android.calculator.model.EntityDao; import org.solovyev.android.calculator.model.Vars; import org.solovyev.android.prefs.BooleanPreference; @@ -40,14 +37,22 @@ import org.solovyev.common.text.EnumMapper; import org.solovyev.common.text.NumberMapper; import org.solovyev.common.text.Strings; -import javax.annotation.Nonnull; -import javax.inject.Inject; -import javax.inject.Singleton; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.Executor; +import javax.annotation.Nonnull; +import javax.inject.Inject; +import javax.inject.Singleton; + +import jscl.AngleUnit; +import jscl.JsclMathEngine; +import jscl.MathEngine; +import jscl.NumeralBase; +import jscl.math.function.IConstant; +import jscl.math.operator.Operator; + @Singleton public class Engine implements SharedPreferences.OnSharedPreferenceChangeListener { @@ -131,6 +136,7 @@ public class Engine implements SharedPreferences.OnSharedPreferenceChangeListene } public void init(@Nonnull Executor initThread) { + Check.isMainThread(); checkPreferences(); preferences.registerOnSharedPreferenceChangeListener(this); applyPreferences(); @@ -183,6 +189,7 @@ public class Engine implements SharedPreferences.OnSharedPreferenceChangeListene } private void applyPreferences() { + Check.isMainThread(); mathEngine.setAngleUnits(Preferences.angleUnit.getPreference(preferences)); mathEngine.setNumeralBase(Preferences.numeralBase.getPreference(preferences)); setMultiplicationSign(Preferences.multiplicationSign.getPreference(preferences)); diff --git a/app/src/main/java/org/solovyev/android/calculator/FunctionsRegistry.java b/app/src/main/java/org/solovyev/android/calculator/FunctionsRegistry.java index 12524a50..553a59d7 100644 --- a/app/src/main/java/org/solovyev/android/calculator/FunctionsRegistry.java +++ b/app/src/main/java/org/solovyev/android/calculator/FunctionsRegistry.java @@ -26,17 +26,15 @@ import android.app.Application; import android.content.SharedPreferences; import android.os.Handler; import android.support.annotation.NonNull; -import jscl.JsclMathEngine; -import jscl.math.function.CustomFunction; -import jscl.math.function.Function; -import jscl.math.function.IFunction; + +import com.squareup.otto.Bus; + import org.json.JSONArray; import org.json.JSONException; import org.simpleframework.xml.Serializer; import org.simpleframework.xml.core.Persister; import org.solovyev.android.Check; import org.solovyev.android.calculator.function.CppFunction; -import org.solovyev.android.calculator.function.FunctionBuilderAdapter; import org.solovyev.android.calculator.json.Json; import org.solovyev.android.calculator.model.OldFunction; import org.solovyev.android.calculator.model.OldFunctions; @@ -44,15 +42,25 @@ import org.solovyev.android.io.FileSaver; import org.solovyev.common.JBuilder; import org.solovyev.common.text.Strings; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executor; + import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; -import java.io.File; -import java.io.IOException; -import java.util.*; -import java.util.concurrent.Executor; + +import jscl.JsclMathEngine; +import jscl.math.function.CustomFunction; +import jscl.math.function.Function; import static android.text.TextUtils.isEmpty; @@ -83,19 +91,20 @@ public class FunctionsRegistry extends BaseEntitiesRegistry builder, @Nullable Function oldFunction) { final Function function = add(builder); - save(); - if (editedInstance == null) { - calculator.fireCalculatorEvent(CalculatorEventType.function_added, function, source); + if (oldFunction == null) { + bus.post(new AddedEvent(function)); } else { - calculator.fireCalculatorEvent(CalculatorEventType.function_changed, ChangeImpl.newInstance(editedInstance, function), source); + bus.post(new ChangedEvent(oldFunction, function)); } } @@ -112,12 +121,25 @@ public class FunctionsRegistry extends BaseEntitiesRegistry result) { + final Function function = super.add(result); + // todo serso: don't save while we're initializing + save(); + return function; + } + @NonNull private List loadFunctions() { try { @@ -194,7 +216,7 @@ public class FunctionsRegistry extends BaseEntitiesRegistry createBuilder(@Nonnull OldFunction function) { - return new FunctionBuilderAdapter(new OldFunction.Builder(function)); + throw new UnsupportedOperationException(); } @Override @@ -239,4 +261,34 @@ public class FunctionsRegistry extends BaseEntitiesRegistry JSON_CREATOR = new Json.Creator() { @NonNull @@ -25,10 +31,23 @@ public class CppFunction implements Jsonable { return new CppFunction(json); } }; + public static final Creator CREATOR = new Creator() { + @Override + public CppFunction createFromParcel(Parcel in) { + return new CppFunction(in); + } + + @Override + public CppFunction[] newArray(int size) { + return new CppFunction[size]; + } + }; + public static final int NO_ID = -1; private static final String JSON_NAME = "n"; private static final String JSON_BODY = "b"; private static final String JSON_PARAMETERS = "ps"; private static final String JSON_DESCRIPTION = "d"; + protected final int id; @Nonnull protected final List parameters = new ArrayList<>(); @Nonnull @@ -41,13 +60,13 @@ public class CppFunction implements Jsonable { private CppFunction(@Nonnull String name, @Nonnull String body) { Check.isNotEmpty(name); Check.isNotEmpty(body); + this.id = NO_ID; this.name = name; this.body = body; } private CppFunction(@NonNull JSONObject json) throws JSONException { - name = json.getString(JSON_NAME); - body = json.getString(JSON_BODY); + id = NO_ID; final JSONArray array = json.optJSONArray(JSON_PARAMETERS); if (array != null) { for (int i = 0; i < array.length(); i++) { @@ -57,21 +76,33 @@ public class CppFunction implements Jsonable { } } } + name = json.getString(JSON_NAME); + body = json.getString(JSON_BODY); description = json.optString(JSON_DESCRIPTION, ""); } private CppFunction(@NonNull CppFunction that) { + id = that.id; + parameters.addAll(that.parameters); name = that.name; body = that.body; description = that.description; - parameters.addAll(that.parameters); } private CppFunction(@NonNull IFunction that) { + id = that.isIdDefined() ? that.getId() : NO_ID; + parameters.addAll(that.getParameterNames()); name = that.getName(); body = that.getContent(); description = Strings.getNotEmpty(that.getDescription(), ""); - parameters.addAll(that.getParameterNames()); + } + + protected CppFunction(Parcel in) { + id = in.readInt(); + parameters.addAll(in.createStringArrayList()); + name = in.readString(); + body = in.readString(); + description = in.readString(); } @Nonnull @@ -93,8 +124,6 @@ public class CppFunction implements Jsonable { @Override public JSONObject toJson() throws JSONException { final JSONObject json = new JSONObject(); - json.put(JSON_NAME, name); - json.put(JSON_BODY, body); if (!parameters.isEmpty()) { final JSONArray array = new JSONArray(); int j = 0; @@ -106,12 +135,18 @@ public class CppFunction implements Jsonable { } json.put(JSON_PARAMETERS, array); } + json.put(JSON_NAME, name); + json.put(JSON_BODY, body); if (!TextUtils.isEmpty(description)) { json.put(JSON_DESCRIPTION, description); } return json; } + public int getId() { + return id; + } + @Nonnull public String getBody() { return body; @@ -132,56 +167,73 @@ public class CppFunction implements Jsonable { return name; } - public static final class Builder extends CppFunction { + @Override + public int describeContents() { + return 0; + } + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(id); + dest.writeStringList(parameters); + dest.writeString(name); + dest.writeString(body); + dest.writeString(description); + } + + @Nonnull + public CustomFunction.Builder toCustomFunctionBuilder() { + final CustomFunction.Builder builder = new CustomFunction.Builder(name, parameters, body); + builder.setDescription(description); + if (id != NO_ID) { + builder.setId(id); + } + return builder; + } + + public static final class Builder { + + @NonNull + private final CppFunction function; private boolean built; private Builder(@Nonnull String name, @Nonnull String body) { - super(name, body); + function = new CppFunction(name, body); } - public Builder(@NonNull CppFunction function) { - super(function); + public Builder(@NonNull CppFunction that) { + function = new CppFunction(that); } - public Builder(@NonNull IFunction function) { - super(function); + public Builder(@NonNull IFunction that) { + function = new CppFunction(that); } @Nonnull public Builder withDescription(@Nonnull String description) { Check.isTrue(!built); - this.description = description; + function.description = description; return this; } @Nonnull public Builder withParameters(@Nonnull Collection parameters) { Check.isTrue(!built); - this.parameters.addAll(parameters); + function.parameters.addAll(parameters); return this; } @Nonnull public Builder withParameter(@Nonnull String parameter) { Check.isTrue(!built); - parameters.add(parameter); + function.parameters.add(parameter); return this; } @Nonnull public CppFunction build() { built = true; - return this; - } - - public void withValuesFrom(@Nonnull IFunction that) { - Check.isTrue(!built); - name = that.getName(); - body = that.getContent(); - description = Strings.getNotEmpty(that.getDescription(), ""); - parameters.clear(); - parameters.addAll(that.getParameterNames()); + return function; } } } diff --git a/app/src/main/java/org/solovyev/android/calculator/function/EditFunctionFragment.java b/app/src/main/java/org/solovyev/android/calculator/function/EditFunctionFragment.java index eebd79c7..177c50cf 100644 --- a/app/src/main/java/org/solovyev/android/calculator/function/EditFunctionFragment.java +++ b/app/src/main/java/org/solovyev/android/calculator/function/EditFunctionFragment.java @@ -28,40 +28,56 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.res.Resources; import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; import android.support.annotation.NonNull; import android.support.design.widget.TextInputLayout; +import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.text.Editable; -import android.view.*; +import android.text.TextUtils; +import android.view.ContextMenu; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; -import butterknife.Bind; -import butterknife.ButterKnife; -import jscl.math.Generic; -import jscl.math.function.*; -import org.solovyev.android.calculator.*; + +import org.solovyev.android.calculator.App; +import org.solovyev.android.calculator.AppComponent; +import org.solovyev.android.calculator.BaseDialogFragment; +import org.solovyev.android.calculator.Calculator; +import org.solovyev.android.calculator.CalculatorEventType; +import org.solovyev.android.calculator.FunctionsRegistry; +import org.solovyev.android.calculator.KeyboardUi; +import org.solovyev.android.calculator.KeyboardWindow; +import org.solovyev.android.calculator.Locator; +import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.math.edit.CalculatorFunctionsActivity; import org.solovyev.android.calculator.math.edit.FunctionsFragment; -import org.solovyev.android.calculator.math.edit.MathEntityRemover; import org.solovyev.android.calculator.math.edit.VarEditorSaver; -import org.solovyev.android.calculator.model.OldFunction; import org.solovyev.common.math.MathRegistry; +import java.util.Collections; +import java.util.List; + import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; +import javax.inject.Inject; -public class EditFunctionFragment extends BaseDialogFragment implements CalculatorEventListener, View.OnClickListener, View.OnFocusChangeListener, View.OnKeyListener { +import butterknife.Bind; +import butterknife.ButterKnife; +import jscl.math.function.CustomFunction; +import jscl.math.function.Function; +import jscl.math.function.IConstant; - private static final String ARG_INPUT = "input"; +public class EditFunctionFragment extends BaseDialogFragment implements View.OnClickListener, View.OnFocusChangeListener, View.OnKeyListener { + + private static final String ARG_FUNCTION = "function"; private static final int MENU_FUNCTION = Menu.FIRST; private static final int MENU_CONSTANT = Menu.FIRST + 1; @@ -79,48 +95,65 @@ public class EditFunctionFragment extends BaseDialogFragment implements Calculat TextInputLayout nameLabel; @Bind(R.id.function_name) EditText nameView; + @Bind(R.id.function_body_label) + TextInputLayout bodyLabel; @Bind(R.id.function_body) EditText bodyView; @Bind(R.id.function_description) EditText descriptionView; - private Input input; + private CppFunction function; + + @Inject + Calculator calculator; + @Inject + FunctionsRegistry registry; @Nonnull - public static EditFunctionFragment create(@Nonnull Input input) { + private static EditFunctionFragment create(@Nullable CppFunction function) { final EditFunctionFragment fragment = new EditFunctionFragment(); - fragment.input = input; - final Bundle args = new Bundle(); - args.putParcelable("input", input); - fragment.setArguments(args); + if (function != null) { + final Bundle args = new Bundle(); + args.putParcelable(ARG_FUNCTION, function); + fragment.setArguments(args); + } return fragment; } - public static void showDialog(@Nonnull Input input, @Nonnull Context context) { - if (context instanceof AppCompatActivity) { - EditFunctionFragment.showDialog(input, ((AppCompatActivity) context).getSupportFragmentManager()); - } else { + public static void showDialog(@Nonnull FragmentActivity activity) { + EditFunctionFragment.showDialog(null, activity.getSupportFragmentManager()); + } + + public static void showDialog(@Nonnull CppFunction function, @Nonnull Context context) { + if (!(context instanceof CalculatorFunctionsActivity)) { final Intent intent = new Intent(context, CalculatorFunctionsActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(FunctionsFragment.EXTRA_FUNCTION, input); + intent.putExtra(FunctionsFragment.EXTRA_FUNCTION, function); context.startActivity(intent); + } else { + EditFunctionFragment.showDialog(function, ((AppCompatActivity) context).getSupportFragmentManager()); } } - public static void showDialog(@Nonnull Input input, @Nonnull FragmentManager fm) { + public static void showDialog(@Nullable CppFunction input, @Nonnull FragmentManager fm) { App.showDialog(create(input), "function-editor", fm); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - input = getArguments().getParcelable(ARG_INPUT); + function = getArguments().getParcelable(ARG_FUNCTION); + } + + @Override + protected void inject(@NonNull AppComponent component) { + super.inject(component); + component.inject(this); } @Override protected void onPrepareDialog(@NonNull AlertDialog.Builder builder) { builder.setNegativeButton(R.string.c_cancel, null); builder.setPositiveButton(R.string.ok, null); - final OldFunction function = input.getFunction(); builder.setTitle(function == null ? R.string.function_create_function : R.string.function_edit_function); if (function != null) { builder.setNeutralButton(R.string.c_remove, null); @@ -145,17 +178,46 @@ public class EditFunctionFragment extends BaseDialogFragment implements Calculat tryClose(); } }); - final OldFunction function = input.getFunction(); if (function != null) { - final Function customFunction = new CustomFunction.Builder(function).create(); final Button neutral = dialog.getButton(AlertDialog.BUTTON_NEUTRAL); - neutral.setOnClickListener(MathEntityRemover.newFunctionRemover(customFunction, null, getActivity(), EditFunctionFragment.this)); + neutral.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + tryRemoveFunction(function, false); + } + }); } } }); return dialog; } + private void tryRemoveFunction(@NonNull CppFunction function, boolean confirmed) { + if (!confirmed) { + showRemovalDialog(function); + return; + } + final CustomFunction entity = function.toCustomFunctionBuilder().create(); + registry.remove(entity); + calculator.fireCalculatorEvent(CalculatorEventType.function_removed, entity, this); + dismiss(); + } + + private void showRemovalDialog(@NonNull final CppFunction function) { + new AlertDialog.Builder(getActivity(), App.getTheme().alertDialogTheme) + .setCancelable(true) + .setTitle(R.string.removal_confirmation) + .setMessage(R.string.function_removal_confirmation_question) + .setNegativeButton(R.string.c_no, null) + .setPositiveButton(R.string.c_yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + tryRemoveFunction(function, true); + } + }) + .create().show(); + } + @Override public void onFocusChange(View v, boolean hasFocus) { if (v.getId() == R.id.function_body) { @@ -166,6 +228,7 @@ public class EditFunctionFragment extends BaseDialogFragment implements Calculat } } } + @Override public void onClick(View v) { if (v.getId() == R.id.function_body) { @@ -199,9 +262,30 @@ public class EditFunctionFragment extends BaseDialogFragment implements Calculat if (!validateName()) { return false; } + if (!validateParameters()) { + return false; + } if (!validateBody()) { return false; } + + final CppFunction newFunction = CppFunction.builder(nameView.getText().toString(), bodyView.getText().toString()) + .withParameters(paramsView.getParams()) + .withDescription(descriptionView.getText().toString()).build(); + final Function oldFunction = function.id == CppFunction.NO_ID ? null : registry.getById(function.id); + registry.add(newFunction.toCustomFunctionBuilder(), oldFunction); + return true; + } + + private boolean validateParameters(@Nonnull List parameterNames) { + for (String parameterName : parameterNames) { + if (!VarEditorSaver.isValidName(parameterName)) { + return false; + } + } + // error = R.string.function_param_not_empty; + + return true; } @@ -211,11 +295,32 @@ public class EditFunctionFragment extends BaseDialogFragment implements Calculat setError(nameLabel, getString(R.string.function_name_is_not_valid)); return false; } + final Function existingFunction = registry.get(name); + if (existingFunction != null && (!existingFunction.isIdDefined() || !existingFunction.getId().equals(function.getId()))) { + setError(nameLabel, getString(R.string.function_already_exists)); + return false; + } clearError(nameLabel); return true; } private boolean validateBody() { + final String body = bodyView.getText().toString(); + if (TextUtils.isEmpty(body)) { + setError(bodyLabel, getString(R.string.function_is_empty)); + return false; + } + clearError(bodyLabel); + return true; + } + + private boolean validateParameters() { + final List parameters = paramsView.getParams(); + /*if (TextUtils.isEmpty(body)) { + setError(bodyLabel, getString(R.string.function_is_empty)); + return false; + }*/ + //clearError(bodyLabel); return true; } @@ -227,14 +332,10 @@ public class EditFunctionFragment extends BaseDialogFragment implements Calculat ButterKnife.bind(this, view); if (savedInstanceState == null) { - final List parameterNames = input.getParameterNames(); - if (parameterNames != null) { - paramsView.addParams(parameterNames); - } - - nameView.setText(input.getName()); - descriptionView.setText(input.getDescription()); - bodyView.setText(input.getContent()); + paramsView.addParams(function.getParameters()); + nameView.setText(function.getName()); + descriptionView.setText(function.getDescription()); + bodyView.setText(function.getBody()); } bodyView.setOnClickListener(this); bodyView.setOnFocusChangeListener(this); @@ -243,177 +344,6 @@ public class EditFunctionFragment extends BaseDialogFragment implements Calculat return view; } - @Override - public void onResume() { - super.onResume(); - - Locator.getInstance().getCalculator().addCalculatorEventListener(this); - } - - @Override - public void onPause() { - Locator.getInstance().getCalculator().removeCalculatorEventListener(this); - - super.onPause(); - } - - @Override - public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) { - switch (calculatorEventType) { - case function_removed: - case function_added: - case function_changed: - if (calculatorEventData.getSource() == EditFunctionFragment.this) { - dismiss(); - } - break; - - } - } - - public static class Input implements Parcelable { - - private static final Parcelable.Creator STRING_CREATOR = new Creator() { - @Override - public String createFromParcel(@Nonnull Parcel in) { - return in.readString(); - } - - @Override - public String[] newArray(int size) { - return new String[size]; - } - }; - @Nullable - private OldFunction function; - @Nullable - private String name; - @Nullable - private String content; - @Nullable - private String description; - @Nullable - private List parameterNames; - public static final Parcelable.Creator CREATOR = new Creator() { - @Override - public Input createFromParcel(@Nonnull Parcel in) { - return Input.fromParcel(in); - } - - @Override - public Input[] newArray(int size) { - return new Input[size]; - } - }; - - private Input() { - } - - @Nonnull - private static Input fromParcel(@Nonnull Parcel in) { - final Input result = new Input(); - result.name = in.readString(); - result.content = in.readString(); - result.description = in.readString(); - - final List parameterNames = new ArrayList<>(); - in.readTypedList(parameterNames, STRING_CREATOR); - result.parameterNames = parameterNames; - - result.function = (OldFunction) in.readSerializable(); - - return result; - } - - @Nonnull - public static Input newInstance() { - return new Input(); - } - - @Nonnull - public static Input newFromFunction(@Nonnull IFunction function) { - final Input result = new Input(); - result.function = OldFunction.fromIFunction(function); - return result; - } - - @Nonnull - public static Input newInstance(@Nullable IFunction function, - @Nullable String name, - @Nullable String value, - @Nullable String description, - @Nonnull List parameterNames) { - - final Input result = new Input(); - if (function != null) { - result.function = OldFunction.fromIFunction(function); - } - result.name = name; - result.content = value; - result.description = description; - result.parameterNames = new ArrayList<>(parameterNames); - - return result; - } - - @Nonnull - public static Input newFromDisplay(@Nonnull DisplayState viewState) { - final Input result = new Input(); - - result.content = viewState.text; - final Generic generic = viewState.getResult(); - if (generic != null) { - final Set constants = CalculatorUtils.getNotSystemConstants(generic); - final List parameterNames = new ArrayList<>(constants.size()); - for (Constant constant : constants) { - parameterNames.add(constant.getName()); - } - result.parameterNames = parameterNames; - } - - return result; - } - - @Nullable - public OldFunction getFunction() { - return function; - } - - @Nullable - public String getName() { - return name == null ? (function == null ? null : function.getName()) : name; - } - - @Nullable - public String getContent() { - return content == null ? (function == null ? null : function.getContent()) : content; - } - - @Nullable - public String getDescription() { - return description == null ? (function == null ? null : function.getDescription()) : description; - } - - @Nullable - public List getParameterNames() { - return parameterNames == null ? (function == null ? null : function.getParameterNames()) : parameterNames; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(@Nonnull Parcel out, int flags) { - out.writeString(name); - out.writeString(content); - out.writeString(description); - out.writeList(parameterNames); - out.writeSerializable(function); - } - } - private class KeyboardUser implements KeyboardUi.User, MenuItem.OnMenuItemClickListener { @NonNull @Override diff --git a/app/src/main/java/org/solovyev/android/calculator/function/FunctionBuilderAdapter.java b/app/src/main/java/org/solovyev/android/calculator/function/FunctionBuilderAdapter.java deleted file mode 100644 index 41fa5e60..00000000 --- a/app/src/main/java/org/solovyev/android/calculator/function/FunctionBuilderAdapter.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2013 serso aka se.solovyev - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Contact details - * - * Email: se.solovyev@gmail.com - * Site: http://se.solovyev.org - */ - -package org.solovyev.android.calculator.function; - -import jscl.CustomFunctionCalculationException; -import jscl.math.function.CustomFunction; -import jscl.math.function.Function; -import org.solovyev.android.calculator.model.MathEntityBuilder; -import org.solovyev.android.calculator.model.OldFunction; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * User: serso - * Date: 1/20/13 - * Time: 12:21 PM - */ -public final class FunctionBuilderAdapter implements MathEntityBuilder { - - @Nonnull - private final OldFunction.Builder nestedBuilder; - - public FunctionBuilderAdapter(@Nonnull OldFunction.Builder nestedBuilder) { - this.nestedBuilder = nestedBuilder; - } - - @Nonnull - @Override - public MathEntityBuilder setName(@Nonnull String name) { - nestedBuilder.setName(name); - return this; - } - - @Nonnull - @Override - public MathEntityBuilder setDescription(@Nullable String description) { - nestedBuilder.setDescription(description); - return this; - } - - @Nonnull - @Override - public MathEntityBuilder setValue(@Nullable String value) { - nestedBuilder.setValue(value); - return this; - } - - @Nonnull - @Override - public Function create() throws CustomFunctionCalculationException, OldFunction.Builder.CreationException { - final OldFunction function = nestedBuilder.create(); - return new CustomFunction.Builder(function).create(); - } -} diff --git a/app/src/main/java/org/solovyev/android/calculator/function/FunctionEditorSaver.java b/app/src/main/java/org/solovyev/android/calculator/function/FunctionEditorSaver.java deleted file mode 100644 index e8195c80..00000000 --- a/app/src/main/java/org/solovyev/android/calculator/function/FunctionEditorSaver.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2013 serso aka se.solovyev - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Contact details - * - * Email: se.solovyev@gmail.com - * Site: http://se.solovyev.org - */ - -package org.solovyev.android.calculator.function; - -import android.view.View; -import android.widget.EditText; -import jscl.CustomFunctionCalculationException; -import jscl.math.function.Function; -import jscl.math.function.IFunction; -import org.solovyev.android.calculator.EntitiesRegistry; -import org.solovyev.android.calculator.FunctionsRegistry; -import org.solovyev.android.calculator.Locator; -import org.solovyev.android.calculator.R; -import org.solovyev.android.calculator.math.edit.VarEditorSaver; -import org.solovyev.android.calculator.model.OldFunction; -import org.solovyev.common.msg.MessageType; -import org.solovyev.common.text.Strings; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Collections; -import java.util.List; - -public class FunctionEditorSaver implements View.OnClickListener { - - @Nonnull - private final Object source; - - @Nonnull - private final OldFunction.Builder builder; - - @Nullable - private final IFunction editedInstance; - - @Nonnull - private final View view; - - public FunctionEditorSaver(@Nonnull OldFunction.Builder builder, - @Nullable IFunction editedInstance, - @Nonnull View view, - @Nonnull EntitiesRegistry registry, - @Nonnull Object source) { - - this.builder = builder; - this.editedInstance = editedInstance; - this.view = view; - this.source = source; - } - - @Nonnull - public static EditFunctionFragment.Input readInput(@Nullable IFunction function, @Nonnull View root) { - final EditText editName = (EditText) root.findViewById(R.id.function_name); - String name = editName.getText().toString(); - - final EditText editValue = (EditText) root.findViewById(R.id.function_body); - String content = editValue.getText().toString(); - - final EditText editDescription = (EditText) root.findViewById(R.id.function_description); - String description = editDescription.getText().toString(); - - final FunctionParamsView editParams = (FunctionParamsView) root.findViewById(R.id.function_params); - List parameterNames = editParams.getParams(); - - return EditFunctionFragment.Input.newInstance(function, name, content, description, parameterNames); - } - - @Override - public void onClick(View v) { - final Integer error; - - final EditFunctionFragment.Input input = readInput(null, view); - - final String name = input.getName(); - final String content = input.getContent(); - final String description = input.getDescription(); - - List parameterNames = input.getParameterNames(); - if (parameterNames == null) { - parameterNames = Collections.emptyList(); - } - - final FunctionsRegistry registry = Locator.getInstance().getEngine().getFunctionsRegistry(); - if (VarEditorSaver.isValidName(name)) { - - boolean canBeSaved = false; - - final Function entityFromRegistry = registry.get(name); - if (entityFromRegistry == null) { - canBeSaved = true; - } else if (editedInstance != null && entityFromRegistry.getId().equals(editedInstance.getId())) { - canBeSaved = true; - } - - if (canBeSaved) { - if (validateParameters(parameterNames)) { - - if (!Strings.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_param_not_empty; - } - } else { - error = R.string.function_already_exists; - } - } else { - error = R.string.function_name_is_not_valid; - } - - if (error != null) { - Locator.getInstance().getNotifier().showMessage(error, MessageType.error); - } else { - try { - registry.add(new FunctionBuilderAdapter(builder), editedInstance, source); - } catch (CustomFunctionCalculationException e) { - Locator.getInstance().getNotifier().showMessage(e); - } catch (OldFunction.Builder.CreationException e) { - Locator.getInstance().getNotifier().showMessage(e); - } - } - } - - private boolean validateParameters(@Nonnull List parameterNames) { - for (String parameterName : parameterNames) { - if (!VarEditorSaver.isValidName(parameterName)) { - return false; - } - } - - return true; - } - -} diff --git a/app/src/main/java/org/solovyev/android/calculator/history/HistoryState.java b/app/src/main/java/org/solovyev/android/calculator/history/HistoryState.java index 7ef8ac24..77724eb1 100644 --- a/app/src/main/java/org/solovyev/android/calculator/history/HistoryState.java +++ b/app/src/main/java/org/solovyev/android/calculator/history/HistoryState.java @@ -1,9 +1,9 @@ package org.solovyev.android.calculator.history; -import android.annotation.SuppressLint; import android.os.Parcel; import android.os.Parcelable; import android.support.annotation.NonNull; + import org.json.JSONException; import org.json.JSONObject; import org.solovyev.android.Check; @@ -173,17 +173,18 @@ public class HistoryState implements Parcelable, Jsonable { dest.writeString(comment); } - @SuppressLint("ParcelCreator") - public static final class Builder extends HistoryState { + public static final class Builder { + @NonNull + private final HistoryState state; private boolean built; private Builder(@Nonnull EditorState editor, @Nonnull DisplayState display) { - super(editor, display); + this.state = new HistoryState(editor, display); } private Builder(@Nonnull HistoryState state, boolean newState) { - super(state, newState); + this.state = new HistoryState(state, newState); if (newState) { withTime(now()); } @@ -192,21 +193,21 @@ public class HistoryState implements Parcelable, Jsonable { @Nonnull public Builder withTime(long time) { Check.isTrue(!built); - this.time = time; + state.time = time; return this; } @Nonnull public Builder withComment(@Nullable String comment) { Check.isTrue(!built); - this.comment = comment == null ? "" : comment; + state.comment = comment == null ? "" : comment; return this; } @Nonnull public HistoryState build() { built = true; - return this; + return state; } } } diff --git a/app/src/main/java/org/solovyev/android/calculator/math/edit/BaseEntitiesFragment.java b/app/src/main/java/org/solovyev/android/calculator/math/edit/BaseEntitiesFragment.java index 230027c4..086d9519 100644 --- a/app/src/main/java/org/solovyev/android/calculator/math/edit/BaseEntitiesFragment.java +++ b/app/src/main/java/org/solovyev/android/calculator/math/edit/BaseEntitiesFragment.java @@ -31,26 +31,44 @@ import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.text.ClipboardManager; import android.text.TextUtils; -import android.view.*; +import android.view.ContextMenu; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; import android.widget.TextView; -import butterknife.Bind; -import butterknife.ButterKnife; + import com.melnykov.fab.FloatingActionButton; + import org.solovyev.android.Check; -import org.solovyev.android.calculator.*; +import org.solovyev.android.calculator.BaseFragment; +import org.solovyev.android.calculator.CalculatorFragmentType; +import org.solovyev.android.calculator.R; import org.solovyev.android.views.llm.DividerItemDecoration; import org.solovyev.common.math.MathEntity; import org.solovyev.common.text.Strings; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import java.util.Collections; +import java.util.Comparator; import java.util.Iterator; import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; -public abstract class BaseEntitiesFragment extends BaseFragment implements CalculatorEventListener { +import butterknife.Bind; +import butterknife.ButterKnife; + + +public abstract class BaseEntitiesFragment extends BaseFragment { public static final String EXTRA_CATEGORY = "category"; + private static final Comparator COMPARATOR = new Comparator() { + @Override + public int compare(MathEntity l, MathEntity r) { + return l.getName().compareTo(r.getName()); + } + }; @Nonnull private final Handler uiHandler = new Handler(); @@ -58,7 +76,6 @@ public abstract class BaseEntitiesFragment extends BaseFra FloatingActionButton fab; @Bind(R.id.entities_recyclerview) RecyclerView recyclerView; - @Nullable private EntitiesAdapter adapter; @Nullable private String category; @@ -132,40 +149,6 @@ public abstract class BaseEntitiesFragment extends BaseFra @Nullable abstract String getCategory(@Nonnull E e); - protected void sort() { - /* - final EntitiesAdapter localAdapter = adapter; - if (localAdapter != null) { - localAdapter.sort(new Comparator() { - @Override - public int compare(E function1, E function2) { - return function1.getName().compareTo(function2.getName()); - } - }); - - localAdapter.notifyDataSetChanged(); - }*/ - } - - public void addToAdapter(@Nonnull E mathEntity) { - if (this.adapter != null) { - //this.adapter.add(mathEntity); - } - } - - public void removeFromAdapter(@Nonnull E mathEntity) { - if (this.adapter != null) { - //this.adapter.remove(mathEntity); - } - } - - public void notifyAdapter() { - if (this.adapter != null) { - this.adapter.notifyDataSetChanged(); - } - } - - @Nullable protected EntitiesAdapter getAdapter() { return adapter; } @@ -175,10 +158,22 @@ public abstract class BaseEntitiesFragment extends BaseFra return uiHandler; } - @Override - public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) { + @SuppressWarnings("deprecation") + protected final void copyDescription(@Nonnull E entity) { + final String description = getDescription(entity); + if (!Strings.isEmpty(description)) { + final ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(Activity.CLIPBOARD_SERVICE); + clipboard.setText(description); + } } + @Nullable + protected abstract String getDescription(@NonNull E entity); + + protected abstract void onCreateContextMenu(@Nonnull ContextMenu menu, @Nonnull E entity, @Nonnull MenuItem.OnMenuItemClickListener listener); + + protected abstract boolean onMenuItemClicked(@Nonnull MenuItem item, @Nonnull E entity); + public class EntityViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener { @Bind(R.id.entity_text) TextView textView; @@ -226,20 +221,6 @@ public abstract class BaseEntitiesFragment extends BaseFra } } - @SuppressWarnings("deprecation") - protected final void copyDescription(@Nonnull E entity) { - final String description = getDescription(entity); - if (!Strings.isEmpty(description)) { - final ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(Activity.CLIPBOARD_SERVICE); - clipboard.setText(description); - } - } - - @Nullable - protected abstract String getDescription(@NonNull E entity); - protected abstract void onCreateContextMenu(@Nonnull ContextMenu menu, @Nonnull E entity, @Nonnull MenuItem.OnMenuItemClickListener listener); - protected abstract boolean onMenuItemClicked(@Nonnull MenuItem item, @Nonnull E entity); - public class EntitiesAdapter extends RecyclerView.Adapter { @Nonnull private final LayoutInflater inflater; @@ -271,5 +252,22 @@ public abstract class BaseEntitiesFragment extends BaseFra public E getItem(int position) { return list.get(position); } + + public void set(int position, @Nonnull E function) { + list.set(position, function); + } + + public void sort() { + Collections.sort(list, COMPARATOR); + notifyDataSetChanged(); + } + + public void add(@Nonnull E entity) { + list.add(entity); + } + + public void remove(@Nonnull E function) { + list.remove(function); + } } } diff --git a/app/src/main/java/org/solovyev/android/calculator/math/edit/CalculatorFunctionsActivity.java b/app/src/main/java/org/solovyev/android/calculator/math/edit/CalculatorFunctionsActivity.java index 4d611655..b59b0640 100644 --- a/app/src/main/java/org/solovyev/android/calculator/math/edit/CalculatorFunctionsActivity.java +++ b/app/src/main/java/org/solovyev/android/calculator/math/edit/CalculatorFunctionsActivity.java @@ -24,12 +24,16 @@ package org.solovyev.android.calculator.math.edit; import android.os.Bundle; import android.util.Log; -import org.solovyev.android.calculator.*; -import javax.annotation.Nonnull; +import org.solovyev.android.calculator.AndroidFunctionCategory; +import org.solovyev.android.calculator.BaseActivity; +import org.solovyev.android.calculator.CalculatorFragmentType; +import org.solovyev.android.calculator.FunctionCategory; +import org.solovyev.android.calculator.R; + import javax.annotation.Nullable; -public class CalculatorFunctionsActivity extends BaseActivity implements CalculatorEventListener { +public class CalculatorFunctionsActivity extends BaseActivity { public CalculatorFunctionsActivity() { super(R.layout.main_empty, CalculatorFunctionsActivity.class.getSimpleName()); @@ -62,13 +66,4 @@ public class CalculatorFunctionsActivity extends BaseActivity implements Calcula } } } - - @Override - public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) { - switch (calculatorEventType) { - case use_function: - this.finish(); - break; - } - } } diff --git a/app/src/main/java/org/solovyev/android/calculator/math/edit/FunctionsFragment.java b/app/src/main/java/org/solovyev/android/calculator/math/edit/FunctionsFragment.java index 0b57b72a..71eb8eeb 100644 --- a/app/src/main/java/org/solovyev/android/calculator/math/edit/FunctionsFragment.java +++ b/app/src/main/java/org/solovyev/android/calculator/math/edit/FunctionsFragment.java @@ -26,24 +26,46 @@ import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.FragmentActivity; import android.view.ContextMenu; +import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; -import jscl.math.function.Function; -import jscl.math.function.IFunction; -import org.solovyev.android.calculator.*; +import android.view.ViewGroup; + +import com.squareup.otto.Bus; +import com.squareup.otto.Subscribe; + +import org.solovyev.android.calculator.AppComponent; +import org.solovyev.android.calculator.Calculator; +import org.solovyev.android.calculator.CalculatorFragmentType; +import org.solovyev.android.calculator.EntitiesRegistry; +import org.solovyev.android.calculator.FunctionsRegistry; +import org.solovyev.android.calculator.Keyboard; +import org.solovyev.android.calculator.R; +import org.solovyev.android.calculator.function.CppFunction; import org.solovyev.android.calculator.function.EditFunctionFragment; import org.solovyev.common.text.Strings; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.inject.Inject; + +import jscl.math.function.Function; +import jscl.math.function.IFunction; + public class FunctionsFragment extends BaseEntitiesFragment { public static final String EXTRA_FUNCTION = "function"; - @NonNull - private final EntitiesRegistry registry = Locator.getInstance().getEngine().getFunctionsRegistry(); + @Inject + FunctionsRegistry registry; + @Inject + Calculator calculator; + @Inject + Keyboard keyboard; + @Inject + Bus bus; public FunctionsFragment() { super(CalculatorFragmentType.functions); @@ -55,15 +77,28 @@ public class FunctionsFragment extends BaseEntitiesFragment { final Bundle bundle = getArguments(); if (bundle != null) { - final EditFunctionFragment.Input input = bundle.getParcelable(EXTRA_FUNCTION); - if (input != null) { - EditFunctionFragment.showDialog(input, getFragmentManager()); + final CppFunction function = bundle.getParcelable(EXTRA_FUNCTION); + if (function != null) { + EditFunctionFragment.showDialog(function, getFragmentManager()); // in order to stop intent for other tabs bundle.remove(EXTRA_FUNCTION); } } } + @Override + protected void inject(@Nonnull AppComponent component) { + super.inject(component); + component.inject(this); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + final View view = super.onCreateView(inflater, container, savedInstanceState); + bus.register(this); + return view; + } + @Override public void onViewCreated(View root, Bundle savedInstanceState) { super.onViewCreated(root, savedInstanceState); @@ -73,14 +108,18 @@ public class FunctionsFragment extends BaseEntitiesFragment { fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - EditFunctionFragment.showDialog(EditFunctionFragment.Input.newInstance(), getFragmentManager()); + EditFunctionFragment.showDialog(getActivity()); } }); } @Override - protected void onClick(@NonNull @Nonnull Function function) { - Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.use_function, function); + protected void onClick(@Nonnull Function function) { + keyboard.buttonPressed(function.getName()); + final FragmentActivity activity = getActivity(); + if (activity instanceof CalculatorFunctionsActivity) { + activity.finish(); + } } @Override @@ -102,15 +141,15 @@ public class FunctionsFragment extends BaseEntitiesFragment { final FragmentActivity activity = getActivity(); switch (item.getItemId()) { case R.string.c_use: - Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.use_function, function); + onClick(function); return true; case R.string.c_edit: if (function instanceof IFunction) { - EditFunctionFragment.showDialog(EditFunctionFragment.Input.newFromFunction((IFunction) function), activity.getSupportFragmentManager()); + EditFunctionFragment.showDialog(CppFunction.builder((IFunction) function).build(), activity.getSupportFragmentManager()); } return true; case R.string.c_remove: - MathEntityRemover.newFunctionRemover(function, null, activity, activity).showConfirmationDialog(); + // todo serso: return true; case R.string.c_copy_description: copyDescription(function); @@ -131,22 +170,48 @@ public class FunctionsFragment extends BaseEntitiesFragment { } @Override - public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) { - super.onCalculatorEvent(calculatorEventData, calculatorEventType, data); + public void onDestroyView() { + bus.unregister(this); + super.onDestroyView(); + } - switch (calculatorEventType) { - case function_added: - processFunctionAdded((Function) data); - break; - - case function_changed: - processFunctionChanged((Change) data); - break; - - case function_removed: - processFunctionRemoved((Function) data); - break; + @Subscribe + public void onFunctionAdded(@NonNull final FunctionsRegistry.AddedEvent event) { + if (!isInCategory(event.function)) { + return; } + final EntitiesAdapter adapter = getAdapter(); + adapter.add(event.function); + adapter.sort(); + } + + @Subscribe + public void onFunctionChanged(@NonNull final FunctionsRegistry.ChangedEvent event) { + if (!isInCategory(event.newFunction)) { + return; + } + if (!event.oldFunction.isIdDefined()) { + return; + } + final EntitiesAdapter adapter = getAdapter(); + if (adapter == null) { + return; + } + for (int i = 0; i < adapter.getItemCount(); i++) { + final Function adapterFunction = adapter.getItem(i); + if (adapterFunction.isIdDefined() && event.oldFunction.getId().equals(adapterFunction.getId())) { + adapter.set(i, adapterFunction); + break; + } + } + adapter.sort(); + } + + @Subscribe + public void onFunctionRemoved(@NonNull final FunctionsRegistry.RemovedEvent event) { + final EntitiesAdapter adapter = getAdapter(); + adapter.remove(event.function); + adapter.notifyDataSetChanged(); } @Nullable @@ -154,64 +219,4 @@ public class FunctionsFragment extends BaseEntitiesFragment { protected String getDescription(@NonNull Function function) { return registry.getDescription(function.getName()); } - - - private void processFunctionRemoved(@Nonnull final Function function) { - if (this.isInCategory(function)) { - getUiHandler().post(new Runnable() { - @Override - public void run() { - removeFromAdapter(function); - notifyAdapter(); - } - }); - } - } - - private void processFunctionChanged(@Nonnull final Change change) { - final IFunction newFunction = change.getNewValue(); - - if (newFunction instanceof Function) { - - if (this.isInCategory((Function) newFunction)) { - - getUiHandler().post(new Runnable() { - @Override - public void run() { - IFunction oldValue = change.getOldValue(); - - if (oldValue.isIdDefined()) { - final EntitiesAdapter adapter = getAdapter(); - if (adapter != null) { - for (int i = 0; i < adapter.getItemCount(); i++) { - final Function functionFromAdapter = adapter.getItem(i); - if (functionFromAdapter.isIdDefined() && oldValue.getId().equals(functionFromAdapter.getId())) { - //adapter.remove(functionFromAdapter); - break; - } - } - } - } - - addToAdapter((Function) newFunction); - sort(); - } - }); - } - } else { - throw new IllegalArgumentException("Function must be instance of jscl.math.function.Function class!"); - } - } - - private void processFunctionAdded(@Nonnull final Function function) { - if (this.isInCategory(function)) { - getUiHandler().post(new Runnable() { - @Override - public void run() { - addToAdapter(function); - sort(); - } - }); - } - } } diff --git a/app/src/main/java/org/solovyev/android/calculator/math/edit/MathEntityRemover.java b/app/src/main/java/org/solovyev/android/calculator/math/edit/MathEntityRemover.java index 84e01c29..3872e0ea 100644 --- a/app/src/main/java/org/solovyev/android/calculator/math/edit/MathEntityRemover.java +++ b/app/src/main/java/org/solovyev/android/calculator/math/edit/MathEntityRemover.java @@ -37,7 +37,6 @@ import org.solovyev.common.math.MathEntity; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import jscl.math.function.Function; import jscl.math.function.IConstant; /** @@ -95,14 +94,7 @@ public class MathEntityRemover implements View.OnClickList return new MathEntityRemover(constant, callbackOnCancel, false, Locator.getInstance().getEngine().getVarsRegistry(), context, source, Params.newConstantInstance()); } - public static MathEntityRemover newFunctionRemover(@Nonnull Function function, - @Nullable DialogInterface.OnClickListener callbackOnCancel, - @Nonnull Context context, - @Nonnull Object source) { - return new MathEntityRemover(function, callbackOnCancel, false, Locator.getInstance().getEngine().getFunctionsRegistry(), context, source, Params.newFunctionInstance()); - } - - /* + /* ********************************************************************** * * METHODS @@ -169,14 +161,6 @@ public class MathEntityRemover implements View.OnClickList return result; } - private static Params newFunctionInstance() { - final Params result = new Params(); - result.removalConfirmationTitleResId = R.string.removal_confirmation; - result.removalConfirmationQuestionResId = R.string.function_removal_confirmation_question; - result.calculatorEventType = CalculatorEventType.function_removed; - return result; - } - public int getRemovalConfirmationTitleResId() { return removalConfirmationTitleResId; } diff --git a/app/src/main/java/org/solovyev/android/calculator/math/edit/OperatorsFragment.java b/app/src/main/java/org/solovyev/android/calculator/math/edit/OperatorsFragment.java index d8cbfad8..600dde92 100644 --- a/app/src/main/java/org/solovyev/android/calculator/math/edit/OperatorsFragment.java +++ b/app/src/main/java/org/solovyev/android/calculator/math/edit/OperatorsFragment.java @@ -26,14 +26,21 @@ import android.support.annotation.NonNull; import android.text.TextUtils; import android.view.ContextMenu; import android.view.MenuItem; -import jscl.math.operator.Operator; -import org.solovyev.android.calculator.*; + +import org.solovyev.android.calculator.CalculatorEventType; +import org.solovyev.android.calculator.CalculatorFragmentType; +import org.solovyev.android.calculator.EntitiesRegistry; +import org.solovyev.android.calculator.Locator; +import org.solovyev.android.calculator.R; import org.solovyev.common.text.Strings; +import java.util.ArrayList; +import java.util.List; + import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; + +import jscl.math.operator.Operator; public class OperatorsFragment extends BaseEntitiesFragment { diff --git a/app/src/main/java/org/solovyev/android/calculator/math/edit/VarsFragment.java b/app/src/main/java/org/solovyev/android/calculator/math/edit/VarsFragment.java index e9742224..28ece235 100644 --- a/app/src/main/java/org/solovyev/android/calculator/math/edit/VarsFragment.java +++ b/app/src/main/java/org/solovyev/android/calculator/math/edit/VarsFragment.java @@ -28,20 +28,34 @@ import android.support.v4.app.FragmentActivity; import android.view.ContextMenu; import android.view.MenuItem; import android.view.View; + import com.melnykov.fab.FloatingActionButton; -import jscl.math.function.IConstant; -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.CalculatorFragmentType; +import org.solovyev.android.calculator.CalculatorParseException; +import org.solovyev.android.calculator.Change; +import org.solovyev.android.calculator.EntitiesRegistry; +import org.solovyev.android.calculator.Locator; +import org.solovyev.android.calculator.PreparedExpression; +import org.solovyev.android.calculator.R; +import org.solovyev.android.calculator.ToJsclTextProcessor; import org.solovyev.android.calculator.math.MathType; import org.solovyev.common.JPredicate; import org.solovyev.common.collections.Collections; import org.solovyev.common.text.Strings; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; -public class VarsFragment extends BaseEntitiesFragment { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import jscl.math.function.IConstant; + +public class VarsFragment extends BaseEntitiesFragmentimplements CalculatorEventListener { public static final String CREATE_VAR_EXTRA_STRING = "create_var"; @NonNull @@ -128,8 +142,6 @@ public class VarsFragment extends BaseEntitiesFragment { @Override public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) { - super.onCalculatorEvent(calculatorEventData, calculatorEventType, data); - switch (calculatorEventType) { case constant_added: processConstantAdded((IConstant) data); @@ -196,8 +208,9 @@ public class VarsFragment extends BaseEntitiesFragment { getUiHandler().post(new Runnable() { @Override public void run() { - removeFromAdapter(constant); - notifyAdapter(); + final EntitiesAdapter adapter = getAdapter(); + adapter.remove(constant); + adapter.notifyDataSetChanged(); } }); } @@ -209,9 +222,10 @@ public class VarsFragment extends BaseEntitiesFragment { getUiHandler().post(new Runnable() { @Override public void run() { - removeFromAdapter(change.getOldValue()); - addToAdapter(newConstant); - sort(); + final EntitiesAdapter adapter = getAdapter(); + adapter.remove(change.getOldValue()); + adapter.add(newConstant); + adapter.sort(); } }); } @@ -222,8 +236,9 @@ public class VarsFragment extends BaseEntitiesFragment { getUiHandler().post(new Runnable() { @Override public void run() { - addToAdapter(constant); - sort(); + final EntitiesAdapter adapter = getAdapter(); + adapter.add(constant); + adapter.sort(); } }); }