new plotter
This commit is contained in:
parent
cbfdf237f0
commit
3f09528f45
@ -2,17 +2,12 @@ package org.solovyev.android.calculator;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import jscl.math.Generic;
|
import jscl.math.Generic;
|
||||||
import jscl.math.function.Constant;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.calculator.core.R;
|
import org.solovyev.android.calculator.core.R;
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
import org.solovyev.android.calculator.plot.PlotInput;
|
|
||||||
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
|
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
|
||||||
import org.solovyev.android.menu.LabeledMenuItem;
|
import org.solovyev.android.menu.LabeledMenuItem;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: Solovyev_S
|
* User: Solovyev_S
|
||||||
* Date: 21.09.12
|
* Date: 21.09.12
|
||||||
@ -81,31 +76,17 @@ public enum CalculatorDisplayMenuItem implements LabeledMenuItem<CalculatorDispl
|
|||||||
plot(R.string.c_plot) {
|
plot(R.string.c_plot) {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
||||||
final Generic generic = data.getResult();
|
final Generic expression = data.getResult();
|
||||||
assert generic != null;
|
assert expression != null;
|
||||||
|
|
||||||
final List<Constant> variables = new ArrayList<Constant>(CalculatorUtils.getNotSystemConstants(generic));
|
Locator.getInstance().getPlotter().removeAllUnpinned();
|
||||||
|
Locator.getInstance().getPlotter().addFunction(expression);
|
||||||
final Constant xVariable;
|
Locator.getInstance().getPlotter().plot();
|
||||||
if ( variables.size() > 0 ) {
|
|
||||||
xVariable = variables.get(0);
|
|
||||||
} else {
|
|
||||||
xVariable = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Constant yVariable;
|
|
||||||
if ( variables.size() > 1 ) {
|
|
||||||
yVariable = variables.get(1);
|
|
||||||
} else {
|
|
||||||
yVariable = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.plot_graph, PlotInput.newInstance(generic, xVariable, yVariable), context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||||
return CalculatorUtils.isPlotPossible(generic, operation);
|
return Locator.getInstance().getPlotter().isPlotPossible(generic);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,6 @@ import org.solovyev.android.AndroidUtils;
|
|||||||
import org.solovyev.android.calculator.math.MathType;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
|
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
|
||||||
import org.solovyev.android.calculator.plot.GraphLineColor;
|
import org.solovyev.android.calculator.plot.GraphLineColor;
|
||||||
import org.solovyev.android.calculator.plot.ParcelablePlotInput;
|
|
||||||
import org.solovyev.android.prefs.BooleanPreference;
|
import org.solovyev.android.prefs.BooleanPreference;
|
||||||
import org.solovyev.android.prefs.IntegerPreference;
|
import org.solovyev.android.prefs.IntegerPreference;
|
||||||
import org.solovyev.android.prefs.LongPreference;
|
import org.solovyev.android.prefs.LongPreference;
|
||||||
@ -16,10 +15,8 @@ import org.solovyev.android.prefs.Preference;
|
|||||||
import org.solovyev.android.prefs.R;
|
import org.solovyev.android.prefs.R;
|
||||||
import org.solovyev.android.prefs.StringPreference;
|
import org.solovyev.android.prefs.StringPreference;
|
||||||
import org.solovyev.android.view.VibratorContainer;
|
import org.solovyev.android.view.VibratorContainer;
|
||||||
import org.solovyev.common.ListMapper;
|
|
||||||
|
|
||||||
import java.text.DecimalFormatSymbols;
|
import java.text.DecimalFormatSymbols;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,164 @@
|
|||||||
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.android.calculator.CalculatorPreferences;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 1/12/13
|
||||||
|
* Time: 11:03 PM
|
||||||
|
*/
|
||||||
|
public class AndroidCalculatorPlotter implements CalculatorPlotter, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final CalculatorPlotter plotter;
|
||||||
|
|
||||||
|
public AndroidCalculatorPlotter(@NotNull Context context,
|
||||||
|
@NotNull CalculatorPlotter plotter) {
|
||||||
|
this.plotter = plotter;
|
||||||
|
|
||||||
|
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
|
||||||
|
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||||
|
|
||||||
|
onSharedPreferenceChanged(preferences, CalculatorPreferences.Graph.plotImag.getKey());
|
||||||
|
onSharedPreferenceChanged(preferences, CalculatorPreferences.Graph.lineColorReal.getKey());
|
||||||
|
onSharedPreferenceChanged(preferences, CalculatorPreferences.Graph.lineColorImag.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public PlotData getPlotData() {
|
||||||
|
return plotter.getPlotData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addFunction(@NotNull Generic expression) {
|
||||||
|
return plotter.addFunction(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addFunction(@NotNull PlotFunction plotFunction) {
|
||||||
|
return plotter.addFunction(plotFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addFunction(@NotNull XyFunction xyFunction) {
|
||||||
|
return plotter.addFunction(xyFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addFunction(@NotNull XyFunction xyFunction, @NotNull PlotFunctionLineDef functionLineDef) {
|
||||||
|
return plotter.addFunction(xyFunction, functionLineDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateFunction(@NotNull PlotFunction newFunction) {
|
||||||
|
return plotter.updateFunction(newFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateFunction(@NotNull XyFunction xyFunction, @NotNull PlotFunctionLineDef functionLineDef) {
|
||||||
|
return plotter.updateFunction(xyFunction, functionLineDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeFunction(@NotNull PlotFunction plotFunction) {
|
||||||
|
return plotter.removeFunction(plotFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeFunction(@NotNull XyFunction xyFunction) {
|
||||||
|
return plotter.removeFunction(xyFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pin(@NotNull PlotFunction plotFunction) {
|
||||||
|
plotter.pin(plotFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unpin(@NotNull PlotFunction plotFunction) {
|
||||||
|
plotter.unpin(plotFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void show(@NotNull PlotFunction plotFunction) {
|
||||||
|
plotter.show(plotFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hide(@NotNull PlotFunction plotFunction) {
|
||||||
|
plotter.hide(plotFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearAllFunctions() {
|
||||||
|
plotter.clearAllFunctions();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public List<PlotFunction> getFunctions() {
|
||||||
|
return plotter.getFunctions();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public List<PlotFunction> getVisibleFunctions() {
|
||||||
|
return plotter.getVisibleFunctions();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void plot() {
|
||||||
|
plotter.plot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPlotPossible(@NotNull Generic expression) {
|
||||||
|
return plotter.isPlotPossible(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPlot3d(boolean plot3d) {
|
||||||
|
plotter.setPlot3d(plot3d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAllUnpinned() {
|
||||||
|
plotter.removeAllUnpinned();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPlotImag(boolean plotImag) {
|
||||||
|
plotter.setPlotImag(plotImag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||||
|
if (CalculatorPreferences.Graph.plotImag.getKey().equals(key)) {
|
||||||
|
setPlotImag(CalculatorPreferences.Graph.plotImag.getPreference(preferences));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CalculatorPreferences.Graph.lineColorReal.getKey().equals(key)) {
|
||||||
|
setRealLineColor(CalculatorPreferences.Graph.lineColorReal.getPreference(preferences));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CalculatorPreferences.Graph.lineColorImag.getKey().equals(key)) {
|
||||||
|
setImagLineColor(CalculatorPreferences.Graph.lineColorImag.getPreference(preferences));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setImagLineColor(@NotNull GraphLineColor imagLineColor) {
|
||||||
|
plotter.setImagLineColor(imagLineColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRealLineColor(@NotNull GraphLineColor realLineColor) {
|
||||||
|
plotter.setRealLineColor(realLineColor);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
|
import android.graphics.DashPathEffect;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 1/5/13
|
||||||
|
* Time: 7:37 PM
|
||||||
|
*/
|
||||||
|
public enum AndroidPlotLineStyle {
|
||||||
|
|
||||||
|
solid(PlotLineStyle.solid) {
|
||||||
|
@Override
|
||||||
|
public void applyToPaint(@NotNull Paint paint) {
|
||||||
|
paint.setPathEffect(null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
dashed(PlotLineStyle.dashed) {
|
||||||
|
@Override
|
||||||
|
public void applyToPaint(@NotNull Paint paint) {
|
||||||
|
paint.setPathEffect(new DashPathEffect(new float[]{10, 20}, 0));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
dotted(PlotLineStyle.dotted) {
|
||||||
|
@Override
|
||||||
|
public void applyToPaint(@NotNull Paint paint) {
|
||||||
|
paint.setPathEffect(new DashPathEffect(new float[]{5, 1}, 0));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
dash_dotted(PlotLineStyle.dash_dotted) {
|
||||||
|
@Override
|
||||||
|
public void applyToPaint(@NotNull Paint paint) {
|
||||||
|
paint.setPathEffect(new DashPathEffect(new float[]{10, 20, 5, 1}, 0));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final PlotLineStyle plotLineStyle;
|
||||||
|
|
||||||
|
AndroidPlotLineStyle(@NotNull PlotLineStyle plotLineStyle) {
|
||||||
|
this.plotLineStyle = plotLineStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void applyToPaint(@NotNull Paint paint);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static AndroidPlotLineStyle valueOf(@NotNull PlotLineStyle plotLineStyle) {
|
||||||
|
for (AndroidPlotLineStyle androidPlotLineStyle : values()) {
|
||||||
|
if ( androidPlotLineStyle.plotLineStyle == plotLineStyle ) {
|
||||||
|
return androidPlotLineStyle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,156 +0,0 @@
|
|||||||
package org.solovyev.android.calculator.plot;
|
|
||||||
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User: serso
|
|
||||||
* Date: 1/5/13
|
|
||||||
* Time: 7:41 PM
|
|
||||||
*/
|
|
||||||
public class FunctionLineDef implements Parcelable {
|
|
||||||
|
|
||||||
/*
|
|
||||||
**********************************************************************
|
|
||||||
*
|
|
||||||
* CONSTANTS
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static final Float DEFAULT_LINE_WIDTH = -1f;
|
|
||||||
|
|
||||||
/*
|
|
||||||
**********************************************************************
|
|
||||||
*
|
|
||||||
* STATIC
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
private static final Creator<FunctionLineDef> CREATOR = new Creator<FunctionLineDef>() {
|
|
||||||
@Override
|
|
||||||
public FunctionLineDef createFromParcel(@NotNull Parcel in) {
|
|
||||||
return fromParcel(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FunctionLineDef[] newArray(int size) {
|
|
||||||
return new FunctionLineDef[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
**********************************************************************
|
|
||||||
*
|
|
||||||
* FIELDS
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private FunctionLineColorType lineColorType = FunctionLineColorType.solid;
|
|
||||||
|
|
||||||
private int lineColor = Color.WHITE;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private FunctionLineStyle lineStyle = FunctionLineStyle.solid;
|
|
||||||
|
|
||||||
private float lineWidth = -DEFAULT_LINE_WIDTH;
|
|
||||||
|
|
||||||
private FunctionLineDef() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static FunctionLineDef newInstance(int lineColor, @NotNull FunctionLineStyle lineStyle) {
|
|
||||||
final FunctionLineDef result = new FunctionLineDef();
|
|
||||||
result.lineColor = lineColor;
|
|
||||||
result.lineStyle = lineStyle;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static FunctionLineDef newInstance(int lineColor, @NotNull FunctionLineStyle lineStyle, float lineWidth) {
|
|
||||||
final FunctionLineDef result = new FunctionLineDef();
|
|
||||||
result.lineColor = lineColor;
|
|
||||||
result.lineStyle = lineStyle;
|
|
||||||
result.lineWidth = lineWidth;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static FunctionLineDef newInstance(int lineColor, @NotNull FunctionLineStyle lineStyle, float lineWidth, @NotNull FunctionLineColorType lineColorType) {
|
|
||||||
final FunctionLineDef result = new FunctionLineDef();
|
|
||||||
result.lineColor = lineColor;
|
|
||||||
result.lineColorType = lineColorType;
|
|
||||||
result.lineStyle = lineStyle;
|
|
||||||
result.lineWidth = lineWidth;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static FunctionLineDef fromParcel(@NotNull Parcel in) {
|
|
||||||
final FunctionLineDef result = new FunctionLineDef();
|
|
||||||
|
|
||||||
result.lineColorType = (FunctionLineColorType) in.readSerializable();
|
|
||||||
result.lineColor = in.readInt();
|
|
||||||
result.lineStyle = (FunctionLineStyle) in.readSerializable();
|
|
||||||
result.lineWidth = in.readFloat();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static FunctionLineDef newDefaultInstance() {
|
|
||||||
return new FunctionLineDef();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public int getLineColor() {
|
|
||||||
return lineColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public FunctionLineStyle getLineStyle() {
|
|
||||||
return lineStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getLineWidth() {
|
|
||||||
return lineWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public FunctionLineColorType getLineColorType() {
|
|
||||||
return lineColorType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void applyToPaint(@NotNull Paint paint) {
|
|
||||||
paint.setColor(lineColor);
|
|
||||||
paint.setStyle(Paint.Style.STROKE);
|
|
||||||
|
|
||||||
if ( lineWidth == DEFAULT_LINE_WIDTH ) {
|
|
||||||
paint.setStrokeWidth(0);
|
|
||||||
} else {
|
|
||||||
paint.setStrokeWidth(lineWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
lineStyle.applyToPaint(paint);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(@NotNull Parcel out, int flags) {
|
|
||||||
out.writeSerializable(lineColorType);
|
|
||||||
out.writeInt(lineColor);
|
|
||||||
out.writeSerializable(lineStyle);
|
|
||||||
out.writeFloat(lineWidth);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
package org.solovyev.android.calculator.plot;
|
|
||||||
|
|
||||||
import android.graphics.DashPathEffect;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User: serso
|
|
||||||
* Date: 1/5/13
|
|
||||||
* Time: 7:37 PM
|
|
||||||
*/
|
|
||||||
public enum FunctionLineStyle {
|
|
||||||
|
|
||||||
solid {
|
|
||||||
@Override
|
|
||||||
public void applyToPaint(@NotNull Paint paint) {
|
|
||||||
paint.setPathEffect(null);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
dashed {
|
|
||||||
@Override
|
|
||||||
public void applyToPaint(@NotNull Paint paint) {
|
|
||||||
paint.setPathEffect(new DashPathEffect(new float[] {10, 20}, 0));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
dotted {
|
|
||||||
@Override
|
|
||||||
public void applyToPaint(@NotNull Paint paint) {
|
|
||||||
paint.setPathEffect(new DashPathEffect(new float[] {5, 1}, 0));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
dash_dotted {
|
|
||||||
@Override
|
|
||||||
public void applyToPaint(@NotNull Paint paint) {
|
|
||||||
paint.setPathEffect(new DashPathEffect(new float[] {10, 20, 5, 1}, 0));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public abstract void applyToPaint(@NotNull Paint paint);
|
|
||||||
|
|
||||||
}
|
|
@ -1,131 +0,0 @@
|
|||||||
package org.solovyev.android.calculator.plot;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public class ParcelablePlotInput implements Parcelable {
|
|
||||||
|
|
||||||
/*
|
|
||||||
**********************************************************************
|
|
||||||
*
|
|
||||||
* STATIC
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static Creator<ParcelablePlotInput> CREATOR = new Creator<ParcelablePlotInput>() {
|
|
||||||
@Override
|
|
||||||
public ParcelablePlotInput createFromParcel(@NotNull Parcel in) {
|
|
||||||
return fromParcel(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ParcelablePlotInput[] newArray(int size) {
|
|
||||||
return new ParcelablePlotInput[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
**********************************************************************
|
|
||||||
*
|
|
||||||
* FIELDS
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private String expression;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private String xVariableName;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private String yVariableName;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private FunctionLineDef lineDef;
|
|
||||||
|
|
||||||
public ParcelablePlotInput(@NotNull String expression,
|
|
||||||
@Nullable String xVariableName,
|
|
||||||
@Nullable String yVariableName) {
|
|
||||||
this(expression, xVariableName, yVariableName, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ParcelablePlotInput(@NotNull String expression,
|
|
||||||
@Nullable String xVariableName,
|
|
||||||
@Nullable String yVariableName,
|
|
||||||
@Nullable FunctionLineDef lineDef) {
|
|
||||||
this.expression = expression;
|
|
||||||
this.xVariableName = xVariableName;
|
|
||||||
this.yVariableName = yVariableName;
|
|
||||||
this.lineDef = lineDef;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static ParcelablePlotInput fromParcel(@NotNull Parcel in) {
|
|
||||||
final String expression = in.readString();
|
|
||||||
final String xVariableName = in.readString();
|
|
||||||
final String yVariableName = in.readString();
|
|
||||||
final FunctionLineDef lineDef = in.readParcelable(Thread.currentThread().getContextClassLoader());
|
|
||||||
return new ParcelablePlotInput(expression, xVariableName, yVariableName, lineDef);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public String getExpression() {
|
|
||||||
return expression;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getXVariableName() {
|
|
||||||
return xVariableName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getYVariableName() {
|
|
||||||
return yVariableName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public FunctionLineDef getLineDef() {
|
|
||||||
return lineDef;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(@NotNull Parcel out, int flags) {
|
|
||||||
out.writeString(expression);
|
|
||||||
out.writeString(xVariableName);
|
|
||||||
out.writeString(yVariableName);
|
|
||||||
out.writeParcelable(lineDef, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (!(o instanceof ParcelablePlotInput)) return false;
|
|
||||||
|
|
||||||
final ParcelablePlotInput that = (ParcelablePlotInput) o;
|
|
||||||
|
|
||||||
if (!expression.equals(that.expression)) return false;
|
|
||||||
if (xVariableName != null ? !xVariableName.equals(that.xVariableName) : that.xVariableName != null)
|
|
||||||
return false;
|
|
||||||
if (yVariableName != null ? !yVariableName.equals(that.yVariableName) : that.yVariableName != null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = expression.hashCode();
|
|
||||||
result = 31 * result + (xVariableName != null ? xVariableName.hashCode() : 0);
|
|
||||||
result = 31 * result + (yVariableName != null ? yVariableName.hashCode() : 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
@ -13,12 +13,12 @@ import org.solovyev.android.view.UpdatableViewBuilder;
|
|||||||
public class ParcelablePlotInputListItem implements ListItem {
|
public class ParcelablePlotInputListItem implements ListItem {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private ParcelablePlotInput plotInput;
|
private XyFunction plotInput;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private UpdatableViewBuilder<TextView> viewBuilder;
|
private UpdatableViewBuilder<TextView> viewBuilder;
|
||||||
|
|
||||||
public ParcelablePlotInputListItem(@NotNull ParcelablePlotInput plotInput) {
|
public ParcelablePlotInputListItem(@NotNull XyFunction plotInput) {
|
||||||
this.plotInput = plotInput;
|
this.plotInput = plotInput;
|
||||||
// todo serso: use correct tag
|
// todo serso: use correct tag
|
||||||
this.viewBuilder = TextViewBuilder.newInstance(R.layout.plot_functions_fragment_list_item, null);
|
this.viewBuilder = TextViewBuilder.newInstance(R.layout.plot_functions_fragment_list_item, null);
|
||||||
@ -52,6 +52,6 @@ public class ParcelablePlotInputListItem implements ListItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void fill(@NotNull TextView textView) {
|
private void fill(@NotNull TextView textView) {
|
||||||
textView.setText(plotInput.getExpression());
|
textView.setText(plotInput.getExpressionString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
package org.solovyev.android.calculator.plot;
|
|
||||||
|
|
||||||
import jscl.math.Generic;
|
|
||||||
import jscl.math.function.Constant;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User: serso
|
|
||||||
* Date: 12/1/12
|
|
||||||
* Time: 5:09 PM
|
|
||||||
*/
|
|
||||||
public class PlotInput {
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private Generic function;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private Constant xVariable;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private Constant yVariable;
|
|
||||||
|
|
||||||
public PlotInput() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static PlotInput newInstance(@NotNull Generic function,
|
|
||||||
@Nullable Constant xVariable,
|
|
||||||
@Nullable Constant yVariable) {
|
|
||||||
PlotInput result = new PlotInput();
|
|
||||||
|
|
||||||
result.function = function;
|
|
||||||
result.xVariable = xVariable;
|
|
||||||
result.yVariable = yVariable;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Generic getFunction() {
|
|
||||||
return function;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public Constant getXVariable() {
|
|
||||||
return xVariable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public Constant getYVariable() {
|
|
||||||
return yVariable;
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,8 +11,6 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||||
import jscl.math.Generic;
|
|
||||||
import jscl.math.function.Constant;
|
|
||||||
import org.achartengine.ChartFactory;
|
import org.achartengine.ChartFactory;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -21,16 +19,9 @@ import org.solovyev.android.calculator.about.CalculatorAboutActivity;
|
|||||||
import org.solovyev.android.calculator.function.FunctionEditDialogFragment;
|
import org.solovyev.android.calculator.function.FunctionEditDialogFragment;
|
||||||
import org.solovyev.android.calculator.help.CalculatorHelpActivity;
|
import org.solovyev.android.calculator.help.CalculatorHelpActivity;
|
||||||
import org.solovyev.android.calculator.history.CalculatorHistoryActivity;
|
import org.solovyev.android.calculator.history.CalculatorHistoryActivity;
|
||||||
import org.solovyev.android.calculator.math.edit.CalculatorFunctionsActivity;
|
import org.solovyev.android.calculator.math.edit.*;
|
||||||
import org.solovyev.android.calculator.math.edit.CalculatorOperatorsActivity;
|
|
||||||
import org.solovyev.android.calculator.math.edit.CalculatorVarsActivity;
|
|
||||||
import org.solovyev.android.calculator.math.edit.CalculatorVarsFragment;
|
|
||||||
import org.solovyev.android.calculator.math.edit.VarEditDialogFragment;
|
|
||||||
import org.solovyev.android.calculator.matrix.CalculatorMatrixActivity;
|
import org.solovyev.android.calculator.matrix.CalculatorMatrixActivity;
|
||||||
import org.solovyev.android.calculator.plot.CalculatorPlotActivity;
|
import org.solovyev.android.calculator.plot.CalculatorPlotActivity;
|
||||||
import org.solovyev.android.calculator.plot.CalculatorPlotFragment;
|
|
||||||
import org.solovyev.android.calculator.plot.ParcelablePlotInput;
|
|
||||||
import org.solovyev.android.calculator.plot.PlotInput;
|
|
||||||
import org.solovyev.common.msg.Message;
|
import org.solovyev.common.msg.Message;
|
||||||
import org.solovyev.common.msg.MessageType;
|
import org.solovyev.common.msg.MessageType;
|
||||||
import org.solovyev.common.text.StringUtils;
|
import org.solovyev.common.text.StringUtils;
|
||||||
@ -104,14 +95,9 @@ public final class CalculatorActivityLauncher implements CalculatorEventListener
|
|||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void plotGraph(@NotNull final Context context,
|
public static void plotGraph(@NotNull final Context context){
|
||||||
@NotNull Generic generic,
|
|
||||||
@Nullable Constant xVariable,
|
|
||||||
@Nullable Constant yVariable){
|
|
||||||
final Intent intent = new Intent();
|
final Intent intent = new Intent();
|
||||||
intent.putExtra(ChartFactory.TITLE, context.getString(R.string.c_graph));
|
intent.putExtra(ChartFactory.TITLE, context.getString(R.string.c_graph));
|
||||||
final ParcelablePlotInput input = new ParcelablePlotInput(generic.toString(), xVariable == null ? null : xVariable.getName(), yVariable == null ? null : yVariable.getName());
|
|
||||||
intent.putExtra(CalculatorPlotFragment.INPUT, input);
|
|
||||||
intent.setClass(context, CalculatorPlotActivity.class);
|
intent.setClass(context, CalculatorPlotActivity.class);
|
||||||
AndroidUtils2.addFlags(intent, false, context);
|
AndroidUtils2.addFlags(intent, false, context);
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
@ -218,12 +204,10 @@ public final class CalculatorActivityLauncher implements CalculatorEventListener
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case plot_graph:
|
case plot_graph:
|
||||||
final PlotInput plotInput = (PlotInput) data;
|
|
||||||
assert plotInput != null;
|
|
||||||
App.getInstance().getUiThreadExecutor().execute(new Runnable() {
|
App.getInstance().getUiThreadExecutor().execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
plotGraph(context, plotInput.getFunction(), plotInput.getXVariable(), plotInput.getYVariable());
|
plotGraph(context);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
@ -19,6 +19,8 @@ import org.solovyev.android.calculator.external.AndroidExternalListenersContaine
|
|||||||
import org.solovyev.android.calculator.history.AndroidCalculatorHistory;
|
import org.solovyev.android.calculator.history.AndroidCalculatorHistory;
|
||||||
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
|
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
|
||||||
import org.solovyev.android.calculator.onscreen.CalculatorOnscreenStartActivity;
|
import org.solovyev.android.calculator.onscreen.CalculatorOnscreenStartActivity;
|
||||||
|
import org.solovyev.android.calculator.plot.AndroidCalculatorPlotter;
|
||||||
|
import org.solovyev.android.calculator.plot.CalculatorPlotterImpl;
|
||||||
import org.solovyev.common.msg.MessageType;
|
import org.solovyev.common.msg.MessageType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -118,7 +120,8 @@ public class CalculatorApplication extends android.app.Application implements Sh
|
|||||||
new AndroidCalculatorLogger(),
|
new AndroidCalculatorLogger(),
|
||||||
new AndroidCalculatorPreferenceService(this),
|
new AndroidCalculatorPreferenceService(this),
|
||||||
new AndroidCalculatorKeyboard(this, new CalculatorKeyboardImpl(calculator)),
|
new AndroidCalculatorKeyboard(this, new CalculatorKeyboardImpl(calculator)),
|
||||||
new AndroidExternalListenersContainer(calculator));
|
new AndroidExternalListenersContainer(calculator),
|
||||||
|
new AndroidCalculatorPlotter(this, new CalculatorPlotterImpl(calculator)));
|
||||||
|
|
||||||
Locator.getInstance().getCalculator().init();
|
Locator.getInstance().getCalculator().init();
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ import org.solovyev.android.calculator.math.edit.CalculatorOperatorsFragment;
|
|||||||
import org.solovyev.android.calculator.math.edit.CalculatorVarsFragment;
|
import org.solovyev.android.calculator.math.edit.CalculatorVarsFragment;
|
||||||
import org.solovyev.android.calculator.matrix.CalculatorMatrixEditFragment;
|
import org.solovyev.android.calculator.matrix.CalculatorMatrixEditFragment;
|
||||||
import org.solovyev.android.calculator.plot.CalculatorArityPlotFragment;
|
import org.solovyev.android.calculator.plot.CalculatorArityPlotFragment;
|
||||||
import org.solovyev.android.calculator.plot.CalculatorPlotFragment;
|
|
||||||
import org.solovyev.android.calculator.plot.CalculatorPlotFunctionsFragment;
|
import org.solovyev.android.calculator.plot.CalculatorPlotFunctionsFragment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,8 +31,7 @@ public enum CalculatorFragmentType {
|
|||||||
variables(CalculatorVarsFragment.class, R.layout.vars_fragment, R.string.c_vars),
|
variables(CalculatorVarsFragment.class, R.layout.vars_fragment, R.string.c_vars),
|
||||||
functions(CalculatorFunctionsFragment.class, R.layout.math_entities_fragment, R.string.c_functions),
|
functions(CalculatorFunctionsFragment.class, R.layout.math_entities_fragment, R.string.c_functions),
|
||||||
operators(CalculatorOperatorsFragment.class, R.layout.math_entities_fragment, R.string.c_operators),
|
operators(CalculatorOperatorsFragment.class, R.layout.math_entities_fragment, R.string.c_operators),
|
||||||
plotter(CalculatorPlotFragment.class, R.layout.plot_fragment, R.string.c_graph),
|
plotter(CalculatorArityPlotFragment.class, R.layout.plot_fragment, R.string.c_graph),
|
||||||
plotter_2(CalculatorArityPlotFragment.class, R.layout.plot_fragment, R.string.c_graph),
|
|
||||||
|
|
||||||
// todo serso: strings
|
// todo serso: strings
|
||||||
plotter_functions(CalculatorPlotFunctionsFragment.class, R.layout.plot_functions_fragment, R.string.c_graph),
|
plotter_functions(CalculatorPlotFunctionsFragment.class, R.layout.plot_functions_fragment, R.string.c_graph),
|
||||||
|
@ -2,35 +2,18 @@ package org.solovyev.android.calculator.plot;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.graphics.Paint;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.FragmentActivity;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import com.actionbarsherlock.view.Menu;
|
import com.actionbarsherlock.view.Menu;
|
||||||
import com.actionbarsherlock.view.MenuInflater;
|
import com.actionbarsherlock.view.MenuInflater;
|
||||||
import com.actionbarsherlock.view.MenuItem;
|
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.achartengine.renderer.XYMultipleSeriesRenderer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.calculator.CalculatorApplication;
|
import org.solovyev.android.calculator.*;
|
||||||
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.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.ActivityMenu;
|
||||||
import org.solovyev.android.menu.IdentifiableMenuItem;
|
import org.solovyev.android.menu.IdentifiableMenuItem;
|
||||||
import org.solovyev.android.menu.ListActivityMenu;
|
import org.solovyev.android.menu.ListActivityMenu;
|
||||||
@ -38,6 +21,7 @@ import org.solovyev.android.sherlock.menu.SherlockMenuHelper;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
@ -59,8 +43,6 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
|
|||||||
|
|
||||||
protected static final String TAG = "CalculatorPlotFragment";
|
protected static final String TAG = "CalculatorPlotFragment";
|
||||||
|
|
||||||
public static final String INPUT = "plot_input";
|
|
||||||
|
|
||||||
protected static final String PLOT_BOUNDARIES = "plot_boundaries";
|
protected static final String PLOT_BOUNDARIES = "plot_boundaries";
|
||||||
|
|
||||||
private static final int DEFAULT_MIN_NUMBER = -10;
|
private static final int DEFAULT_MIN_NUMBER = -10;
|
||||||
@ -75,9 +57,6 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
|
|||||||
**********************************************************************
|
**********************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private ParcelablePlotInput input;
|
|
||||||
|
|
||||||
private int bgColor;
|
private int bgColor;
|
||||||
|
|
||||||
// thread for applying UI changes
|
// thread for applying UI changes
|
||||||
@ -85,7 +64,7 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
|
|||||||
private final Handler uiHandler = new Handler();
|
private final Handler uiHandler = new Handler();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private PreparedInput preparedInput;
|
private PlotData plotData = new PlotData(Collections.<PlotFunction>emptyList(), false);
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private ActivityMenu<Menu, MenuItem> fragmentMenu;
|
private ActivityMenu<Menu, MenuItem> fragmentMenu;
|
||||||
@ -107,13 +86,9 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
|
|||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
final Bundle arguments = getArguments();
|
// todo serso: init variable properly
|
||||||
|
boolean paneFragment = true;
|
||||||
if (arguments != null) {
|
if (paneFragment) {
|
||||||
input = (ParcelablePlotInput) arguments.getParcelable(INPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input == null) {
|
|
||||||
this.bgColor = getResources().getColor(R.color.cpp_pane_background);
|
this.bgColor = getResources().getColor(R.color.cpp_pane_background);
|
||||||
} else {
|
} else {
|
||||||
this.bgColor = getResources().getColor(android.R.color.transparent);
|
this.bgColor = getResources().getColor(android.R.color.transparent);
|
||||||
@ -126,11 +101,7 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
|
|||||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
if (input == null) {
|
this.plotData = Locator.getInstance().getPlotter().getPlotData();
|
||||||
this.preparedInput = prepareInputFromDisplay(Locator.getInstance().getDisplay().getViewState(), savedInstanceState);
|
|
||||||
} else {
|
|
||||||
this.preparedInput = prepareInput(input, true, savedInstanceState);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -150,42 +121,31 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
|
|||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
createChart(preparedInput);
|
createChart(plotData);
|
||||||
createGraphicalView(getView(), preparedInput);
|
createGraphicalView(getView(), plotData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable final Object data) {
|
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable final Object data) {
|
||||||
if (calculatorEventType.isOfType(CalculatorEventType.display_state_changed)) {
|
if (calculatorEventType.isOfType(CalculatorEventType.plot_data_changed)) {
|
||||||
PreparedInput preparedInput = getPreparedInput();
|
final CalculatorEventHolder.Result result = this.lastEventHolder.apply(calculatorEventData);
|
||||||
if (!preparedInput.isFromInputArgs()) {
|
if (result.isNewAfter()) {
|
||||||
|
onNewPlotData((PlotData) data);
|
||||||
final CalculatorEventHolder.Result result = this.lastEventHolder.apply(calculatorEventData);
|
|
||||||
if (result.isNewAfter()) {
|
|
||||||
preparedInput = prepareInputFromDisplay(((CalculatorDisplayChangeEventData) data).getNewValue(), null);
|
|
||||||
onNewPreparedInput(preparedInput);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onNewPreparedInput(@NotNull PreparedInput preparedInput) {
|
private void onNewPlotData(@NotNull final PlotData plotData) {
|
||||||
this.preparedInput = preparedInput;
|
this.plotData = plotData;
|
||||||
|
|
||||||
final PreparedInput finalPreparedInput = preparedInput;
|
|
||||||
getUiHandler().post(new Runnable() {
|
getUiHandler().post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
createChart(plotData);
|
||||||
|
|
||||||
if (!finalPreparedInput.isError()) {
|
final View view = getView();
|
||||||
createChart(finalPreparedInput);
|
if (view != null) {
|
||||||
|
createGraphicalView(view, plotData);
|
||||||
final View view = getView();
|
|
||||||
if (view != null) {
|
|
||||||
createGraphicalView(view, finalPreparedInput);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
onError();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -193,9 +153,9 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
|
|||||||
|
|
||||||
protected abstract void onError();
|
protected abstract void onError();
|
||||||
|
|
||||||
protected abstract void createGraphicalView(@NotNull View view, @NotNull PreparedInput preparedInput);
|
protected abstract void createGraphicalView(@NotNull View view, @NotNull PlotData plotData);
|
||||||
|
|
||||||
protected abstract void createChart(@NotNull PreparedInput preparedInput);
|
protected abstract void createChart(@NotNull PlotData plotData);
|
||||||
|
|
||||||
|
|
||||||
protected double getMaxValue(@Nullable PlotBoundaries plotBoundaries) {
|
protected double getMaxValue(@Nullable PlotBoundaries plotBoundaries) {
|
||||||
@ -219,11 +179,6 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
|
|||||||
return uiHandler;
|
return uiHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public PreparedInput getPreparedInput() {
|
|
||||||
return preparedInput;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getBgColor() {
|
public int getBgColor() {
|
||||||
return bgColor;
|
return bgColor;
|
||||||
}
|
}
|
||||||
@ -257,7 +212,7 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(@NotNull MenuItem data, @NotNull Context context) {
|
public void onClick(@NotNull MenuItem data, @NotNull Context context) {
|
||||||
onNewPreparedInput(PreparedInput.force3dInstance(preparedInput));
|
Locator.getInstance().getPlotter().setPlot3d(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -294,82 +249,6 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
|
|||||||
**********************************************************************
|
**********************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@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;
|
|
||||||
if ( variables.size() > 0 ) {
|
|
||||||
xVariable = variables.get(0);
|
|
||||||
} else {
|
|
||||||
xVariable = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Constant yVariable;
|
|
||||||
if ( variables.size() > 1 ) {
|
|
||||||
yVariable = variables.get(1);
|
|
||||||
} else {
|
|
||||||
yVariable = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final ParcelablePlotInput input = new ParcelablePlotInput(expression.toString(), xVariable == null ? null : 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 ParcelablePlotInput 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;
|
|
||||||
if (input.getXVariableName() != null) {
|
|
||||||
xVar = new Constant(input.getXVariableName());
|
|
||||||
} else {
|
|
||||||
xVar = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
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> {
|
private static enum PlotMenu implements IdentifiableMenuItem<MenuItem> {
|
||||||
|
|
||||||
preferences(R.id.menu_plot_settings) {
|
preferences(R.id.menu_plot_settings) {
|
||||||
@ -447,108 +326,19 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PreparedInput {
|
public static void applyToPaint(@NotNull PlotFunctionLineDef plotFunctionLineDef, @NotNull Paint paint) {
|
||||||
|
paint.setColor(plotFunctionLineDef.getLineColor());
|
||||||
|
paint.setStyle(Paint.Style.STROKE);
|
||||||
|
|
||||||
@Nullable
|
if ( plotFunctionLineDef.getLineWidth() == PlotFunctionLineDef.DEFAULT_LINE_WIDTH ) {
|
||||||
private ParcelablePlotInput input;
|
paint.setStrokeWidth(0);
|
||||||
|
} else {
|
||||||
@Nullable
|
paint.setStrokeWidth(plotFunctionLineDef.getLineWidth());
|
||||||
private Generic expression;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private Constant xVariable;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private Constant yVariable;
|
|
||||||
|
|
||||||
private boolean fromInputArgs;
|
|
||||||
|
|
||||||
private boolean force3d = false;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private PlotBoundaries plotBoundaries = PlotBoundaries.newDefaultInstance();
|
|
||||||
|
|
||||||
private PreparedInput() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
final AndroidPlotLineStyle androidPlotLineStyle = AndroidPlotLineStyle.valueOf(plotFunctionLineDef.getLineStyle());
|
||||||
public static PreparedInput newInstance(@NotNull ParcelablePlotInput input,
|
if (androidPlotLineStyle != null) {
|
||||||
@NotNull Generic expression,
|
androidPlotLineStyle.applyToPaint(paint);
|
||||||
@Nullable 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static PreparedInput force3dInstance(final PreparedInput that) {
|
|
||||||
if (!that.isError()) {
|
|
||||||
final PreparedInput result = PreparedInput.newInstance(that.input, that.expression, that.xVariable, that.yVariable, that.fromInputArgs, that.plotBoundaries);
|
|
||||||
result.force3d = true;
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
return that;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isFromInputArgs() {
|
|
||||||
return fromInputArgs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public ParcelablePlotInput 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 isForce3d() {
|
|
||||||
return force3d;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isError() {
|
|
||||||
return input == null || expression == null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,25 +8,25 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
* Date: 1/5/13
|
* Date: 1/5/13
|
||||||
* Time: 7:35 PM
|
* Time: 7:35 PM
|
||||||
*/
|
*/
|
||||||
public class FunctionPlotDef {
|
public class ArityPlotFunction {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Function function;
|
private Function function;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private FunctionLineDef lineDef;
|
private PlotFunctionLineDef lineDef;
|
||||||
|
|
||||||
private FunctionPlotDef() {
|
private ArityPlotFunction() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static FunctionPlotDef newInstance(@NotNull Function function) {
|
public static ArityPlotFunction newInstance(@NotNull Function function) {
|
||||||
return newInstance(function, FunctionLineDef.newDefaultInstance());
|
return newInstance(function, PlotFunctionLineDef.newDefaultInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static FunctionPlotDef newInstance(@NotNull Function function, @NotNull FunctionLineDef lineDef) {
|
public static ArityPlotFunction newInstance(@NotNull Function function, @NotNull PlotFunctionLineDef lineDef) {
|
||||||
final FunctionPlotDef result = new FunctionPlotDef();
|
final ArityPlotFunction result = new ArityPlotFunction();
|
||||||
|
|
||||||
result.function = function;
|
result.function = function;
|
||||||
result.lineDef = lineDef;
|
result.lineDef = lineDef;
|
||||||
@ -40,7 +40,7 @@ public class FunctionPlotDef {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public FunctionLineDef getLineDef() {
|
public PlotFunctionLineDef getLineDef() {
|
||||||
return lineDef;
|
return lineDef;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,8 +1,6 @@
|
|||||||
package org.solovyev.android.calculator.plot;
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import jscl.math.Generic;
|
import jscl.math.Generic;
|
||||||
@ -10,7 +8,6 @@ import jscl.math.function.Constant;
|
|||||||
import org.javia.arity.Function;
|
import org.javia.arity.Function;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.calculator.CalculatorPreferences;
|
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -38,13 +35,7 @@ public class CalculatorArityPlotFragment extends AbstractCalculatorPlotFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void createGraphicalView(@NotNull View root, @NotNull PreparedInput preparedInput) {
|
protected void createGraphicalView(@NotNull View root, @NotNull PlotData plotData) {
|
||||||
|
|
||||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
|
|
||||||
|
|
||||||
final GraphLineColor realLineColor = CalculatorPreferences.Graph.lineColorReal.getPreference(preferences);
|
|
||||||
final GraphLineColor imagLineColor = CalculatorPreferences.Graph.lineColorImag.getPreference(preferences);
|
|
||||||
final boolean plotImag = CalculatorPreferences.Graph.plotImag.getPreference(preferences);
|
|
||||||
|
|
||||||
// remove old
|
// remove old
|
||||||
final ViewGroup graphContainer = (ViewGroup) root.findViewById(R.id.main_fragment_layout);
|
final ViewGroup graphContainer = (ViewGroup) root.findViewById(R.id.main_fragment_layout);
|
||||||
@ -53,47 +44,42 @@ public class CalculatorArityPlotFragment extends AbstractCalculatorPlotFragment
|
|||||||
graphContainer.removeView((View) graphView);
|
graphContainer.removeView((View) graphView);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!preparedInput.isError()) {
|
final List<ArityPlotFunction> arityFunctions = new ArrayList<ArityPlotFunction>();
|
||||||
final Generic expression = preparedInput.getExpression();
|
|
||||||
final Constant xVariable = preparedInput.getXVariable();
|
for (PlotFunction plotFunction : plotData.getFunctions()) {
|
||||||
final Constant yVariable = preparedInput.getYVariable();
|
|
||||||
|
final XyFunction xyFunction = plotFunction.getXyFunction();
|
||||||
|
|
||||||
|
final Generic expression = xyFunction.getExpression();
|
||||||
|
final Constant xVariable = xyFunction.getXVariable();
|
||||||
|
final Constant yVariable = xyFunction.getYVariable();
|
||||||
|
|
||||||
final int arity = xVariable == null ? 0 : (yVariable == null ? 1 : 2);
|
final int arity = xVariable == null ? 0 : (yVariable == null ? 1 : 2);
|
||||||
|
|
||||||
final List<FunctionPlotDef> functions = new ArrayList<FunctionPlotDef>();
|
final Function arityFunction;
|
||||||
|
if (xyFunction.isImag()) {
|
||||||
functions.add(FunctionPlotDef.newInstance(new RealArityFunction(arity, expression, xVariable, yVariable), FunctionLineDef.newInstance(realLineColor.getColor(), FunctionLineStyle.solid, 3f, FunctionLineColorType.color_map)));
|
arityFunction = new ImaginaryArityFunction(arity, expression, xVariable, yVariable);
|
||||||
if (plotImag) {
|
} else {
|
||||||
functions.add(FunctionPlotDef.newInstance(new ImaginaryArityFunction(arity, expression, xVariable, yVariable), FunctionLineDef.newInstance(imagLineColor.getColor(), FunctionLineStyle.solid, 3f, FunctionLineColorType.color_map)));
|
arityFunction = new RealArityFunction(arity, expression, xVariable, yVariable);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (arity) {
|
arityFunctions.add(ArityPlotFunction.newInstance(arityFunction, plotFunction.getPlotFunctionLineDef()));
|
||||||
case 0:
|
|
||||||
case 1:
|
|
||||||
if (preparedInput.isForce3d()) {
|
|
||||||
graphView = new Graph3dView(getActivity());
|
|
||||||
} else {
|
|
||||||
graphView = new Graph2dView(getActivity());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
graphView = new Graph3dView(getActivity());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Unsupported arity: " + arity);
|
|
||||||
}
|
|
||||||
|
|
||||||
graphView.init(FunctionViewDef.newInstance(Color.WHITE, Color.WHITE, Color.DKGRAY, getBgColor()));
|
|
||||||
graphView.setFunctionPlotDefs(functions);
|
|
||||||
|
|
||||||
graphContainer.addView((View) graphView);
|
|
||||||
} else {
|
|
||||||
onError();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( plotData.isPlot3d() ) {
|
||||||
|
graphView = new Graph3dView(getActivity());
|
||||||
|
} else {
|
||||||
|
graphView = new Graph2dView(getActivity());
|
||||||
|
}
|
||||||
|
|
||||||
|
graphView.init(FunctionViewDef.newInstance(Color.WHITE, Color.WHITE, Color.DKGRAY, getBgColor()));
|
||||||
|
graphView.setFunctionPlotDefs(arityFunctions);
|
||||||
|
|
||||||
|
graphContainer.addView((View) graphView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void createChart(@NotNull PreparedInput preparedInput) {
|
protected void createChart(@NotNull PlotData plotData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -35,6 +35,6 @@ public class CalculatorPlotActivity extends CalculatorFragmentActivity {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static CalculatorFragmentType getPlotterFragmentType() {
|
public static CalculatorFragmentType getPlotterFragmentType() {
|
||||||
return CalculatorFragmentType.plotter_2;
|
return CalculatorFragmentType.plotter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,235 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
|
||||||
* For more information, please, contact se.solovyev@gmail.com
|
|
||||||
* or visit http://se.solovyev.org
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.solovyev.android.calculator.plot;
|
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import jscl.math.Generic;
|
|
||||||
import jscl.math.function.Constant;
|
|
||||||
import org.achartengine.chart.XYChart;
|
|
||||||
import org.achartengine.model.XYMultipleSeriesDataset;
|
|
||||||
import org.achartengine.model.XYSeries;
|
|
||||||
import org.achartengine.renderer.XYMultipleSeriesRenderer;
|
|
||||||
import org.achartengine.tools.PanListener;
|
|
||||||
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.CalculatorPreferences;
|
|
||||||
import org.solovyev.android.calculator.R;
|
|
||||||
import org.solovyev.common.MutableObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User: serso
|
|
||||||
* Date: 12/1/11
|
|
||||||
* Time: 12:40 AM
|
|
||||||
*/
|
|
||||||
public class CalculatorPlotFragment extends AbstractCalculatorPlotFragment {
|
|
||||||
|
|
||||||
public static final long EVAL_DELAY_MILLIS = 200;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private XYChart chart;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The encapsulated graphical view.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
private MyGraphicalView graphicalView;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
//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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean is3dPlotSupported() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
protected PlotBoundaries getPlotBoundaries() {
|
|
||||||
if (chart != null) {
|
|
||||||
return new PlotBoundaries(chart.getRenderer());
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (!getPreparedInput().isError()) {
|
|
||||||
final XYChart chart = this.chart;
|
|
||||||
assert chart != null;
|
|
||||||
|
|
||||||
final PlotBoundaries plotBoundaries = preparedInput.getPlotBoundaries();
|
|
||||||
double minValue = getMinValue(plotBoundaries);
|
|
||||||
double maxValue = getMaxValue(plotBoundaries);
|
|
||||||
|
|
||||||
// reverting boundaries (as in prepareChart() we add some cached values )
|
|
||||||
double minX = Double.MAX_VALUE;
|
|
||||||
double minY = Double.MAX_VALUE;
|
|
||||||
|
|
||||||
double maxX = Double.MIN_VALUE;
|
|
||||||
double maxY = Double.MIN_VALUE;
|
|
||||||
|
|
||||||
for (XYSeries series : chart.getDataset().getSeries()) {
|
|
||||||
minX = Math.min(minX, series.getMinX());
|
|
||||||
minY = Math.min(minY, series.getMinY());
|
|
||||||
maxX = Math.max(maxX, series.getMaxX());
|
|
||||||
maxY = Math.max(maxY, series.getMaxY());
|
|
||||||
}
|
|
||||||
|
|
||||||
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.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.getBgColor());
|
|
||||||
|
|
||||||
graphicalView.addZoomListener(new ZoomListener() {
|
|
||||||
@Override
|
|
||||||
public void zoomApplied(ZoomEvent e) {
|
|
||||||
updateDataSets(chart);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void zoomReset() {
|
|
||||||
updateDataSets(chart);
|
|
||||||
}
|
|
||||||
}, true, true);
|
|
||||||
|
|
||||||
graphicalView.addPanListener(new PanListener() {
|
|
||||||
@Override
|
|
||||||
public void panApplied() {
|
|
||||||
updateDataSets(chart);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
graphContainer.addView(graphicalView);
|
|
||||||
|
|
||||||
updateDataSets(chart, 50);
|
|
||||||
} else {
|
|
||||||
graphicalView = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void updateDataSets(@NotNull final XYChart chart) {
|
|
||||||
updateDataSets(chart, EVAL_DELAY_MILLIS);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateDataSets(@NotNull final XYChart chart, long millisToWait) {
|
|
||||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
|
|
||||||
final GraphLineColor imagLineColor = CalculatorPreferences.Graph.lineColorImag.getPreference(preferences);
|
|
||||||
|
|
||||||
final PreparedInput preparedInput = getPreparedInput();
|
|
||||||
|
|
||||||
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() {
|
|
||||||
// allow only one runner at one time
|
|
||||||
synchronized (pendingOperation) {
|
|
||||||
//lock all operations with history
|
|
||||||
if (pendingOperation.getObject() == this) {
|
|
||||||
|
|
||||||
getPlotExecutor().execute(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
final XYMultipleSeriesRenderer dr = chart.getRenderer();
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
getUiHandler().post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
graphicalView.repaint();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
getUiHandler().postDelayed(pendingOperation.getObject(), millisToWait);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final MutableObject<Runnable> pendingOperation = new MutableObject<Runnable>();
|
|
||||||
|
|
||||||
|
|
||||||
/* public void zoomInClickHandler(@NotNull View v) {
|
|
||||||
this.graphicalView.zoomIn();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void zoomOutClickHandler(@NotNull View v) {
|
|
||||||
this.graphicalView.zoomOut();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
public void onError() {
|
|
||||||
this.chart = null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,7 +12,7 @@ final class CalculatorPlotFunctionsController {
|
|||||||
private static final CalculatorPlotFunctionsController instance = new CalculatorPlotFunctionsController();
|
private static final CalculatorPlotFunctionsController instance = new CalculatorPlotFunctionsController();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final List<ParcelablePlotInput> functions = new ArrayList<ParcelablePlotInput>();
|
private final List<XyFunction> functions = new ArrayList<XyFunction>();
|
||||||
|
|
||||||
private CalculatorPlotFunctionsController() {
|
private CalculatorPlotFunctionsController() {
|
||||||
}
|
}
|
||||||
@ -23,11 +23,11 @@ final class CalculatorPlotFunctionsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<ParcelablePlotInput> getFunctions() {
|
public List<XyFunction> getFunctions() {
|
||||||
return Collections.unmodifiableList(functions);
|
return Collections.unmodifiableList(functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean addFunction(@NotNull ParcelablePlotInput function) {
|
public boolean addFunction(@NotNull XyFunction function) {
|
||||||
if (!functions.contains(function)) {
|
if (!functions.contains(function)) {
|
||||||
return functions.add(function);
|
return functions.add(function);
|
||||||
} else {
|
} else {
|
||||||
|
@ -23,9 +23,9 @@ public class CalculatorPlotFunctionsFragment extends CalculatorListFragment {
|
|||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
final List<ParcelablePlotInputListItem> items = Lists.transform(CalculatorPlotFunctionsController.getInstance().getFunctions(), new Function<ParcelablePlotInput, ParcelablePlotInputListItem>() {
|
final List<ParcelablePlotInputListItem> items = Lists.transform(CalculatorPlotFunctionsController.getInstance().getFunctions(), new Function<XyFunction, ParcelablePlotInputListItem>() {
|
||||||
@Override
|
@Override
|
||||||
public ParcelablePlotInputListItem apply(@Nullable ParcelablePlotInput input) {
|
public ParcelablePlotInputListItem apply(@Nullable XyFunction input) {
|
||||||
return new ParcelablePlotInputListItem(input);
|
return new ParcelablePlotInputListItem(input);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -86,12 +86,12 @@ public class Graph2dView extends View implements GraphView {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(@NotNull FunctionViewDef functionViewDef) {
|
public void init(@NotNull FunctionViewDef functionViewDef) {
|
||||||
this.graphViewHelper = GraphViewHelper.newInstance(functionViewDef, Collections.<FunctionPlotDef>emptyList());
|
this.graphViewHelper = GraphViewHelper.newInstance(functionViewDef, Collections.<ArityPlotFunction>emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFunctionPlotDefs(@NotNull List<FunctionPlotDef> functionPlotDefs) {
|
public void setFunctionPlotDefs(@NotNull List<ArityPlotFunction> functionPlotDefs) {
|
||||||
|
|
||||||
for (FunctionPlotDef functionPlotDef: functionPlotDefs) {
|
for (ArityPlotFunction functionPlotDef: functionPlotDefs) {
|
||||||
final int arity = functionPlotDef.getFunction().arity();
|
final int arity = functionPlotDef.getFunction().arity();
|
||||||
if (arity != 0 && arity != 1) {
|
if (arity != 0 && arity != 1) {
|
||||||
throw new IllegalArgumentException("Function must have arity 0 or 1 for 2d plot!");
|
throw new IllegalArgumentException("Function must have arity 0 or 1 for 2d plot!");
|
||||||
@ -348,15 +348,16 @@ public class Graph2dView extends View implements GraphView {
|
|||||||
private static StringBuilder b = new StringBuilder();
|
private static StringBuilder b = new StringBuilder();
|
||||||
private static char[] buf = new char[20];
|
private static char[] buf = new char[20];
|
||||||
|
|
||||||
private static StringBuilder format(float fv) {
|
private static StringBuilder format(final float value) {
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
boolean addDot = false;
|
boolean addDot = false;
|
||||||
int v = Math.round(fv * 100);
|
|
||||||
boolean isNeg = v < 0;
|
final boolean negative = value < 0;
|
||||||
v = isNeg ? -v : v;
|
|
||||||
|
int absValue = Math.round(Math.abs(value) * 100);
|
||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
int digit = v % 10;
|
int digit = absValue % 10;
|
||||||
v /= 10;
|
absValue /= 10;
|
||||||
if (digit != 0 || addDot) {
|
if (digit != 0 || addDot) {
|
||||||
buf[pos++] = (char) ('0' + digit);
|
buf[pos++] = (char) ('0' + digit);
|
||||||
addDot = true;
|
addDot = true;
|
||||||
@ -365,14 +366,14 @@ public class Graph2dView extends View implements GraphView {
|
|||||||
if (addDot) {
|
if (addDot) {
|
||||||
buf[pos++] = '.';
|
buf[pos++] = '.';
|
||||||
}
|
}
|
||||||
if (v == 0) {
|
if (absValue == 0) {
|
||||||
buf[pos++] = '0';
|
buf[pos++] = '0';
|
||||||
}
|
}
|
||||||
while (v != 0) {
|
while (absValue != 0) {
|
||||||
buf[pos++] = (char) ('0' + (v % 10));
|
buf[pos++] = (char) ('0' + (absValue % 10));
|
||||||
v /= 10;
|
absValue /= 10;
|
||||||
}
|
}
|
||||||
if (isNeg) {
|
if (negative) {
|
||||||
buf[pos++] = '-';
|
buf[pos++] = '-';
|
||||||
}
|
}
|
||||||
b.setLength(0);
|
b.setLength(0);
|
||||||
@ -459,13 +460,16 @@ public class Graph2dView extends View implements GraphView {
|
|||||||
paint.setPathEffect(null);
|
paint.setPathEffect(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// AXIS
|
{
|
||||||
|
// AXIS
|
||||||
|
|
||||||
paint.setColor(graphViewHelper.getFunctionViewDef().getAxisColor());
|
paint.setColor(graphViewHelper.getFunctionViewDef().getAxisColor());
|
||||||
if (drawYAxis) {
|
if (drawYAxis) {
|
||||||
canvas.drawLine(x0, 0, x0, height, paint);
|
canvas.drawLine(x0, 0, x0, height, paint);
|
||||||
|
}
|
||||||
|
canvas.drawLine(0, y0, width, y0, paint);
|
||||||
}
|
}
|
||||||
canvas.drawLine(0, y0, width, y0, paint);
|
|
||||||
|
|
||||||
matrix.reset();
|
matrix.reset();
|
||||||
matrix.preTranslate(-currentX, -currentY);
|
matrix.preTranslate(-currentX, -currentY);
|
||||||
@ -474,23 +478,29 @@ public class Graph2dView extends View implements GraphView {
|
|||||||
|
|
||||||
paint.setAntiAlias(false);
|
paint.setAntiAlias(false);
|
||||||
|
|
||||||
final List<FunctionPlotDef> functionPlotDefs = graphViewHelper.getFunctionPlotDefs();
|
{
|
||||||
|
//GRAPH
|
||||||
|
|
||||||
// create path once
|
final List<ArityPlotFunction> functionPlotDefs = graphViewHelper.getFunctionPlotDefs();
|
||||||
final Path path = new Path();
|
|
||||||
|
|
||||||
for (int i = 0; i < functionPlotDefs.size(); i++) {
|
// create path once
|
||||||
final FunctionPlotDef fpd = functionPlotDefs.get(i);
|
final Path path = new Path();
|
||||||
computeGraph(fpd.getFunction(), minX, maxX, boundMinY, boundMaxY, graphs.get(i));
|
|
||||||
|
|
||||||
graphToPath(graphs.get(i), path);
|
for (int i = 0; i < functionPlotDefs.size(); i++) {
|
||||||
|
final ArityPlotFunction fpd = functionPlotDefs.get(i);
|
||||||
|
computeGraph(fpd.getFunction(), minX, maxX, boundMinY, boundMaxY, graphs.get(i));
|
||||||
|
|
||||||
path.transform(matrix);
|
graphToPath(graphs.get(i), path);
|
||||||
|
|
||||||
fpd.getLineDef().applyToPaint(paint);
|
path.transform(matrix);
|
||||||
|
|
||||||
canvas.drawPath(path, paint);
|
AbstractCalculatorPlotFragment.applyToPaint(fpd.getLineDef(), paint);
|
||||||
|
|
||||||
|
canvas.drawPath(path, paint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
lastMinX = minX;
|
lastMinX = minX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,637 @@
|
|||||||
|
// Copyright (C) 2009-2010 Mihai Preda
|
||||||
|
|
||||||
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.*;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Scroller;
|
||||||
|
import android.widget.ZoomButtonsController;
|
||||||
|
import org.javia.arity.Function;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.android.AndroidUtils2;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Graph2dViewNew extends View implements GraphView {
|
||||||
|
|
||||||
|
// view width and height
|
||||||
|
private int width;
|
||||||
|
private int height;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Matrix matrix = new Matrix();
|
||||||
|
|
||||||
|
// paints
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Paint paint = new Paint();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Paint textPaint = new Paint();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Paint fillPaint = new Paint();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private GraphViewHelper graphViewHelper = GraphViewHelper.newDefaultInstance();
|
||||||
|
|
||||||
|
private final GraphData next = GraphData.newEmptyInstance();
|
||||||
|
|
||||||
|
private final GraphData endGraph = GraphData.newEmptyInstance();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private List<GraphData> graphs = new ArrayList<GraphData>(graphViewHelper.getFunctionPlotDefs().size());
|
||||||
|
|
||||||
|
private float x0;
|
||||||
|
private float y0;
|
||||||
|
private float graphWidth = 20;
|
||||||
|
|
||||||
|
private float lastXMin;
|
||||||
|
|
||||||
|
private float lastYMin;
|
||||||
|
private float lastYMax;
|
||||||
|
|
||||||
|
private float lastTouchX, lastTouchY;
|
||||||
|
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private TouchHandler touchHandler;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected ZoomButtonsController zoomController = new ZoomButtonsController(this);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private ZoomTracker zoomTracker = new ZoomTracker();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Scroller scroller;
|
||||||
|
|
||||||
|
public Graph2dViewNew(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Graph2dViewNew(Context context) {
|
||||||
|
super(context);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(Context context) {
|
||||||
|
touchHandler = new TouchHandler(this);
|
||||||
|
zoomController.setOnZoomListener(this);
|
||||||
|
scroller = new Scroller(context);
|
||||||
|
|
||||||
|
paint.setAntiAlias(false);
|
||||||
|
textPaint.setAntiAlias(true);
|
||||||
|
|
||||||
|
width = this.getWidth();
|
||||||
|
height = this.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String captureScreenshot() {
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
|
||||||
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
onDraw(canvas);
|
||||||
|
return AndroidUtils2.saveBitmap(bitmap, GraphView.SCREENSHOT_DIR, "calculator");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearAllGraphs() {
|
||||||
|
for (GraphData graph : graphs) {
|
||||||
|
graph.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( graphViewHelper.getFunctionPlotDefs().size() > graphs.size() ) {
|
||||||
|
graphs.add(GraphData.newEmptyInstance());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(@NotNull FunctionViewDef functionViewDef) {
|
||||||
|
this.graphViewHelper = GraphViewHelper.newInstance(functionViewDef, Collections.<ArityPlotFunction>emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFunctionPlotDefs(@NotNull List<ArityPlotFunction> functionPlotDefs) {
|
||||||
|
|
||||||
|
for (ArityPlotFunction functionPlotDef: functionPlotDefs) {
|
||||||
|
final int arity = functionPlotDef.getFunction().arity();
|
||||||
|
if (arity != 0 && arity != 1) {
|
||||||
|
throw new IllegalArgumentException("Function must have arity 0 or 1 for 2d plot!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.graphViewHelper = this.graphViewHelper.copy(functionPlotDefs);
|
||||||
|
clearAllGraphs();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onVisibilityChanged(boolean visible) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onZoom(boolean zoomIn) {
|
||||||
|
if (zoomIn) {
|
||||||
|
if (canZoomIn()) {
|
||||||
|
graphWidth /= 2;
|
||||||
|
invalidateGraphs();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (canZoomOut()) {
|
||||||
|
graphWidth *= 2;
|
||||||
|
invalidateGraphs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zoomController.setZoomInEnabled(canZoomIn());
|
||||||
|
zoomController.setZoomOutEnabled(canZoomOut());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResume() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPause() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDetachedFromWindow() {
|
||||||
|
zoomController.setVisible(false);
|
||||||
|
super.onDetachedFromWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onSizeChanged(int w, int h, int ow, int oh) {
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
clearAllGraphs();
|
||||||
|
// points = new float[w+w];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onDraw(Canvas canvas) {
|
||||||
|
if (graphViewHelper.getFunctionPlotDefs().size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (scroller.computeScrollOffset()) {
|
||||||
|
final float scale = graphWidth / width;
|
||||||
|
x0 = scroller.getCurrX() * scale;
|
||||||
|
y0 = scroller.getCurrY() * scale;
|
||||||
|
if (!scroller.isFinished()) {
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drawGraph(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float eval(Function f, float x) {
|
||||||
|
float v = (float) f.eval(x);
|
||||||
|
// Calculator.log("eval " + x + "; " + v);
|
||||||
|
if (v < -10000f) {
|
||||||
|
return -10000f;
|
||||||
|
}
|
||||||
|
if (v > 10000f) {
|
||||||
|
return 10000f;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// distance from (x,y) to the line (x1,y1) to (x2,y2), squared, multiplied by 4
|
||||||
|
/*
|
||||||
|
private float distance(float x1, float y1, float x2, float y2, float x, float y) {
|
||||||
|
float dx = x2 - x1;
|
||||||
|
float dy = y2 - y1;
|
||||||
|
float mx = x - x1;
|
||||||
|
float my = y - y1;
|
||||||
|
float up = dx*my - dy*mx;
|
||||||
|
return up*up*4/(dx*dx + dy*dy);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// distance as above when x==(x1+x2)/2.
|
||||||
|
private float distance2(float x1, float y1, float x2, float y2, float y) {
|
||||||
|
final float dx = x2 - x1;
|
||||||
|
final float dy = y2 - y1;
|
||||||
|
final float up = dx * (y1 + y2 - y - y);
|
||||||
|
return up * up / (dx * dx + dy * dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void computeGraph(@NotNull Function function,
|
||||||
|
float xMin,
|
||||||
|
float xMax,
|
||||||
|
float yMin,
|
||||||
|
float yMax,
|
||||||
|
@NotNull GraphData graph) {
|
||||||
|
if (function.arity() == 0) {
|
||||||
|
float v = (float) function.eval();
|
||||||
|
if (v < -10000f) {
|
||||||
|
v = -10000f;
|
||||||
|
}
|
||||||
|
if (v > 10000f) {
|
||||||
|
v = 10000f;
|
||||||
|
}
|
||||||
|
graph.clear();
|
||||||
|
graph.push(xMin, v);
|
||||||
|
graph.push(xMax, v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare graph
|
||||||
|
if (!graph.empty()) {
|
||||||
|
if (xMin >= lastXMin) {
|
||||||
|
graph.eraseBefore(xMin);
|
||||||
|
} else {
|
||||||
|
graph.eraseAfter(xMax);
|
||||||
|
xMax = Math.min(xMax, graph.firstX());
|
||||||
|
graph.swap(endGraph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (graph.empty()) {
|
||||||
|
graph.push(xMin, eval(function, xMin));
|
||||||
|
}
|
||||||
|
|
||||||
|
final float scale = width / graphWidth;
|
||||||
|
final float maxStep = 15.8976f / scale;
|
||||||
|
final float minStep = .05f / scale;
|
||||||
|
float ythresh = 1 / scale;
|
||||||
|
ythresh = ythresh * ythresh;
|
||||||
|
|
||||||
|
|
||||||
|
float leftX, leftY;
|
||||||
|
float rightX = graph.topX(), rightY = graph.topY();
|
||||||
|
int nEval = 1;
|
||||||
|
while (true) {
|
||||||
|
leftX = rightX;
|
||||||
|
leftY = rightY;
|
||||||
|
if (leftX > xMax) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (next.empty()) {
|
||||||
|
float x = leftX + maxStep;
|
||||||
|
next.push(x, eval(function, x));
|
||||||
|
++nEval;
|
||||||
|
}
|
||||||
|
rightX = next.topX();
|
||||||
|
rightY = next.topY();
|
||||||
|
next.pop();
|
||||||
|
|
||||||
|
if (leftY != leftY && rightY != rightY) { // NaN
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float dx = rightX - leftX;
|
||||||
|
float middleX = (leftX + rightX) / 2;
|
||||||
|
float middleY = eval(function, middleX);
|
||||||
|
++nEval;
|
||||||
|
boolean middleIsOutside = (middleY < leftY && middleY < rightY) || (leftY < middleY && rightY < middleY);
|
||||||
|
if (dx < minStep) {
|
||||||
|
// Calculator.log("minStep");
|
||||||
|
if (middleIsOutside) {
|
||||||
|
graph.push(rightX, Float.NaN);
|
||||||
|
}
|
||||||
|
graph.push(rightX, rightY);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (middleIsOutside && ((leftY < yMin && rightY > yMax) || (leftY > yMax && rightY < yMin))) {
|
||||||
|
graph.push(rightX, Float.NaN);
|
||||||
|
graph.push(rightX, rightY);
|
||||||
|
// Calculator.log("+-inf");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!middleIsOutside) {
|
||||||
|
/*
|
||||||
|
float diff = leftY + rightY - middleY - middleY;
|
||||||
|
float dy = rightY - leftY;
|
||||||
|
float dx2 = dx*dx;
|
||||||
|
float distance = dx2*diff*diff/(dx2+dy*dy);
|
||||||
|
*/
|
||||||
|
// Calculator.log("" + dx + ' ' + leftY + ' ' + middleY + ' ' + rightY + ' ' + distance + ' ' + ythresh);
|
||||||
|
if (distance2(leftX, leftY, rightX, rightY, middleY) < ythresh) {
|
||||||
|
graph.push(rightX, rightY);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next.push(rightX, rightY);
|
||||||
|
next.push(middleX, middleY);
|
||||||
|
rightX = leftX;
|
||||||
|
rightY = leftY;
|
||||||
|
}
|
||||||
|
if (!endGraph.empty()) {
|
||||||
|
graph.append(endGraph);
|
||||||
|
}
|
||||||
|
long t2 = System.currentTimeMillis();
|
||||||
|
// Calculator.log("graph points " + graph.size + " evals " + nEval + " time " + (t2-t1));
|
||||||
|
|
||||||
|
next.clear();
|
||||||
|
endGraph.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void graphToPath(@NotNull GraphData graph, @NotNull Path path) {
|
||||||
|
|
||||||
|
final int size = graph.getSize();
|
||||||
|
final float[] xs = graph.getXs();
|
||||||
|
final float[] ys = graph.getYs();
|
||||||
|
|
||||||
|
path.rewind();
|
||||||
|
|
||||||
|
boolean newCurve = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
|
||||||
|
final float y = ys[i];
|
||||||
|
final float x = xs[i];
|
||||||
|
|
||||||
|
if (y != y) {
|
||||||
|
newCurve = true;
|
||||||
|
} else { // !NaN
|
||||||
|
if (newCurve) {
|
||||||
|
path.moveTo(x, y);
|
||||||
|
newCurve = false;
|
||||||
|
} else {
|
||||||
|
path.lineTo(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final float NTICKS = 15;
|
||||||
|
|
||||||
|
private static float stepFactor(float w) {
|
||||||
|
float f = 1;
|
||||||
|
while (w / f > NTICKS) {
|
||||||
|
f *= 10;
|
||||||
|
}
|
||||||
|
while (w / f < NTICKS / 10) {
|
||||||
|
f /= 10;
|
||||||
|
}
|
||||||
|
float r = w / f;
|
||||||
|
if (r < NTICKS / 5) {
|
||||||
|
return f / 5;
|
||||||
|
} else if (r < NTICKS / 2) {
|
||||||
|
return f / 2;
|
||||||
|
} else {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static StringBuilder b = new StringBuilder();
|
||||||
|
private static char[] buf = new char[20];
|
||||||
|
|
||||||
|
private static StringBuilder format(final float value) {
|
||||||
|
int pos = 0;
|
||||||
|
boolean addDot = false;
|
||||||
|
|
||||||
|
final boolean negative = value < 0;
|
||||||
|
|
||||||
|
int absValue = Math.round(Math.abs(value) * 100);
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
int digit = absValue % 10;
|
||||||
|
absValue /= 10;
|
||||||
|
if (digit != 0 || addDot) {
|
||||||
|
buf[pos++] = (char) ('0' + digit);
|
||||||
|
addDot = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (addDot) {
|
||||||
|
buf[pos++] = '.';
|
||||||
|
}
|
||||||
|
if (absValue == 0) {
|
||||||
|
buf[pos++] = '0';
|
||||||
|
}
|
||||||
|
while (absValue != 0) {
|
||||||
|
buf[pos++] = (char) ('0' + (absValue % 10));
|
||||||
|
absValue /= 10;
|
||||||
|
}
|
||||||
|
if (negative) {
|
||||||
|
buf[pos++] = '-';
|
||||||
|
}
|
||||||
|
b.setLength(0);
|
||||||
|
b.append(buf, 0, pos);
|
||||||
|
b.reverse();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawGraph(Canvas canvas) {
|
||||||
|
|
||||||
|
final float xMin = getXMin();
|
||||||
|
final float xMax = getXMax(xMin);
|
||||||
|
|
||||||
|
float graphHeight = graphWidth * height / width;
|
||||||
|
float yMin = y0 - graphHeight / 2;
|
||||||
|
float yMax = yMin + graphHeight;
|
||||||
|
|
||||||
|
if (yMin < lastYMin || yMax > lastYMax) {
|
||||||
|
float halfGraphHeight = graphHeight / 2;
|
||||||
|
lastYMin = yMin - halfGraphHeight;
|
||||||
|
lastYMax = yMax + halfGraphHeight;
|
||||||
|
clearAllGraphs();
|
||||||
|
}
|
||||||
|
|
||||||
|
// set background
|
||||||
|
canvas.drawColor(graphViewHelper.getFunctionViewDef().getBackgroundColor());
|
||||||
|
|
||||||
|
// prepare paint
|
||||||
|
paint.setStrokeWidth(0);
|
||||||
|
paint.setAntiAlias(false);
|
||||||
|
paint.setStyle(Paint.Style.STROKE);
|
||||||
|
|
||||||
|
final float scale = width / graphWidth;
|
||||||
|
|
||||||
|
float x0 = -xMin * scale;
|
||||||
|
boolean drawYAxis = true;
|
||||||
|
if (x0 < 25) {
|
||||||
|
x0 = 25;
|
||||||
|
// drawYAxis = false;
|
||||||
|
} else if (x0 > width - 3) {
|
||||||
|
x0 = width - 3;
|
||||||
|
// drawYAxis = false;
|
||||||
|
}
|
||||||
|
float y0 = yMax * scale;
|
||||||
|
if (y0 < 3) {
|
||||||
|
y0 = 3;
|
||||||
|
} else if (y0 > height - 15) {
|
||||||
|
y0 = height - 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
final float tickSize = 3;
|
||||||
|
final float y2 = y0 + tickSize;
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
// GRID
|
||||||
|
|
||||||
|
paint.setPathEffect(new DashPathEffect(new float[]{5, 10}, 0));
|
||||||
|
paint.setColor(graphViewHelper.getFunctionViewDef().getGridColor());
|
||||||
|
|
||||||
|
float step = stepFactor(graphWidth);
|
||||||
|
// Calculator.log("width " + gwidth + " step " + step);
|
||||||
|
float v = ((int) (xMin / step)) * step;
|
||||||
|
textPaint.setColor(graphViewHelper.getFunctionViewDef().getAxisLabelsColor());
|
||||||
|
textPaint.setTextSize(12);
|
||||||
|
textPaint.setTextAlign(Paint.Align.CENTER);
|
||||||
|
float stepScale = step * scale;
|
||||||
|
for (float x = (v - xMin) * scale; x <= width; x += stepScale, v += step) {
|
||||||
|
canvas.drawLine(x, 0, x, height, paint);
|
||||||
|
if (!(-.001f < v && v < .001f)) {
|
||||||
|
StringBuilder b = format(v);
|
||||||
|
canvas.drawText(b, 0, b.length(), x, y2 + 10, textPaint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final float x1 = x0 - tickSize;
|
||||||
|
v = ((int) (yMin / step)) * step;
|
||||||
|
textPaint.setTextAlign(Paint.Align.RIGHT);
|
||||||
|
for (float y = height - (v - yMin) * scale; y >= 0; y -= stepScale, v += step) {
|
||||||
|
canvas.drawLine(0, y, width, y, paint);
|
||||||
|
if (!(-.001f < v && v < .001f)) {
|
||||||
|
StringBuilder b = format(v);
|
||||||
|
canvas.drawText(b, 0, b.length(), x1, y + 4, textPaint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
paint.setPathEffect(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// AXIS
|
||||||
|
|
||||||
|
paint.setColor(graphViewHelper.getFunctionViewDef().getAxisColor());
|
||||||
|
if (drawYAxis) {
|
||||||
|
canvas.drawLine(x0, 0, x0, height, paint);
|
||||||
|
}
|
||||||
|
canvas.drawLine(0, y0, width, y0, paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
matrix.reset();
|
||||||
|
matrix.preTranslate(-this.x0, -this.y0);
|
||||||
|
matrix.postScale(scale, -scale);
|
||||||
|
matrix.postTranslate(width / 2, height / 2);
|
||||||
|
|
||||||
|
paint.setAntiAlias(false);
|
||||||
|
|
||||||
|
{
|
||||||
|
//GRAPH
|
||||||
|
|
||||||
|
final List<ArityPlotFunction> functionPlotDefs = graphViewHelper.getFunctionPlotDefs();
|
||||||
|
|
||||||
|
// create path once
|
||||||
|
final Path path = new Path();
|
||||||
|
|
||||||
|
for (int i = 0; i < functionPlotDefs.size(); i++) {
|
||||||
|
final ArityPlotFunction fpd = functionPlotDefs.get(i);
|
||||||
|
computeGraph(fpd.getFunction(), xMin, xMax, lastYMin, lastYMax, graphs.get(i));
|
||||||
|
|
||||||
|
graphToPath(graphs.get(i), path);
|
||||||
|
|
||||||
|
path.transform(matrix);
|
||||||
|
|
||||||
|
AbstractCalculatorPlotFragment.applyToPaint(fpd.getLineDef(), paint);
|
||||||
|
|
||||||
|
canvas.drawPath(path, paint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
lastXMin = xMin;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float getXMax(float minX) {
|
||||||
|
return minX + graphWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float getXMax() {
|
||||||
|
return getXMax(getXMin());
|
||||||
|
}
|
||||||
|
|
||||||
|
private float getXMin() {
|
||||||
|
return x0 - graphWidth / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canZoomIn() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canZoomOut() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void invalidateGraphs() {
|
||||||
|
clearAllGraphs();
|
||||||
|
lastYMin = lastYMax = 0;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
return touchHandler != null ? touchHandler.onTouchEvent(event) : super.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onTouchDown(float x, float y) {
|
||||||
|
zoomController.setVisible(true);
|
||||||
|
if (!scroller.isFinished()) {
|
||||||
|
scroller.abortAnimation();
|
||||||
|
}
|
||||||
|
lastTouchX = x;
|
||||||
|
lastTouchY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onTouchMove(float x, float y) {
|
||||||
|
float deltaX = x - lastTouchX;
|
||||||
|
float deltaY = y - lastTouchY;
|
||||||
|
if (deltaX < -1 || deltaX > 1 || deltaY < -1 || deltaY > 1) {
|
||||||
|
scroll(-deltaX, deltaY);
|
||||||
|
lastTouchX = x;
|
||||||
|
lastTouchY = y;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onTouchUp(float x, float y) {
|
||||||
|
final float scale = width / graphWidth;
|
||||||
|
float sx = -touchHandler.velocityTracker.getXVelocity();
|
||||||
|
float sy = touchHandler.velocityTracker.getYVelocity();
|
||||||
|
final float asx = Math.abs(sx);
|
||||||
|
final float asy = Math.abs(sy);
|
||||||
|
if (asx < asy / 3) {
|
||||||
|
sx = 0;
|
||||||
|
} else if (asy < asx / 3) {
|
||||||
|
sy = 0;
|
||||||
|
}
|
||||||
|
scroller.fling(Math.round(x0 * scale),
|
||||||
|
Math.round(y0 * scale),
|
||||||
|
Math.round(sx), Math.round(sy), -10000, 10000, -10000, 10000);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onTouchZoomDown(float x1, float y1, float x2, float y2) {
|
||||||
|
zoomTracker.start(graphWidth, x1, y1, x2, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onTouchZoomMove(float x1, float y1, float x2, float y2) {
|
||||||
|
if (!zoomTracker.update(x1, y1, x2, y2)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
float targetGwidth = zoomTracker.value;
|
||||||
|
if (targetGwidth > .25f && targetGwidth < 200) {
|
||||||
|
graphWidth = targetGwidth;
|
||||||
|
}
|
||||||
|
// scroll(-zoomTracker.moveX, zoomTracker.moveY);
|
||||||
|
invalidateGraphs();
|
||||||
|
// Calculator.log("zoom redraw");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scroll(float deltaX, float deltaY) {
|
||||||
|
final float scale = graphWidth / width;
|
||||||
|
float dx = deltaX * scale;
|
||||||
|
float dy = deltaY * scale;
|
||||||
|
final float adx = Math.abs(dx);
|
||||||
|
final float ady = Math.abs(dy);
|
||||||
|
if (adx < ady / 3) {
|
||||||
|
dx = 0;
|
||||||
|
} else if (ady < adx / 3) {
|
||||||
|
dy = 0;
|
||||||
|
}
|
||||||
|
x0 += dx;
|
||||||
|
y0 += dy;
|
||||||
|
}
|
||||||
|
}
|
@ -92,9 +92,9 @@ class Graph3d {
|
|||||||
return bb;
|
return bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(@NotNull GL11 gl, @NotNull FunctionPlotDef fpd, float zoom) {
|
public void update(@NotNull GL11 gl, @NotNull ArityPlotFunction fpd, float zoom) {
|
||||||
final Function function = fpd.getFunction();
|
final Function function = fpd.getFunction();
|
||||||
final FunctionLineDef lineDef = fpd.getLineDef();
|
final PlotFunctionLineDef lineDef = fpd.getLineDef();
|
||||||
final int NTICK = useHighQuality3d ? 5 : 0;
|
final int NTICK = useHighQuality3d ? 5 : 0;
|
||||||
|
|
||||||
final float size = 4 * zoom;
|
final float size = 4 * zoom;
|
||||||
@ -285,7 +285,7 @@ class Graph3d {
|
|||||||
return maxAbsZ;
|
return maxAbsZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] prepareFunctionPolygonColors(FunctionLineDef lineDef, float[] vertices, float maxAbsZ) {
|
private byte[] prepareFunctionPolygonColors(PlotFunctionLineDef lineDef, float[] vertices, float maxAbsZ) {
|
||||||
// 4 color components per polygon (color[i] = red, color[i+1] = green, color[i+2] = blue, color[i+3] = alpha )
|
// 4 color components per polygon (color[i] = red, color[i+1] = green, color[i+2] = blue, color[i+3] = alpha )
|
||||||
final byte colors[] = new byte[polygonsⁿ * COLOR_COMPONENTS_COUNT];
|
final byte colors[] = new byte[polygonsⁿ * COLOR_COMPONENTS_COUNT];
|
||||||
|
|
||||||
@ -295,7 +295,7 @@ class Graph3d {
|
|||||||
final float z = vertices[j];
|
final float z = vertices[j];
|
||||||
|
|
||||||
if (!Float.isNaN(z)) {
|
if (!Float.isNaN(z)) {
|
||||||
if (lineDef.getLineColorType() == FunctionLineColorType.color_map) {
|
if (lineDef.getLineColorType() == PlotFunctionLineColorType.color_map) {
|
||||||
final float color = z / maxAbsZ;
|
final float color = z / maxAbsZ;
|
||||||
final float abs = Math.abs(color);
|
final float abs = Math.abs(color);
|
||||||
colors[i] = floatToByte(color);
|
colors[i] = floatToByte(color);
|
||||||
|
@ -174,11 +174,11 @@ public class Graph3dView extends GLView implements GraphView {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(@NotNull FunctionViewDef functionViewDef) {
|
public void init(@NotNull FunctionViewDef functionViewDef) {
|
||||||
this.graphViewHelper = GraphViewHelper.newInstance(functionViewDef, Collections.<FunctionPlotDef>emptyList());
|
this.graphViewHelper = GraphViewHelper.newInstance(functionViewDef, Collections.<ArityPlotFunction>emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFunctionPlotDefs(@NotNull List<FunctionPlotDef> functionPlotDefs) {
|
public void setFunctionPlotDefs(@NotNull List<ArityPlotFunction> functionPlotDefs) {
|
||||||
for (FunctionPlotDef functionPlotDef: functionPlotDefs) {
|
for (ArityPlotFunction functionPlotDef: functionPlotDefs) {
|
||||||
final int arity = functionPlotDef.getFunction().arity();
|
final int arity = functionPlotDef.getFunction().arity();
|
||||||
if (arity != 0 && arity != 1 && arity != 2) {
|
if (arity != 0 && arity != 1 && arity != 2) {
|
||||||
throw new IllegalArgumentException("Function must have arity 0 or 1 or 2 for 3d plot!");
|
throw new IllegalArgumentException("Function must have arity 0 or 1 or 2 for 3d plot!");
|
||||||
|
@ -13,7 +13,7 @@ public interface GraphView extends ZoomButtonsController.OnZoomListener, TouchHa
|
|||||||
|
|
||||||
public void init(@NotNull FunctionViewDef functionViewDef);
|
public void init(@NotNull FunctionViewDef functionViewDef);
|
||||||
|
|
||||||
public void setFunctionPlotDefs(@NotNull List<FunctionPlotDef> functionPlotDefs);
|
public void setFunctionPlotDefs(@NotNull List<ArityPlotFunction> functionPlotDefs);
|
||||||
|
|
||||||
public void onPause();
|
public void onPause();
|
||||||
public void onResume();
|
public void onResume();
|
||||||
|
@ -16,7 +16,7 @@ public class GraphViewHelper {
|
|||||||
private FunctionViewDef functionViewDef = FunctionViewDef.newDefaultInstance();
|
private FunctionViewDef functionViewDef = FunctionViewDef.newDefaultInstance();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private List<FunctionPlotDef> functionPlotDefs = Collections.emptyList();
|
private List<ArityPlotFunction> functionPlotDefs = Collections.emptyList();
|
||||||
|
|
||||||
private GraphViewHelper() {
|
private GraphViewHelper() {
|
||||||
}
|
}
|
||||||
@ -28,7 +28,7 @@ public class GraphViewHelper {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static GraphViewHelper newInstance(@NotNull FunctionViewDef functionViewDef,
|
public static GraphViewHelper newInstance(@NotNull FunctionViewDef functionViewDef,
|
||||||
@NotNull List<FunctionPlotDef> functionPlotDefs) {
|
@NotNull List<ArityPlotFunction> functionPlotDefs) {
|
||||||
final GraphViewHelper result = new GraphViewHelper();
|
final GraphViewHelper result = new GraphViewHelper();
|
||||||
|
|
||||||
result.functionViewDef = functionViewDef;
|
result.functionViewDef = functionViewDef;
|
||||||
@ -38,7 +38,7 @@ public class GraphViewHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public GraphViewHelper copy(@NotNull List<FunctionPlotDef> newFunctionPlotDefs) {
|
public GraphViewHelper copy(@NotNull List<ArityPlotFunction> newFunctionPlotDefs) {
|
||||||
final GraphViewHelper result = new GraphViewHelper();
|
final GraphViewHelper result = new GraphViewHelper();
|
||||||
|
|
||||||
result.functionViewDef = functionViewDef;
|
result.functionViewDef = functionViewDef;
|
||||||
@ -48,7 +48,7 @@ public class GraphViewHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<FunctionPlotDef> getFunctionPlotDefs() {
|
public List<ArityPlotFunction> getFunctionPlotDefs() {
|
||||||
return functionPlotDefs;
|
return functionPlotDefs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ class ZoomTracker {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float distance(float x1, float y1, float x2, float y2) {
|
private static float distance(float x1, float y1, float x2, float y2) {
|
||||||
final float dx = x1-x2;
|
final float dx = x1-x2;
|
||||||
final float dy = y1-y2;
|
final float dy = y1-y2;
|
||||||
// return (float) Math.sqrt(dx*dx+dy*dy);
|
// return (float) Math.sqrt(dx*dx+dy*dy);
|
||||||
|
@ -7,6 +7,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.solovyev.android.calculator.external.CalculatorExternalListenersContainer;
|
import org.solovyev.android.calculator.external.CalculatorExternalListenersContainer;
|
||||||
import org.solovyev.android.calculator.history.CalculatorHistory;
|
import org.solovyev.android.calculator.history.CalculatorHistory;
|
||||||
|
import org.solovyev.android.calculator.plot.CalculatorPlotter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
@ -16,7 +17,7 @@ import org.solovyev.android.calculator.history.CalculatorHistory;
|
|||||||
public class CalculatorTestUtils {
|
public class CalculatorTestUtils {
|
||||||
|
|
||||||
public static void staticSetUp(@Nullable Context context) throws Exception {
|
public static void staticSetUp(@Nullable Context context) throws Exception {
|
||||||
Locator.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(CalculatorKeyboard.class), Mockito.mock(CalculatorExternalListenersContainer.class));
|
Locator.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(CalculatorKeyboard.class), Mockito.mock(CalculatorExternalListenersContainer.class), Mockito.mock(CalculatorPlotter.class));
|
||||||
Locator.getInstance().getEngine().init();
|
Locator.getInstance().getEngine().init();
|
||||||
|
|
||||||
if ( context != null ) {
|
if ( context != null ) {
|
||||||
|
@ -159,11 +159,8 @@ public enum CalculatorEventType {
|
|||||||
show_create_matrix_dialog,
|
show_create_matrix_dialog,
|
||||||
show_create_function_dialog,
|
show_create_function_dialog,
|
||||||
|
|
||||||
//org.solovyev.android.calculator.plot.PlotInput
|
|
||||||
plot_graph,
|
plot_graph,
|
||||||
|
plot_data_changed,
|
||||||
|
|
||||||
plot_graph_3d,
|
|
||||||
|
|
||||||
//String
|
//String
|
||||||
show_evaluation_error;
|
show_evaluation_error;
|
||||||
|
@ -3,6 +3,7 @@ package org.solovyev.android.calculator;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.calculator.external.CalculatorExternalListenersContainer;
|
import org.solovyev.android.calculator.external.CalculatorExternalListenersContainer;
|
||||||
import org.solovyev.android.calculator.history.CalculatorHistory;
|
import org.solovyev.android.calculator.history.CalculatorHistory;
|
||||||
|
import org.solovyev.android.calculator.plot.CalculatorPlotter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: Solovyev_S
|
* User: Solovyev_S
|
||||||
@ -19,7 +20,8 @@ public interface CalculatorLocator {
|
|||||||
@NotNull CalculatorLogger logger,
|
@NotNull CalculatorLogger logger,
|
||||||
@NotNull CalculatorPreferenceService preferenceService,
|
@NotNull CalculatorPreferenceService preferenceService,
|
||||||
@NotNull CalculatorKeyboard keyboard,
|
@NotNull CalculatorKeyboard keyboard,
|
||||||
@NotNull CalculatorExternalListenersContainer externalListenersContainer);
|
@NotNull CalculatorExternalListenersContainer externalListenersContainer,
|
||||||
|
@NotNull CalculatorPlotter plotter);
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
Calculator getCalculator();
|
Calculator getCalculator();
|
||||||
@ -48,6 +50,9 @@ public interface CalculatorLocator {
|
|||||||
@NotNull
|
@NotNull
|
||||||
CalculatorLogger getLogger();
|
CalculatorLogger getLogger();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
CalculatorPlotter getPlotter();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
CalculatorPreferenceService getPreferenceService();
|
CalculatorPreferenceService getPreferenceService();
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import jscl.math.Generic;
|
|||||||
import jscl.math.function.Constant;
|
import jscl.math.function.Constant;
|
||||||
import jscl.math.function.IConstant;
|
import jscl.math.function.IConstant;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -41,16 +40,4 @@ public final class CalculatorUtils {
|
|||||||
return notSystemConstants;
|
return notSystemConstants;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isPlotPossible(@NotNull Generic expression, @NotNull JsclOperation operation) {
|
|
||||||
boolean result = false;
|
|
||||||
|
|
||||||
if (operation == JsclOperation.simplify || operation == JsclOperation.numeric) {
|
|
||||||
int size = getNotSystemConstants(expression).size();
|
|
||||||
if (size == 0 || size == 1 || size == 2) {
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package org.solovyev.android.calculator;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.calculator.external.CalculatorExternalListenersContainer;
|
import org.solovyev.android.calculator.external.CalculatorExternalListenersContainer;
|
||||||
import org.solovyev.android.calculator.history.CalculatorHistory;
|
import org.solovyev.android.calculator.history.CalculatorHistory;
|
||||||
|
import org.solovyev.android.calculator.plot.CalculatorPlotter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: Solovyev_S
|
* User: Solovyev_S
|
||||||
@ -47,7 +48,10 @@ public class Locator implements CalculatorLocator {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private CalculatorExternalListenersContainer calculatorExternalListenersContainer;
|
private CalculatorExternalListenersContainer calculatorExternalListenersContainer;
|
||||||
|
|
||||||
public Locator() {
|
@NotNull
|
||||||
|
private CalculatorPlotter calculatorPlotter;
|
||||||
|
|
||||||
|
public Locator() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -59,7 +63,8 @@ public class Locator implements CalculatorLocator {
|
|||||||
@NotNull CalculatorLogger logger,
|
@NotNull CalculatorLogger logger,
|
||||||
@NotNull CalculatorPreferenceService preferenceService,
|
@NotNull CalculatorPreferenceService preferenceService,
|
||||||
@NotNull CalculatorKeyboard keyboard,
|
@NotNull CalculatorKeyboard keyboard,
|
||||||
@NotNull CalculatorExternalListenersContainer externalListenersContainer) {
|
@NotNull CalculatorExternalListenersContainer externalListenersContainer,
|
||||||
|
@NotNull CalculatorPlotter plotter) {
|
||||||
|
|
||||||
this.calculator = calculator;
|
this.calculator = calculator;
|
||||||
this.calculatorEngine = engine;
|
this.calculatorEngine = engine;
|
||||||
@ -69,6 +74,7 @@ public class Locator implements CalculatorLocator {
|
|||||||
this.calculatorLogger = logger;
|
this.calculatorLogger = logger;
|
||||||
this.calculatorPreferenceService = preferenceService;
|
this.calculatorPreferenceService = preferenceService;
|
||||||
this.calculatorExternalListenersContainer = externalListenersContainer;
|
this.calculatorExternalListenersContainer = externalListenersContainer;
|
||||||
|
this.calculatorPlotter = plotter;
|
||||||
|
|
||||||
calculatorEditor = new CalculatorEditorImpl(this.calculator);
|
calculatorEditor = new CalculatorEditorImpl(this.calculator);
|
||||||
calculatorDisplay = new CalculatorDisplayImpl(this.calculator);
|
calculatorDisplay = new CalculatorDisplayImpl(this.calculator);
|
||||||
@ -134,6 +140,12 @@ public class Locator implements CalculatorLocator {
|
|||||||
return calculatorLogger;
|
return calculatorLogger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public CalculatorPlotter getPlotter() {
|
||||||
|
return calculatorPlotter;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public CalculatorPreferenceService getPreferenceService() {
|
public CalculatorPreferenceService getPreferenceService() {
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 1/12/13
|
||||||
|
* Time: 8:23 PM
|
||||||
|
*/
|
||||||
|
public interface CalculatorPlotter {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
PlotData getPlotData();
|
||||||
|
|
||||||
|
boolean addFunction(@NotNull Generic expression);
|
||||||
|
boolean addFunction(@NotNull PlotFunction plotFunction);
|
||||||
|
boolean addFunction(@NotNull XyFunction xyFunction);
|
||||||
|
boolean addFunction(@NotNull XyFunction xyFunction, @NotNull PlotFunctionLineDef functionLineDef);
|
||||||
|
|
||||||
|
boolean updateFunction(@NotNull PlotFunction newFunction);
|
||||||
|
boolean updateFunction(@NotNull XyFunction xyFunction, @NotNull PlotFunctionLineDef functionLineDef);
|
||||||
|
|
||||||
|
boolean removeFunction(@NotNull PlotFunction plotFunction);
|
||||||
|
boolean removeFunction(@NotNull XyFunction xyFunction);
|
||||||
|
|
||||||
|
void pin(@NotNull PlotFunction plotFunction);
|
||||||
|
void unpin(@NotNull PlotFunction plotFunction);
|
||||||
|
|
||||||
|
void show(@NotNull PlotFunction plotFunction);
|
||||||
|
void hide(@NotNull PlotFunction plotFunction);
|
||||||
|
|
||||||
|
void clearAllFunctions();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
List<PlotFunction> getFunctions();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
List<PlotFunction> getVisibleFunctions();
|
||||||
|
|
||||||
|
void plot();
|
||||||
|
|
||||||
|
boolean isPlotPossible(@NotNull Generic expression);
|
||||||
|
|
||||||
|
void setPlot3d(boolean plot3d);
|
||||||
|
|
||||||
|
void removeAllUnpinned();
|
||||||
|
|
||||||
|
void setPlotImag(boolean plotImag);
|
||||||
|
|
||||||
|
void setRealLineColor(@NotNull GraphLineColor realLineColor);
|
||||||
|
|
||||||
|
void setImagLineColor(@NotNull GraphLineColor imagLineColor);
|
||||||
|
}
|
@ -0,0 +1,294 @@
|
|||||||
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import jscl.math.function.Constant;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.android.calculator.Calculator;
|
||||||
|
import org.solovyev.android.calculator.CalculatorEventType;
|
||||||
|
import org.solovyev.android.calculator.CalculatorUtils;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 1/12/13
|
||||||
|
* Time: 8:42 PM
|
||||||
|
*/
|
||||||
|
public class CalculatorPlotterImpl implements CalculatorPlotter {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final List<PlotFunction> functions = new ArrayList<PlotFunction>();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Calculator calculator;
|
||||||
|
|
||||||
|
private boolean plot3d = false;
|
||||||
|
|
||||||
|
private boolean plotImag = false;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private GraphLineColor realLineColor;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private GraphLineColor imagLineColor;
|
||||||
|
|
||||||
|
public CalculatorPlotterImpl(@NotNull Calculator calculator) {
|
||||||
|
this.calculator = calculator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public PlotData getPlotData() {
|
||||||
|
return new PlotData(getVisibleFunctions(), plot3d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addFunction(@NotNull Generic expression) {
|
||||||
|
final List<Constant> variables = new ArrayList<Constant>(CalculatorUtils.getNotSystemConstants(expression));
|
||||||
|
|
||||||
|
assert variables.size() <= 2;
|
||||||
|
|
||||||
|
final Constant xVariable;
|
||||||
|
if (variables.size() > 0) {
|
||||||
|
xVariable = variables.get(0);
|
||||||
|
} else {
|
||||||
|
xVariable = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Constant yVariable;
|
||||||
|
if (variables.size() > 1) {
|
||||||
|
yVariable = variables.get(1);
|
||||||
|
} else {
|
||||||
|
yVariable = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean realAdded = addFunction(new XyFunction(expression, xVariable, yVariable, false));
|
||||||
|
|
||||||
|
final PlotFunction imagPlotFunction = new PlotFunction(new XyFunction(expression, xVariable, yVariable, true));
|
||||||
|
final boolean imagAdded = addFunction(plotImag ? imagPlotFunction : PlotFunction.invisible(imagPlotFunction));
|
||||||
|
|
||||||
|
return imagAdded || realAdded;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addFunction(@NotNull PlotFunction plotFunction) {
|
||||||
|
synchronized (functions) {
|
||||||
|
if (!functions.contains(plotFunction)) {
|
||||||
|
functions.add(plotFunction);
|
||||||
|
onFunctionsChanged();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAllUnpinned() {
|
||||||
|
synchronized (functions) {
|
||||||
|
boolean changed = Iterables.removeIf(functions, new Predicate<PlotFunction>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(@Nullable PlotFunction function) {
|
||||||
|
return function != null && !function.isPinned();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
onFunctionsChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeFunction(@NotNull PlotFunction plotFunction) {
|
||||||
|
synchronized (functions) {
|
||||||
|
boolean changed = functions.remove(plotFunction);
|
||||||
|
if (changed) {
|
||||||
|
onFunctionsChanged();
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addFunction(@NotNull XyFunction xyFunction) {
|
||||||
|
return addFunction(new PlotFunction(xyFunction));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addFunction(@NotNull XyFunction xyFunction, @NotNull PlotFunctionLineDef functionLineDef) {
|
||||||
|
return addFunction(new PlotFunction(xyFunction, functionLineDef));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateFunction(@NotNull XyFunction xyFunction, @NotNull PlotFunctionLineDef functionLineDef) {
|
||||||
|
final PlotFunction newFunction = new PlotFunction(xyFunction, functionLineDef);
|
||||||
|
|
||||||
|
return updateFunction(newFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateFunction(@NotNull PlotFunction newFunction) {
|
||||||
|
boolean changed = false;
|
||||||
|
|
||||||
|
synchronized (functions) {
|
||||||
|
for (int i = 0; i < functions.size(); i++) {
|
||||||
|
final PlotFunction plotFunction = functions.get(i);
|
||||||
|
if (plotFunction.equals(newFunction)) {
|
||||||
|
// update old function
|
||||||
|
functions.set(i, newFunction);
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeFunction(@NotNull XyFunction xyFunction) {
|
||||||
|
return removeFunction(new PlotFunction(xyFunction));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pin(@NotNull PlotFunction plotFunction) {
|
||||||
|
updateFunction(PlotFunction.pin(plotFunction));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unpin(@NotNull PlotFunction plotFunction) {
|
||||||
|
updateFunction(PlotFunction.unpin(plotFunction));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void show(@NotNull PlotFunction plotFunction) {
|
||||||
|
updateFunction(PlotFunction.visible(plotFunction));
|
||||||
|
firePlotDataChangedEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hide(@NotNull PlotFunction plotFunction) {
|
||||||
|
updateFunction(PlotFunction.invisible(plotFunction));
|
||||||
|
firePlotDataChangedEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearAllFunctions() {
|
||||||
|
synchronized (functions) {
|
||||||
|
functions.clear();
|
||||||
|
onFunctionsChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: this method must be called from synchronized block
|
||||||
|
private void onFunctionsChanged() {
|
||||||
|
assert Thread.holdsLock(functions);
|
||||||
|
|
||||||
|
int maxArity = 0;
|
||||||
|
for (PlotFunction function : functions) {
|
||||||
|
final XyFunction xyFunction = function.getXyFunction();
|
||||||
|
|
||||||
|
maxArity = Math.max(maxArity, xyFunction.getArity());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxArity > 1) {
|
||||||
|
plot3d = true;
|
||||||
|
} else {
|
||||||
|
plot3d = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
firePlotDataChangedEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<PlotFunction> getFunctions() {
|
||||||
|
synchronized (functions) {
|
||||||
|
return new ArrayList<PlotFunction>(functions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<PlotFunction> getVisibleFunctions() {
|
||||||
|
synchronized (functions) {
|
||||||
|
return Lists.newArrayList(Iterables.filter(functions, new Predicate<PlotFunction>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(@Nullable PlotFunction function) {
|
||||||
|
return function != null && function.isVisible();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void plot() {
|
||||||
|
calculator.fireCalculatorEvent(CalculatorEventType.plot_graph, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPlotPossible(@NotNull Generic expression) {
|
||||||
|
boolean result = false;
|
||||||
|
|
||||||
|
int size = CalculatorUtils.getNotSystemConstants(expression).size();
|
||||||
|
if (size == 0 || size == 1 || size == 2) {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPlot3d(boolean plot3d) {
|
||||||
|
if (this.plot3d != plot3d) {
|
||||||
|
this.plot3d = plot3d;
|
||||||
|
firePlotDataChangedEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void firePlotDataChangedEvent() {
|
||||||
|
calculator.fireCalculatorEvent(CalculatorEventType.plot_data_changed, getPlotData());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPlotImag(boolean plotImag) {
|
||||||
|
if (this.plotImag != plotImag) {
|
||||||
|
this.plotImag = plotImag;
|
||||||
|
if (toggleImagFunctions(this.plotImag)) {
|
||||||
|
firePlotDataChangedEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRealLineColor(@NotNull GraphLineColor realLineColor) {
|
||||||
|
this.realLineColor = realLineColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setImagLineColor(@NotNull GraphLineColor imagLineColor) {
|
||||||
|
this.imagLineColor = imagLineColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean toggleImagFunctions(boolean show) {
|
||||||
|
boolean changed = false;
|
||||||
|
|
||||||
|
synchronized (functions) {
|
||||||
|
for (int i = 0; i < functions.size(); i++) {
|
||||||
|
final PlotFunction plotFunction = functions.get(i);
|
||||||
|
if (plotFunction.getXyFunction().isImag()) {
|
||||||
|
functions.set(i, show ? PlotFunction.visible(plotFunction) : PlotFunction.invisible(plotFunction));
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,5 @@
|
|||||||
package org.solovyev.android.calculator.plot;
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
import android.graphics.Color;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 10/4/12
|
* Date: 10/4/12
|
||||||
@ -9,11 +7,19 @@ import android.graphics.Color;
|
|||||||
*/
|
*/
|
||||||
public enum GraphLineColor {
|
public enum GraphLineColor {
|
||||||
|
|
||||||
white(Color.WHITE),
|
// Color.WHITE
|
||||||
grey(Color.GRAY),
|
white(0xFFFFFFFF),
|
||||||
red(Color.RED),
|
|
||||||
blue(Color.rgb(16, 100, 140)),
|
// Color.GRAY
|
||||||
green(Color.GREEN);
|
grey(0xFF888888),
|
||||||
|
|
||||||
|
// Color.RED
|
||||||
|
red(0xFFFF0000),
|
||||||
|
|
||||||
|
blue(0xFF10648C),
|
||||||
|
|
||||||
|
// Color.GREEN
|
||||||
|
green(0xFF00FF00);
|
||||||
|
|
||||||
private final int color;
|
private final int color;
|
||||||
|
|
@ -0,0 +1,28 @@
|
|||||||
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 1/12/13
|
||||||
|
* Time: 10:01 PM
|
||||||
|
*/
|
||||||
|
public class PlotData {
|
||||||
|
|
||||||
|
private List<PlotFunction> functions;
|
||||||
|
|
||||||
|
private boolean plot3d;
|
||||||
|
|
||||||
|
public PlotData(List<PlotFunction> functions, boolean plot3d) {
|
||||||
|
this.functions = functions;
|
||||||
|
this.plot3d = plot3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PlotFunction> getFunctions() {
|
||||||
|
return functions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPlot3d() {
|
||||||
|
return plot3d;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 1/12/13
|
||||||
|
* Time: 8:45 PM
|
||||||
|
*/
|
||||||
|
public class PlotFunction {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private XyFunction xyFunction;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private PlotFunctionLineDef plotFunctionLineDef;
|
||||||
|
|
||||||
|
private boolean pinned = false;
|
||||||
|
|
||||||
|
private boolean visible = true;
|
||||||
|
|
||||||
|
public PlotFunction(@NotNull XyFunction xyFunction) {
|
||||||
|
this.xyFunction = xyFunction;
|
||||||
|
this.plotFunctionLineDef = PlotFunctionLineDef.newDefaultInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlotFunction(@NotNull XyFunction xyFunction,
|
||||||
|
@NotNull PlotFunctionLineDef plotFunctionLineDef) {
|
||||||
|
this.xyFunction = xyFunction;
|
||||||
|
this.plotFunctionLineDef = plotFunctionLineDef;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private PlotFunction copy() {
|
||||||
|
final PlotFunction copy = new PlotFunction(this.xyFunction);
|
||||||
|
|
||||||
|
copy.plotFunctionLineDef = this.plotFunctionLineDef;
|
||||||
|
copy.pinned = this.pinned;
|
||||||
|
copy.visible = this.visible;
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PlotFunction pin(@NotNull PlotFunction that) {
|
||||||
|
final PlotFunction copy = that.copy();
|
||||||
|
copy.pinned = true;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PlotFunction unpin(@NotNull PlotFunction that) {
|
||||||
|
final PlotFunction copy = that.copy();
|
||||||
|
copy.pinned = false;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PlotFunction visible(@NotNull PlotFunction that) {
|
||||||
|
final PlotFunction copy = that.copy();
|
||||||
|
copy.visible = true;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PlotFunction invisible(@NotNull PlotFunction that) {
|
||||||
|
final PlotFunction copy = that.copy();
|
||||||
|
copy.visible = false;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public XyFunction getXyFunction() {
|
||||||
|
return xyFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public PlotFunctionLineDef getPlotFunctionLineDef() {
|
||||||
|
return plotFunctionLineDef;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPinned() {
|
||||||
|
return pinned;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof PlotFunction)) return false;
|
||||||
|
|
||||||
|
PlotFunction that = (PlotFunction) o;
|
||||||
|
|
||||||
|
if (!xyFunction.equals(that.xyFunction)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return xyFunction.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isVisible() {
|
||||||
|
return visible;
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,7 @@ package org.solovyev.android.calculator.plot;
|
|||||||
* Date: 1/5/13
|
* Date: 1/5/13
|
||||||
* Time: 10:45 PM
|
* Time: 10:45 PM
|
||||||
*/
|
*/
|
||||||
public enum FunctionLineColorType {
|
public enum PlotFunctionLineColorType {
|
||||||
|
|
||||||
color_map,
|
color_map,
|
||||||
solid;
|
solid;
|
@ -0,0 +1,96 @@
|
|||||||
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 1/5/13
|
||||||
|
* Time: 7:41 PM
|
||||||
|
*/
|
||||||
|
public class PlotFunctionLineDef {
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* CONSTANTS
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static final Float DEFAULT_LINE_WIDTH = -1f;
|
||||||
|
|
||||||
|
private static final int WHITE = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* FIELDS
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private PlotFunctionLineColorType lineColorType = PlotFunctionLineColorType.solid;
|
||||||
|
|
||||||
|
private int lineColor = WHITE;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private PlotLineStyle lineStyle = PlotLineStyle.solid;
|
||||||
|
|
||||||
|
private float lineWidth = -DEFAULT_LINE_WIDTH;
|
||||||
|
|
||||||
|
private PlotFunctionLineDef() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static PlotFunctionLineDef newInstance(int lineColor, @NotNull PlotLineStyle lineStyle) {
|
||||||
|
final PlotFunctionLineDef result = new PlotFunctionLineDef();
|
||||||
|
result.lineColor = lineColor;
|
||||||
|
result.lineStyle = lineStyle;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static PlotFunctionLineDef newInstance(int lineColor, @NotNull PlotLineStyle lineStyle, float lineWidth) {
|
||||||
|
final PlotFunctionLineDef result = new PlotFunctionLineDef();
|
||||||
|
result.lineColor = lineColor;
|
||||||
|
result.lineStyle = lineStyle;
|
||||||
|
result.lineWidth = lineWidth;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static PlotFunctionLineDef newInstance(int lineColor, @NotNull PlotLineStyle lineStyle, float lineWidth, @NotNull PlotFunctionLineColorType lineColorType) {
|
||||||
|
final PlotFunctionLineDef result = new PlotFunctionLineDef();
|
||||||
|
result.lineColor = lineColor;
|
||||||
|
result.lineColorType = lineColorType;
|
||||||
|
result.lineStyle = lineStyle;
|
||||||
|
result.lineWidth = lineWidth;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static PlotFunctionLineDef newDefaultInstance() {
|
||||||
|
return new PlotFunctionLineDef();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLineColor() {
|
||||||
|
return lineColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public PlotLineStyle getLineStyle() {
|
||||||
|
return lineStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getLineWidth() {
|
||||||
|
return lineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public PlotFunctionLineColorType getLineColorType() {
|
||||||
|
return lineColorType;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 1/5/13
|
||||||
|
* Time: 7:37 PM
|
||||||
|
*/
|
||||||
|
public enum PlotLineStyle {
|
||||||
|
|
||||||
|
solid,
|
||||||
|
dashed,
|
||||||
|
dotted,
|
||||||
|
dash_dotted;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,128 @@
|
|||||||
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import jscl.math.function.Constant;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class XyFunction {
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* FIELDS
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Generic expression;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String expressionString;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final Constant xVariable;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String xVariableName;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final Constant yVariable;
|
||||||
|
|
||||||
|
private final boolean imag;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String yVariableName;
|
||||||
|
|
||||||
|
private int arity;
|
||||||
|
|
||||||
|
public XyFunction(@NotNull Generic expression,
|
||||||
|
@Nullable Constant xVariable,
|
||||||
|
@Nullable Constant yVariable,
|
||||||
|
boolean imag) {
|
||||||
|
this.expression = expression;
|
||||||
|
this.xVariable = xVariable;
|
||||||
|
this.yVariable = yVariable;
|
||||||
|
this.imag = imag;
|
||||||
|
|
||||||
|
if (imag) {
|
||||||
|
this.expressionString = "Im(" + expression.toString() + ")";
|
||||||
|
} else {
|
||||||
|
this.expressionString = expression.toString();
|
||||||
|
}
|
||||||
|
this.xVariableName = xVariable == null ? null : xVariable.getName();
|
||||||
|
this.yVariableName = yVariable == null ? null : yVariable.getName();
|
||||||
|
|
||||||
|
this.arity = 2;
|
||||||
|
if ( this.yVariableName == null ) {
|
||||||
|
this.arity--;
|
||||||
|
}
|
||||||
|
if ( this.xVariableName == null ) {
|
||||||
|
this.arity--;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isImag() {
|
||||||
|
return imag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getArity() {
|
||||||
|
return arity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Generic getExpression() {
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Constant getXVariable() {
|
||||||
|
return xVariable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Constant getYVariable() {
|
||||||
|
return yVariable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public String getExpressionString() {
|
||||||
|
return expressionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getXVariableName() {
|
||||||
|
return xVariableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getYVariableName() {
|
||||||
|
return yVariableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof XyFunction)) return false;
|
||||||
|
|
||||||
|
final XyFunction that = (XyFunction) o;
|
||||||
|
|
||||||
|
if (!expressionString.equals(that.expressionString)) return false;
|
||||||
|
if (xVariableName != null ? !xVariableName.equals(that.xVariableName) : that.xVariableName != null)
|
||||||
|
return false;
|
||||||
|
if (yVariableName != null ? !yVariableName.equals(that.yVariableName) : that.yVariableName != null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = expressionString.hashCode();
|
||||||
|
result = 31 * result + (xVariableName != null ? xVariableName.hashCode() : 0);
|
||||||
|
result = 31 * result + (yVariableName != null ? yVariableName.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ package org.solovyev.android.calculator;
|
|||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.solovyev.android.calculator.external.CalculatorExternalListenersContainer;
|
import org.solovyev.android.calculator.external.CalculatorExternalListenersContainer;
|
||||||
import org.solovyev.android.calculator.history.CalculatorHistory;
|
import org.solovyev.android.calculator.history.CalculatorHistory;
|
||||||
|
import org.solovyev.android.calculator.plot.CalculatorPlotter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
@ -12,7 +13,7 @@ import org.solovyev.android.calculator.history.CalculatorHistory;
|
|||||||
public class AbstractCalculatorTest {
|
public class AbstractCalculatorTest {
|
||||||
|
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
Locator.getInstance().init(new CalculatorImpl(), CalculatorTestUtils.newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(CalculatorKeyboard.class), Mockito.mock(CalculatorExternalListenersContainer.class));
|
Locator.getInstance().init(new CalculatorImpl(), CalculatorTestUtils.newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(CalculatorKeyboard.class), Mockito.mock(CalculatorExternalListenersContainer.class), Mockito.mock(CalculatorPlotter.class));
|
||||||
Locator.getInstance().getEngine().init();
|
Locator.getInstance().getEngine().init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import org.mockito.Mockito;
|
|||||||
import org.solovyev.android.calculator.external.CalculatorExternalListenersContainer;
|
import org.solovyev.android.calculator.external.CalculatorExternalListenersContainer;
|
||||||
import org.solovyev.android.calculator.history.CalculatorHistory;
|
import org.solovyev.android.calculator.history.CalculatorHistory;
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
import org.solovyev.android.calculator.plot.CalculatorPlotter;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
@ -24,7 +25,7 @@ public class CalculatorTestUtils {
|
|||||||
public static final int TIMEOUT = 3;
|
public static final int TIMEOUT = 3;
|
||||||
|
|
||||||
public static void staticSetUp() throws Exception {
|
public static void staticSetUp() throws Exception {
|
||||||
Locator.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(CalculatorKeyboard.class), Mockito.mock(CalculatorExternalListenersContainer.class));
|
Locator.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(CalculatorKeyboard.class), Mockito.mock(CalculatorExternalListenersContainer.class), Mockito.mock(CalculatorPlotter.class));
|
||||||
Locator.getInstance().getEngine().init();
|
Locator.getInstance().getEngine().init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user