new plotter
This commit is contained in:
@@ -12,7 +12,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public class AndroidCalculatorLogger implements CalculatorLogger {
|
||||
|
||||
@NotNull
|
||||
private static final String TAG = AndroidCalculatorLogger.class.getSimpleName();
|
||||
private static final String TAG = "Calculatorpp";
|
||||
|
||||
@Override
|
||||
public void debug(@Nullable String tag, @NotNull String message) {
|
||||
@@ -21,7 +21,7 @@ public class AndroidCalculatorLogger implements CalculatorLogger {
|
||||
|
||||
@NotNull
|
||||
private String getTag(@Nullable String tag) {
|
||||
return tag != null ? tag : TAG;
|
||||
return tag != null ? TAG + "/" + tag : TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -25,6 +25,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.AndroidUtils;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
import org.solovyev.android.calculator.about.CalculatorReleaseNotesFragment;
|
||||
import org.solovyev.android.calculator.plot.CalculatorPlotActivity;
|
||||
import org.solovyev.android.fragments.FragmentUtils;
|
||||
import org.solovyev.android.prefs.Preference;
|
||||
import org.solovyev.common.equals.EqualsTool;
|
||||
@@ -63,7 +64,7 @@ public class CalculatorActivity extends SherlockFragmentActivity implements Shar
|
||||
activityHelper.addTab(this, CalculatorFragmentType.variables, null, R.id.main_second_pane);
|
||||
activityHelper.addTab(this, CalculatorFragmentType.functions, null, R.id.main_second_pane);
|
||||
activityHelper.addTab(this, CalculatorFragmentType.operators, null, R.id.main_second_pane);
|
||||
activityHelper.addTab(this, CalculatorFragmentType.plotter, null, R.id.main_second_pane);
|
||||
activityHelper.addTab(this, CalculatorPlotActivity.getPlotterFragmentType(), null, R.id.main_second_pane);
|
||||
activityHelper.addTab(this, CalculatorFragmentType.faq, null, R.id.main_second_pane);
|
||||
} else {
|
||||
getSupportActionBar().hide();
|
||||
|
@@ -23,6 +23,7 @@ import org.solovyev.android.calculator.help.CalculatorHelpActivity;
|
||||
import org.solovyev.android.calculator.history.CalculatorHistoryActivity;
|
||||
import org.solovyev.android.calculator.math.edit.*;
|
||||
import org.solovyev.android.calculator.matrix.CalculatorMatrixActivity;
|
||||
import org.solovyev.android.calculator.plot.AbstractCalculatorPlotFragment;
|
||||
import org.solovyev.android.calculator.plot.CalculatorPlotActivity;
|
||||
import org.solovyev.android.calculator.plot.CalculatorPlotFragment;
|
||||
import org.solovyev.android.calculator.plot.PlotInput;
|
||||
@@ -99,10 +100,14 @@ public final class CalculatorActivityLauncher implements CalculatorEventListener
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
public static void plotGraph(@NotNull final Context context, @NotNull Generic generic, @NotNull Constant constant){
|
||||
public static void plotGraph(@NotNull final Context context,
|
||||
@NotNull Generic generic,
|
||||
@NotNull Constant xVariable,
|
||||
@Nullable Constant yVariable){
|
||||
final Intent intent = new Intent();
|
||||
intent.putExtra(ChartFactory.TITLE, context.getString(R.string.c_graph));
|
||||
intent.putExtra(CalculatorPlotFragment.INPUT, new CalculatorPlotFragment.Input(generic.toString(), constant.getName()));
|
||||
final AbstractCalculatorPlotFragment.Input input = new CalculatorPlotFragment.Input(generic.toString(), xVariable.getName(), yVariable == null ? null : yVariable.getName());
|
||||
intent.putExtra(CalculatorPlotFragment.INPUT, input);
|
||||
intent.setClass(context, CalculatorPlotActivity.class);
|
||||
AndroidUtils2.addFlags(intent, false, context);
|
||||
context.startActivity(intent);
|
||||
@@ -214,7 +219,7 @@ public final class CalculatorActivityLauncher implements CalculatorEventListener
|
||||
App.getInstance().getUiThreadExecutor().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
plotGraph(context, plotInput.getFunction(), plotInput.getConstant());
|
||||
plotGraph(context, plotInput.getFunction(), plotInput.getXVariable(), plotInput.getYVariable());
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
@@ -3,6 +3,7 @@ package org.solovyev.android.calculator;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import net.robotmedia.billing.BillingController;
|
||||
@@ -65,8 +66,12 @@ public class CalculatorApplication extends android.app.Application implements Sh
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@NotNull
|
||||
private final List<CalculatorEventListener> listeners = new ArrayList<CalculatorEventListener>();
|
||||
|
||||
@NotNull
|
||||
protected final Handler uiHandler = new Handler();
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
@@ -186,6 +191,11 @@ public class CalculatorApplication extends android.app.Application implements Sh
|
||||
return new CalculatorFragmentHelperImpl(layoutId, titleResId, listenersOnCreate);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Handler getUiHandler() {
|
||||
return uiHandler;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
|
@@ -13,6 +13,7 @@ import org.solovyev.android.calculator.math.edit.CalculatorFunctionsFragment;
|
||||
import org.solovyev.android.calculator.math.edit.CalculatorOperatorsFragment;
|
||||
import org.solovyev.android.calculator.math.edit.CalculatorVarsFragment;
|
||||
import org.solovyev.android.calculator.matrix.CalculatorMatrixEditFragment;
|
||||
import org.solovyev.android.calculator.plot.CalculatorArityPlotFragment;
|
||||
import org.solovyev.android.calculator.plot.CalculatorPlotFragment;
|
||||
|
||||
/**
|
||||
@@ -31,6 +32,7 @@ public enum CalculatorFragmentType {
|
||||
functions(CalculatorFunctionsFragment.class, R.layout.math_entities_fragment, R.string.c_functions),
|
||||
operators(CalculatorOperatorsFragment.class, R.layout.math_entities_fragment, R.string.c_operators),
|
||||
plotter(CalculatorPlotFragment.class, R.layout.plot_fragment, R.string.c_graph),
|
||||
plotter_2(CalculatorArityPlotFragment.class, R.layout.plot_fragment, R.string.c_graph),
|
||||
about(CalculatorAboutFragment.class, R.layout.about_fragment, R.string.c_about),
|
||||
faq(CalculatorHelpFaqFragment.class, R.layout.help_faq_fragment, R.string.c_faq),
|
||||
hints(CalculatorHelpHintsFragment.class, R.layout.help_hints_fragment, R.string.c_hints),
|
||||
|
@@ -0,0 +1,525 @@
|
||||
package org.solovyev.android.calculator.plot;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
import jscl.math.Expression;
|
||||
import jscl.math.Generic;
|
||||
import jscl.math.function.Constant;
|
||||
import jscl.text.ParseException;
|
||||
import org.achartengine.renderer.XYMultipleSeriesRenderer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.menu.ActivityMenu;
|
||||
import org.solovyev.android.menu.IdentifiableMenuItem;
|
||||
import org.solovyev.android.menu.ListActivityMenu;
|
||||
import org.solovyev.android.sherlock.menu.SherlockMenuHelper;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/30/12
|
||||
* Time: 3:09 PM
|
||||
*/
|
||||
public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment implements CalculatorEventListener {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTANTS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
protected static final String TAG = "CalculatorPlotFragment";
|
||||
|
||||
public static final String INPUT = "plotter_input";
|
||||
|
||||
protected static final String PLOT_BOUNDARIES = "plot_boundaries";
|
||||
|
||||
private static final int DEFAULT_MIN_NUMBER = -10;
|
||||
|
||||
private static final int DEFAULT_MAX_NUMBER = 10;
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* FIELDS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nullable
|
||||
private Input input;
|
||||
|
||||
private int bgColor;
|
||||
|
||||
// thread for applying UI changes
|
||||
@NotNull
|
||||
private final Handler uiHandler = new Handler();
|
||||
|
||||
@NotNull
|
||||
private PreparedInput preparedInput;
|
||||
|
||||
@NotNull
|
||||
private ActivityMenu<Menu, MenuItem> fragmentMenu = ListActivityMenu.fromResource(R.menu.plot_menu, PlotMenu.class, SherlockMenuHelper.getInstance());
|
||||
|
||||
// thread which calculated data for graph view
|
||||
@NotNull
|
||||
private final Executor plotExecutor = Executors.newSingleThreadExecutor();
|
||||
|
||||
@NotNull
|
||||
private final CalculatorEventHolder lastEventHolder = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
|
||||
|
||||
|
||||
public AbstractCalculatorPlotFragment() {
|
||||
super(CalculatorApplication.getInstance().createFragmentHelper(R.layout.plot_fragment, R.string.c_graph, false));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final Bundle arguments = getArguments();
|
||||
|
||||
if (arguments != null) {
|
||||
input = (CalculatorPlotFragment.Input) arguments.getSerializable(INPUT);
|
||||
}
|
||||
|
||||
if (input == null) {
|
||||
this.bgColor = getResources().getColor(R.color.cpp_pane_background);
|
||||
} else {
|
||||
this.bgColor = getResources().getColor(android.R.color.transparent);
|
||||
}
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
if (input == null) {
|
||||
this.preparedInput = prepareInputFromDisplay(Locator.getInstance().getDisplay().getViewState(), savedInstanceState);
|
||||
} else {
|
||||
this.preparedInput = prepareInput(input, true, savedInstanceState);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle out) {
|
||||
super.onSaveInstanceState(out);
|
||||
|
||||
final PlotBoundaries plotBoundaries = getPlotBoundaries();
|
||||
if (plotBoundaries != null) {
|
||||
out.putSerializable(PLOT_BOUNDARIES, plotBoundaries);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract PlotBoundaries getPlotBoundaries();
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
createChart(preparedInput);
|
||||
createGraphicalView(getView(), preparedInput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable final Object data) {
|
||||
if (calculatorEventType.isOfType(CalculatorEventType.display_state_changed)) {
|
||||
PreparedInput preparedInput = getPreparedInput();
|
||||
if (!preparedInput.isFromInputArgs()) {
|
||||
|
||||
final CalculatorEventHolder.Result result = this.lastEventHolder.apply(calculatorEventData);
|
||||
if (result.isNewAfter()) {
|
||||
preparedInput = prepareInputFromDisplay(((CalculatorDisplayChangeEventData) data).getNewValue(), null);
|
||||
this.preparedInput = preparedInput;
|
||||
|
||||
|
||||
final PreparedInput finalPreparedInput = preparedInput;
|
||||
getUiHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if (!finalPreparedInput.isError()) {
|
||||
createChart(finalPreparedInput);
|
||||
|
||||
final View view = getView();
|
||||
if (view != null) {
|
||||
createGraphicalView(view, finalPreparedInput);
|
||||
}
|
||||
} else {
|
||||
onError();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void onError();
|
||||
|
||||
protected abstract void createGraphicalView(@NotNull View view, @NotNull PreparedInput preparedInput);
|
||||
|
||||
protected abstract void createChart(@NotNull PreparedInput preparedInput);
|
||||
|
||||
|
||||
protected double getMaxValue(@Nullable PlotBoundaries plotBoundaries) {
|
||||
return plotBoundaries == null ? DEFAULT_MAX_NUMBER : plotBoundaries.getXMax();
|
||||
}
|
||||
|
||||
protected double getMinValue(@Nullable PlotBoundaries plotBoundaries) {
|
||||
return plotBoundaries == null ? DEFAULT_MIN_NUMBER : plotBoundaries.getXMin();
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* GETTERS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@NotNull
|
||||
public Handler getUiHandler() {
|
||||
return uiHandler;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PreparedInput getPreparedInput() {
|
||||
return preparedInput;
|
||||
}
|
||||
|
||||
public int getBgColor() {
|
||||
return bgColor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Executor getPlotExecutor() {
|
||||
return plotExecutor;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* MENU
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
|
||||
final FragmentActivity activity = this.getActivity();
|
||||
if (activity != null) {
|
||||
fragmentMenu.onCreateOptionsMenu(activity, menu);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
|
||||
final FragmentActivity activity = this.getActivity();
|
||||
if (activity != null) {
|
||||
fragmentMenu.onPrepareOptionsMenu(activity, menu);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
return super.onOptionsItemSelected(item) || fragmentMenu.onOptionsItemSelected(this.getActivity(), item);
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@NotNull
|
||||
protected static PreparedInput prepareInputFromDisplay(@NotNull CalculatorDisplayViewState displayState, @Nullable Bundle savedInstanceState) {
|
||||
try {
|
||||
if (displayState.isValid() && displayState.getResult() != null) {
|
||||
final Generic expression = displayState.getResult();
|
||||
if (CalculatorUtils.isPlotPossible(expression, displayState.getOperation())) {
|
||||
final List<Constant> variables = new ArrayList<Constant>(CalculatorUtils.getNotSystemConstants(expression));
|
||||
final Constant xVariable = variables.get(0);
|
||||
|
||||
final Constant yVariable;
|
||||
if ( variables.size() > 1 ) {
|
||||
yVariable = variables.get(1);
|
||||
} else {
|
||||
yVariable = null;
|
||||
}
|
||||
|
||||
final Input input = new Input(expression.toString(), xVariable.getName(), yVariable == null ? null : yVariable.getName());
|
||||
return prepareInput(input, false, savedInstanceState);
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG, e.getLocalizedMessage(), e);
|
||||
}
|
||||
|
||||
return PreparedInput.newErrorInstance(false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PreparedInput prepareInput(@NotNull Input input, boolean fromInputArgs, @Nullable Bundle savedInstanceState) {
|
||||
PreparedInput result;
|
||||
|
||||
try {
|
||||
final PreparedExpression preparedExpression = ToJsclTextProcessor.getInstance().process(input.getExpression());
|
||||
final Generic expression = Expression.valueOf(preparedExpression.getExpression());
|
||||
final Constant xVar = new Constant(input.getXVariableName());
|
||||
|
||||
final Constant yVar;
|
||||
if (input.getYVariableName() != null) {
|
||||
yVar = new Constant(input.getYVariableName());
|
||||
} else {
|
||||
yVar = null;
|
||||
}
|
||||
|
||||
PlotBoundaries plotBoundaries = null;
|
||||
if (savedInstanceState != null) {
|
||||
plotBoundaries = (PlotBoundaries) savedInstanceState.getSerializable(PLOT_BOUNDARIES);
|
||||
}
|
||||
|
||||
if ( plotBoundaries == null ) {
|
||||
plotBoundaries = PlotBoundaries.newDefaultInstance();
|
||||
}
|
||||
|
||||
result = PreparedInput.newInstance(input, expression, xVar, yVar, fromInputArgs, plotBoundaries);
|
||||
} catch (ParseException e) {
|
||||
result = PreparedInput.newErrorInstance(fromInputArgs);
|
||||
Locator.getInstance().getNotifier().showMessage(e);
|
||||
} catch (CalculatorParseException e) {
|
||||
result = PreparedInput.newErrorInstance(fromInputArgs);
|
||||
Locator.getInstance().getNotifier().showMessage(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static enum PlotMenu implements IdentifiableMenuItem<MenuItem> {
|
||||
|
||||
preferences(R.id.menu_plot_settings) {
|
||||
@Override
|
||||
public void onClick(@NotNull MenuItem data, @NotNull Context context) {
|
||||
context.startActivity(new Intent(context, CalculatorPlotPreferenceActivity.class));
|
||||
}
|
||||
};
|
||||
|
||||
private final int itemId;
|
||||
|
||||
private PlotMenu(int itemId) {
|
||||
this.itemId = itemId;
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Integer getItemId() {
|
||||
return itemId;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class PlotBoundaries implements Serializable {
|
||||
|
||||
private double xMin;
|
||||
private double xMax;
|
||||
private double yMin;
|
||||
private double yMax;
|
||||
|
||||
public PlotBoundaries() {
|
||||
}
|
||||
|
||||
public PlotBoundaries(@NotNull XYMultipleSeriesRenderer renderer) {
|
||||
this.xMin = renderer.getXAxisMin();
|
||||
this.yMin = renderer.getYAxisMin();
|
||||
this.xMax = renderer.getXAxisMax();
|
||||
this.yMax = renderer.getYAxisMax();
|
||||
}
|
||||
|
||||
public double getXMin() {
|
||||
return xMin;
|
||||
}
|
||||
|
||||
public double getXMax() {
|
||||
return xMax;
|
||||
}
|
||||
|
||||
public double getYMin() {
|
||||
return yMin;
|
||||
}
|
||||
|
||||
public double getYMax() {
|
||||
return yMax;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PlotBoundaries{" +
|
||||
"yMax=" + yMax +
|
||||
", yMin=" + yMin +
|
||||
", xMax=" + xMax +
|
||||
", xMin=" + xMin +
|
||||
'}';
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PlotBoundaries newDefaultInstance() {
|
||||
PlotBoundaries plotBoundaries = new PlotBoundaries();
|
||||
plotBoundaries.xMin = DEFAULT_MIN_NUMBER;
|
||||
plotBoundaries.yMin = DEFAULT_MIN_NUMBER;
|
||||
plotBoundaries.xMax = DEFAULT_MAX_NUMBER;
|
||||
plotBoundaries.yMax = DEFAULT_MAX_NUMBER;
|
||||
return plotBoundaries;
|
||||
}
|
||||
}
|
||||
|
||||
public static class PreparedInput {
|
||||
|
||||
@Nullable
|
||||
private Input input;
|
||||
|
||||
@Nullable
|
||||
private Generic expression;
|
||||
|
||||
@Nullable
|
||||
private Constant xVariable;
|
||||
|
||||
@Nullable
|
||||
private Constant yVariable;
|
||||
|
||||
private boolean fromInputArgs;
|
||||
|
||||
@NotNull
|
||||
private PlotBoundaries plotBoundaries = PlotBoundaries.newDefaultInstance();
|
||||
|
||||
private PreparedInput() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PreparedInput newInstance(@NotNull Input input,
|
||||
@NotNull Generic expression,
|
||||
@NotNull Constant xVariable,
|
||||
@Nullable Constant yVariable,
|
||||
boolean fromInputArgs,
|
||||
@NotNull PlotBoundaries plotBoundaries) {
|
||||
final PreparedInput result = new PreparedInput();
|
||||
|
||||
result.input = input;
|
||||
result.expression = expression;
|
||||
result.xVariable = xVariable;
|
||||
result.yVariable = yVariable;
|
||||
result.fromInputArgs = fromInputArgs;
|
||||
result.plotBoundaries = plotBoundaries;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PreparedInput newErrorInstance(boolean fromInputArgs) {
|
||||
final PreparedInput result = new PreparedInput();
|
||||
|
||||
result.input = null;
|
||||
result.expression = null;
|
||||
result.xVariable = null;
|
||||
result.yVariable = null;
|
||||
result.fromInputArgs = fromInputArgs;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isFromInputArgs() {
|
||||
return fromInputArgs;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Input getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Generic getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PlotBoundaries getPlotBoundaries() {
|
||||
return plotBoundaries;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Constant getXVariable() {
|
||||
return xVariable;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Constant getYVariable() {
|
||||
return yVariable;
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return input == null || expression == null || xVariable == null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Input implements Serializable {
|
||||
|
||||
@NotNull
|
||||
private String expression;
|
||||
|
||||
@NotNull
|
||||
private String xVariableName;
|
||||
|
||||
@Nullable
|
||||
private String yVariableName;
|
||||
|
||||
public Input(@NotNull String expression,
|
||||
@NotNull String xVariableName,
|
||||
@Nullable String yVariableName) {
|
||||
this.expression = expression;
|
||||
this.xVariableName = xVariableName;
|
||||
this.yVariableName = yVariableName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getXVariableName() {
|
||||
return xVariableName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getYVariableName() {
|
||||
return yVariableName;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,131 @@
|
||||
package org.solovyev.android.calculator.plot;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import arity.calculator.Graph2dView;
|
||||
import arity.calculator.Graph3dView;
|
||||
import arity.calculator.GraphView;
|
||||
import jscl.math.Generic;
|
||||
import jscl.math.function.Constant;
|
||||
import org.javia.arity.Complex;
|
||||
import org.javia.arity.Function;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/30/12
|
||||
* Time: 4:43 PM
|
||||
*/
|
||||
public class CalculatorArityPlotFragment extends AbstractCalculatorPlotFragment {
|
||||
|
||||
@Nullable
|
||||
private GraphView graphView;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected PlotBoundaries getPlotBoundaries() {
|
||||
if ( graphView != null ) {
|
||||
// todo serso: return plot boundaries
|
||||
return null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createGraphicalView(@NotNull View root, @NotNull PreparedInput preparedInput) {
|
||||
// remove old
|
||||
final ViewGroup graphContainer = (ViewGroup) root.findViewById(R.id.main_fragment_layout);
|
||||
|
||||
if (graphView instanceof View) {
|
||||
graphContainer.removeView((View) graphView);
|
||||
}
|
||||
|
||||
if (!preparedInput.isError()) {
|
||||
final Generic expression = preparedInput.getExpression();
|
||||
final Constant xVariable = preparedInput.getXVariable();
|
||||
final Constant yVariable = preparedInput.getYVariable();
|
||||
|
||||
final int arity = yVariable == null ? 1 : 2;
|
||||
|
||||
final List<Function> functions = new ArrayList<Function>();
|
||||
functions.add(new Function() {
|
||||
@Override
|
||||
public int arity() {
|
||||
return arity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double eval(double x) {
|
||||
return PlotUtils.calculatorExpression(expression, xVariable, x).realPart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double eval(double x, double y) {
|
||||
return PlotUtils.calculatorExpression(expression, xVariable, x, yVariable, y).realPart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Complex eval(Complex x) {
|
||||
jscl.math.numeric.Complex result = PlotUtils.calculatorExpression(expression, xVariable, x.re);
|
||||
return new Complex(result.realPart(), result.imaginaryPart());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Complex eval(Complex x, Complex y) {
|
||||
jscl.math.numeric.Complex result = PlotUtils.calculatorExpression(expression, xVariable, x.re, yVariable, y.re);
|
||||
return new Complex(result.realPart(), result.imaginaryPart());
|
||||
}
|
||||
});
|
||||
|
||||
if (functions.size() == 1) {
|
||||
final Function f = functions.get(0);
|
||||
graphView = f.arity() == 1 ? new Graph2dView(getActivity()) : new Graph3dView(getActivity());
|
||||
graphView.setFunction(f);
|
||||
} else {
|
||||
graphView = new Graph2dView(this.getActivity());
|
||||
((Graph2dView) graphView).setFunctions(functions);
|
||||
}
|
||||
|
||||
graphContainer.addView((View) graphView);
|
||||
} else {
|
||||
onError();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createChart(@NotNull PreparedInput preparedInput) {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (this.graphView != null) {
|
||||
this.graphView.onResume();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onError() {
|
||||
final View root = getView();
|
||||
if (root != null && graphView instanceof View) {
|
||||
final ViewGroup graphContainer = (ViewGroup) root.findViewById(R.id.main_fragment_layout);
|
||||
graphContainer.removeView((View) graphView);
|
||||
}
|
||||
this.graphView = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (this.graphView != null) {
|
||||
this.graphView.onPause();
|
||||
}
|
||||
}
|
||||
}
|
@@ -3,6 +3,7 @@ package org.solovyev.android.calculator.plot;
|
||||
import android.app.ActionBar;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.CalculatorFragmentActivity;
|
||||
import org.solovyev.android.calculator.R;
|
||||
@@ -29,6 +30,11 @@ public class CalculatorPlotActivity extends CalculatorFragmentActivity {
|
||||
}
|
||||
|
||||
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
|
||||
getActivityHelper().setFragment(this, CalculatorFragmentType.plotter, arguments, R.id.main_layout);
|
||||
getActivityHelper().setFragment(this, getPlotterFragmentType(), arguments, R.id.main_layout);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static CalculatorFragmentType getPlotterFragmentType() {
|
||||
return CalculatorFragmentType.plotter_2;
|
||||
}
|
||||
}
|
||||
|
@@ -6,23 +6,12 @@
|
||||
|
||||
package org.solovyev.android.calculator.plot;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
import jscl.math.Expression;
|
||||
import jscl.math.Generic;
|
||||
import jscl.math.function.Constant;
|
||||
import jscl.text.ParseException;
|
||||
import org.achartengine.chart.XYChart;
|
||||
import org.achartengine.model.XYMultipleSeriesDataset;
|
||||
import org.achartengine.model.XYSeries;
|
||||
@@ -32,47 +21,16 @@ import org.achartengine.tools.ZoomEvent;
|
||||
import org.achartengine.tools.ZoomListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.CalculatorApplication;
|
||||
import org.solovyev.android.calculator.CalculatorDisplayChangeEventData;
|
||||
import org.solovyev.android.calculator.CalculatorDisplayViewState;
|
||||
import org.solovyev.android.calculator.CalculatorEventData;
|
||||
import org.solovyev.android.calculator.CalculatorEventHolder;
|
||||
import org.solovyev.android.calculator.CalculatorEventListener;
|
||||
import org.solovyev.android.calculator.CalculatorEventType;
|
||||
import org.solovyev.android.calculator.CalculatorFragment;
|
||||
import org.solovyev.android.calculator.CalculatorParseException;
|
||||
import org.solovyev.android.calculator.CalculatorPreferences;
|
||||
import org.solovyev.android.calculator.CalculatorUtils;
|
||||
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.menu.ActivityMenu;
|
||||
import org.solovyev.android.menu.IdentifiableMenuItem;
|
||||
import org.solovyev.android.menu.ListActivityMenu;
|
||||
import org.solovyev.android.sherlock.menu.SherlockMenuHelper;
|
||||
import org.solovyev.common.MutableObject;
|
||||
import org.solovyev.common.collections.CollectionsUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/1/11
|
||||
* Time: 12:40 AM
|
||||
*/
|
||||
public class CalculatorPlotFragment extends CalculatorFragment implements CalculatorEventListener {
|
||||
|
||||
private static final String TAG = CalculatorPlotFragment.class.getSimpleName();
|
||||
|
||||
private static final int DEFAULT_MIN_NUMBER = -10;
|
||||
|
||||
private static final int DEFAULT_MAX_NUMBER = 10;
|
||||
|
||||
public static final String INPUT = "plotter_input";
|
||||
private static final String PLOT_BOUNDARIES = "plot_boundaries";
|
||||
public class CalculatorPlotFragment extends AbstractCalculatorPlotFragment {
|
||||
|
||||
public static final long EVAL_DELAY_MILLIS = 200;
|
||||
|
||||
@@ -85,153 +43,42 @@ public class CalculatorPlotFragment extends CalculatorFragment implements Calcul
|
||||
@Nullable
|
||||
private MyGraphicalView graphicalView;
|
||||
|
||||
// thread which calculated data for graph view
|
||||
@NotNull
|
||||
private final Executor plotExecutor = Executors.newSingleThreadExecutor();
|
||||
protected void createChart(@NotNull PreparedInput preparedInput) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
|
||||
final Boolean interpolate = CalculatorPreferences.Graph.interpolate.getPreference(preferences);
|
||||
final GraphLineColor realLineColor = CalculatorPreferences.Graph.lineColorReal.getPreference(preferences);
|
||||
final GraphLineColor imagLineColor = CalculatorPreferences.Graph.lineColorImag.getPreference(preferences);
|
||||
|
||||
// thread for applying UI changes
|
||||
@NotNull
|
||||
private final Handler uiHandler = new Handler();
|
||||
|
||||
@NotNull
|
||||
private PreparedInput preparedInput;
|
||||
//noinspection ConstantConditions
|
||||
try {
|
||||
this.chart = PlotUtils.prepareChart(getMinValue(null), getMaxValue(null), preparedInput.getExpression(), preparedInput.getXVariable(), getBgColor(), interpolate, realLineColor.getColor(), imagLineColor.getColor());
|
||||
} catch (ArithmeticException e) {
|
||||
PlotUtils.handleArithmeticException(e, CalculatorPlotFragment.this);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Input input;
|
||||
|
||||
@NotNull
|
||||
private final CalculatorEventHolder lastEventHolder = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
|
||||
|
||||
private int bgColor;
|
||||
|
||||
@NotNull
|
||||
private ActivityMenu<Menu, MenuItem> fragmentMenu = ListActivityMenu.fromResource(R.menu.plot_menu, PlotMenu.class, SherlockMenuHelper.getInstance());
|
||||
|
||||
public CalculatorPlotFragment() {
|
||||
super(CalculatorApplication.getInstance().createFragmentHelper(R.layout.plot_fragment, R.string.c_graph, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final Bundle arguments = getArguments();
|
||||
|
||||
if (arguments != null) {
|
||||
input = (Input) arguments.getSerializable(INPUT);
|
||||
}
|
||||
|
||||
if (input == null) {
|
||||
this.bgColor = getResources().getColor(R.color.cpp_pane_background);
|
||||
} else {
|
||||
this.bgColor = getResources().getColor(android.R.color.transparent);
|
||||
}
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PreparedInput prepareInputFromDisplay(@NotNull CalculatorDisplayViewState displayState, @Nullable Bundle savedInstanceState) {
|
||||
try {
|
||||
if (displayState.isValid() && displayState.getResult() != null) {
|
||||
final Generic expression = displayState.getResult();
|
||||
if (CalculatorUtils.isPlotPossible(expression, displayState.getOperation())) {
|
||||
final Constant constant = CollectionsUtils.getFirstCollectionElement(CalculatorUtils.getNotSystemConstants(expression));
|
||||
|
||||
final Input input = new Input(expression.toString(), constant.getName());
|
||||
return prepareInput(input, false, savedInstanceState);
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG, e.getLocalizedMessage(), e);
|
||||
}
|
||||
|
||||
return PreparedInput.newErrorInstance(false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PreparedInput prepareInput(@NotNull Input input, boolean fromInputArgs, @Nullable Bundle savedInstanceState) {
|
||||
PreparedInput result;
|
||||
|
||||
try {
|
||||
final PreparedExpression preparedExpression = ToJsclTextProcessor.getInstance().process(input.getExpression());
|
||||
final Generic expression = Expression.valueOf(preparedExpression.getExpression());
|
||||
final Constant variable = new Constant(input.getVariableName());
|
||||
|
||||
PlotBoundaries plotBoundaries = null;
|
||||
if ( savedInstanceState != null ) {
|
||||
plotBoundaries = (PlotBoundaries)savedInstanceState.getSerializable(PLOT_BOUNDARIES);
|
||||
}
|
||||
|
||||
result = PreparedInput.newInstance(input, expression, variable, fromInputArgs, plotBoundaries);
|
||||
} catch (ParseException e) {
|
||||
result = PreparedInput.newErrorInstance(fromInputArgs);
|
||||
Locator.getInstance().getNotifier().showMessage(e);
|
||||
} catch (CalculatorParseException e) {
|
||||
result = PreparedInput.newErrorInstance(fromInputArgs);
|
||||
Locator.getInstance().getNotifier().showMessage(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void createChart() {
|
||||
if (!preparedInput.isError()) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
|
||||
final Boolean interpolate = CalculatorPreferences.Graph.interpolate.getPreference(preferences);
|
||||
final GraphLineColor realLineColor = CalculatorPreferences.Graph.lineColorReal.getPreference(preferences);
|
||||
final GraphLineColor imagLineColor = CalculatorPreferences.Graph.lineColorImag.getPreference(preferences);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
try {
|
||||
this.chart = PlotUtils.prepareChart(getMinValue(null), getMaxValue(null), preparedInput.getExpression(), preparedInput.getVariable(), bgColor, interpolate, realLineColor.getColor(), imagLineColor.getColor());
|
||||
} catch (ArithmeticException e) {
|
||||
PlotUtils.handleArithmeticException(e, CalculatorPlotFragment.this);
|
||||
}
|
||||
} else {
|
||||
onError();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
if (input == null) {
|
||||
this.preparedInput = prepareInputFromDisplay(Locator.getInstance().getDisplay().getViewState(), savedInstanceState);
|
||||
} else {
|
||||
this.preparedInput = prepareInput(input, true, savedInstanceState);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle out) {
|
||||
super.onSaveInstanceState(out);
|
||||
|
||||
protected PlotBoundaries getPlotBoundaries() {
|
||||
if (chart != null) {
|
||||
out.putSerializable(PLOT_BOUNDARIES, new PlotBoundaries(chart.getRenderer()));
|
||||
return new PlotBoundaries(chart.getRenderer());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
createChart();
|
||||
createGraphicalView(getView(), this.preparedInput.getPlotBoundaries());
|
||||
}
|
||||
|
||||
private void createGraphicalView(@NotNull View root, @Nullable PlotBoundaries plotBoundaries) {
|
||||
protected void createGraphicalView(@NotNull View root, @Nullable PreparedInput preparedInput) {
|
||||
final ViewGroup graphContainer = (ViewGroup) root.findViewById(R.id.main_fragment_layout);
|
||||
|
||||
if (graphicalView != null) {
|
||||
graphContainer.removeView(graphicalView);
|
||||
}
|
||||
|
||||
if (!preparedInput.isError()) {
|
||||
if (!getPreparedInput().isError()) {
|
||||
final XYChart chart = this.chart;
|
||||
assert chart != null;
|
||||
|
||||
final PlotBoundaries plotBoundaries = preparedInput.getPlotBoundaries();
|
||||
double minValue = getMinValue(plotBoundaries);
|
||||
double maxValue = getMaxValue(plotBoundaries);
|
||||
|
||||
@@ -249,20 +96,20 @@ public class CalculatorPlotFragment extends CalculatorFragment implements Calcul
|
||||
maxY = Math.max(maxY, series.getMaxY());
|
||||
}
|
||||
|
||||
if (plotBoundaries == null) {
|
||||
if (preparedInput == null) {
|
||||
chart.getRenderer().setXAxisMin(Math.max(minX, minValue));
|
||||
chart.getRenderer().setYAxisMin(Math.max(minY, minValue));
|
||||
chart.getRenderer().setXAxisMax(Math.min(maxX, maxValue));
|
||||
chart.getRenderer().setYAxisMax(Math.min(maxY, maxValue));
|
||||
} else {
|
||||
chart.getRenderer().setXAxisMin(plotBoundaries.xMin);
|
||||
chart.getRenderer().setYAxisMin(plotBoundaries.yMin);
|
||||
chart.getRenderer().setXAxisMax(plotBoundaries.xMax);
|
||||
chart.getRenderer().setYAxisMax(plotBoundaries.yMax);
|
||||
chart.getRenderer().setXAxisMin(plotBoundaries.getXMin());
|
||||
chart.getRenderer().setYAxisMin(plotBoundaries.getYMin());
|
||||
chart.getRenderer().setXAxisMax(plotBoundaries.getXMax());
|
||||
chart.getRenderer().setYAxisMax(plotBoundaries.getYMax());
|
||||
}
|
||||
|
||||
graphicalView = new MyGraphicalView(this.getActivity(), chart);
|
||||
graphicalView.setBackgroundColor(this.bgColor);
|
||||
graphicalView.setBackgroundColor(this.getBgColor());
|
||||
|
||||
graphicalView.addZoomListener(new ZoomListener() {
|
||||
@Override
|
||||
@@ -292,14 +139,6 @@ public class CalculatorPlotFragment extends CalculatorFragment implements Calcul
|
||||
|
||||
}
|
||||
|
||||
private double getMaxValue(@Nullable PlotBoundaries plotBoundaries) {
|
||||
return plotBoundaries == null ? DEFAULT_MAX_NUMBER : plotBoundaries.xMax;
|
||||
}
|
||||
|
||||
private double getMinValue(@Nullable PlotBoundaries plotBoundaries) {
|
||||
return plotBoundaries == null ? DEFAULT_MIN_NUMBER : plotBoundaries.xMin;
|
||||
}
|
||||
|
||||
|
||||
private void updateDataSets(@NotNull final XYChart chart) {
|
||||
updateDataSets(chart, EVAL_DELAY_MILLIS);
|
||||
@@ -309,10 +148,13 @@ public class CalculatorPlotFragment extends CalculatorFragment implements Calcul
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
|
||||
final GraphLineColor imagLineColor = CalculatorPreferences.Graph.lineColorImag.getPreference(preferences);
|
||||
|
||||
final Generic expression = preparedInput.getExpression();
|
||||
final Constant variable = preparedInput.getVariable();
|
||||
final PreparedInput preparedInput = getPreparedInput();
|
||||
|
||||
if (expression != null && variable != null) {
|
||||
final Generic expression = preparedInput.getExpression();
|
||||
final Constant variable = preparedInput.getXVariable();
|
||||
final MyGraphicalView graphicalView = this.graphicalView;
|
||||
|
||||
if (expression != null && variable != null && graphicalView != null) {
|
||||
pendingOperation.setObject(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -321,43 +163,43 @@ public class CalculatorPlotFragment extends CalculatorFragment implements Calcul
|
||||
//lock all operations with history
|
||||
if (pendingOperation.getObject() == this) {
|
||||
|
||||
plotExecutor.execute(new Runnable() {
|
||||
getPlotExecutor().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final XYMultipleSeriesRenderer dr = chart.getRenderer();
|
||||
final XYMultipleSeriesRenderer dr = chart.getRenderer();
|
||||
|
||||
final XYMultipleSeriesDataset dataset = chart.getDataset();
|
||||
if (dataset != null && dr != null) {
|
||||
final MyXYSeries realSeries = (MyXYSeries) dataset.getSeriesAt(0);
|
||||
final XYMultipleSeriesDataset dataset = chart.getDataset();
|
||||
if (dataset != null && dr != null) {
|
||||
final MyXYSeries realSeries = (MyXYSeries) dataset.getSeriesAt(0);
|
||||
|
||||
if (realSeries != null) {
|
||||
final MyXYSeries imagSeries;
|
||||
if (dataset.getSeriesCount() > 1) {
|
||||
imagSeries = (MyXYSeries) dataset.getSeriesAt(1);
|
||||
} else {
|
||||
imagSeries = new MyXYSeries(PlotUtils.getImagFunctionName(variable), PlotUtils.DEFAULT_NUMBER_OF_STEPS * 2);
|
||||
}
|
||||
if (realSeries != null) {
|
||||
final MyXYSeries imagSeries;
|
||||
if (dataset.getSeriesCount() > 1) {
|
||||
imagSeries = (MyXYSeries) dataset.getSeriesAt(1);
|
||||
} else {
|
||||
imagSeries = new MyXYSeries(PlotUtils.getImagFunctionName(variable), PlotUtils.DEFAULT_NUMBER_OF_STEPS * 2);
|
||||
}
|
||||
|
||||
try {
|
||||
if (PlotUtils.addXY(dr.getXAxisMin(), dr.getXAxisMax(), expression, variable, realSeries, imagSeries, true, PlotUtils.DEFAULT_NUMBER_OF_STEPS)) {
|
||||
if (dataset.getSeriesCount() <= 1) {
|
||||
dataset.addSeries(imagSeries);
|
||||
dr.addSeriesRenderer(PlotUtils.createImagRenderer(imagLineColor.getColor()));
|
||||
}
|
||||
}
|
||||
} catch (ArithmeticException e) {
|
||||
PlotUtils.handleArithmeticException(e, CalculatorPlotFragment.this);
|
||||
}
|
||||
try {
|
||||
if (PlotUtils.addXY(dr.getXAxisMin(), dr.getXAxisMax(), expression, variable, realSeries, imagSeries, true, PlotUtils.DEFAULT_NUMBER_OF_STEPS)) {
|
||||
if (dataset.getSeriesCount() <= 1) {
|
||||
dataset.addSeries(imagSeries);
|
||||
dr.addSeriesRenderer(PlotUtils.createImagRenderer(imagLineColor.getColor()));
|
||||
}
|
||||
}
|
||||
} catch (ArithmeticException e) {
|
||||
PlotUtils.handleArithmeticException(e, CalculatorPlotFragment.this);
|
||||
}
|
||||
|
||||
uiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
graphicalView.repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
getUiHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
graphicalView.repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -366,37 +208,12 @@ public class CalculatorPlotFragment extends CalculatorFragment implements Calcul
|
||||
}
|
||||
|
||||
|
||||
uiHandler.postDelayed(pendingOperation.getObject(), millisToWait);
|
||||
getUiHandler().postDelayed(pendingOperation.getObject(), millisToWait);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private final MutableObject<Runnable> pendingOperation = new MutableObject<Runnable>();
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable final Object data) {
|
||||
if (calculatorEventType.isOfType(CalculatorEventType.display_state_changed)) {
|
||||
if (!preparedInput.isFromInputArgs()) {
|
||||
|
||||
final CalculatorEventHolder.Result result = this.lastEventHolder.apply(calculatorEventData);
|
||||
if (result.isNewAfter()) {
|
||||
this.preparedInput = prepareInputFromDisplay(((CalculatorDisplayChangeEventData) data).getNewValue(), null);
|
||||
createChart();
|
||||
|
||||
uiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final View view = getView();
|
||||
if (view != null) {
|
||||
createGraphicalView(view, preparedInput.getPlotBoundaries());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* public void zoomInClickHandler(@NotNull View v) {
|
||||
this.graphicalView.zoomIn();
|
||||
@@ -406,196 +223,8 @@ public class CalculatorPlotFragment extends CalculatorFragment implements Calcul
|
||||
this.graphicalView.zoomOut();
|
||||
}*/
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* MENU
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
|
||||
final FragmentActivity activity = this.getActivity();
|
||||
if (activity != null) {
|
||||
fragmentMenu.onCreateOptionsMenu(activity, menu);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
|
||||
final FragmentActivity activity = this.getActivity();
|
||||
if (activity != null) {
|
||||
fragmentMenu.onPrepareOptionsMenu(activity, menu);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
return super.onOptionsItemSelected(item) || fragmentMenu.onOptionsItemSelected(this.getActivity(), item);
|
||||
}
|
||||
|
||||
public void onError() {
|
||||
this.chart = null;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private static enum PlotMenu implements IdentifiableMenuItem<MenuItem> {
|
||||
|
||||
preferences(R.id.menu_plot_settings) {
|
||||
@Override
|
||||
public void onClick(@NotNull MenuItem data, @NotNull Context context) {
|
||||
context.startActivity(new Intent(context, CalculatorPlotPreferenceActivity.class));
|
||||
}
|
||||
};
|
||||
|
||||
private final int itemId;
|
||||
|
||||
private PlotMenu(int itemId) {
|
||||
this.itemId = itemId;
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Integer getItemId() {
|
||||
return itemId;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class PlotBoundaries implements Serializable {
|
||||
|
||||
private double xMin;
|
||||
private double xMax;
|
||||
private double yMin;
|
||||
private double yMax;
|
||||
|
||||
public PlotBoundaries() {
|
||||
}
|
||||
|
||||
public PlotBoundaries(@NotNull XYMultipleSeriesRenderer renderer) {
|
||||
this.xMin = renderer.getXAxisMin();
|
||||
this.yMin = renderer.getYAxisMin();
|
||||
this.xMax = renderer.getXAxisMax();
|
||||
this.yMax = renderer.getYAxisMax();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PlotBoundaries{" +
|
||||
"yMax=" + yMax +
|
||||
", yMin=" + yMin +
|
||||
", xMax=" + xMax +
|
||||
", xMin=" + xMin +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
public static class PreparedInput {
|
||||
|
||||
@Nullable
|
||||
private Input input;
|
||||
|
||||
@Nullable
|
||||
private Generic expression;
|
||||
|
||||
@Nullable
|
||||
private Constant variable;
|
||||
|
||||
private boolean fromInputArgs;
|
||||
|
||||
@Nullable
|
||||
private PlotBoundaries plotBoundaries = null;
|
||||
|
||||
private PreparedInput() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PreparedInput newInstance(@NotNull Input input, @NotNull Generic expression, @NotNull Constant variable, boolean fromInputArgs, @Nullable PlotBoundaries plotBoundaries) {
|
||||
final PreparedInput result = new PreparedInput();
|
||||
|
||||
result.input = input;
|
||||
result.expression = expression;
|
||||
result.variable = variable;
|
||||
result.fromInputArgs = fromInputArgs;
|
||||
result.plotBoundaries = plotBoundaries;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PreparedInput newErrorInstance(boolean fromInputArgs) {
|
||||
final PreparedInput result = new PreparedInput();
|
||||
|
||||
result.input = null;
|
||||
result.expression = null;
|
||||
result.variable = null;
|
||||
result.fromInputArgs = fromInputArgs;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isFromInputArgs() {
|
||||
return fromInputArgs;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Input getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Generic getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PlotBoundaries getPlotBoundaries() {
|
||||
return plotBoundaries;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Constant getVariable() {
|
||||
return variable;
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return input == null || expression == null || variable == null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Input implements Serializable {
|
||||
|
||||
@NotNull
|
||||
private String expression;
|
||||
|
||||
@NotNull
|
||||
private String variableName;
|
||||
|
||||
public Input(@NotNull String expression, @NotNull String variableName) {
|
||||
this.expression = expression;
|
||||
this.variableName = variableName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getVariableName() {
|
||||
return variableName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -202,7 +202,7 @@ public final class PlotUtils {
|
||||
return renderer;
|
||||
}
|
||||
|
||||
static void handleArithmeticException(@NotNull ArithmeticException e, @NotNull CalculatorPlotFragment calculatorPlotFragment) {
|
||||
static void handleArithmeticException(@NotNull ArithmeticException e, @NotNull AbstractCalculatorPlotFragment calculatorPlotFragment) {
|
||||
String message = e.getLocalizedMessage();
|
||||
if (StringUtils.isEmpty(message)) {
|
||||
message = e.getMessage();
|
||||
@@ -371,9 +371,20 @@ public final class PlotUtils {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Complex calculatorExpression(@NotNull Generic expression, @NotNull Constant variable, double x) {
|
||||
public static Complex calculatorExpression(@NotNull Generic expression, @NotNull Constant xVar, double x) {
|
||||
try {
|
||||
return unwrap(expression.substitute(variable, Expression.valueOf(x)).numeric());
|
||||
return unwrap(expression.substitute(xVar, Expression.valueOf(x)).numeric());
|
||||
} catch (RuntimeException e) {
|
||||
return NaN;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Complex calculatorExpression(@NotNull Generic expression, @NotNull Constant xVar, double x, @NotNull Constant yVar, double y) {
|
||||
try {
|
||||
Generic tmp = expression.substitute(xVar, Expression.valueOf(x));
|
||||
tmp = tmp.substitute(yVar, Expression.valueOf(y));
|
||||
return unwrap(tmp.numeric());
|
||||
} catch (RuntimeException e) {
|
||||
return NaN;
|
||||
}
|
||||
|
Reference in New Issue
Block a user