new plotter

This commit is contained in:
Sergey Solovyev
2013-01-16 17:47:56 +04:00
parent 93c5e2a093
commit c3f1e3200f
14 changed files with 188 additions and 80 deletions

View File

@@ -33,10 +33,8 @@ public enum CalculatorFragmentType {
functions(CalculatorFunctionsFragment.class, R.layout.math_entities_fragment, R.string.c_functions),
operators(CalculatorOperatorsFragment.class, R.layout.math_entities_fragment, R.string.c_operators),
plotter(CalculatorPlotFragment.class, R.layout.cpp_plot_fragment, R.string.c_graph),
// todo serso: strings
plotter_functions(CalculatorPlotFunctionsActivity.CalculatorPlotFunctionsFragment.class, R.layout.cpp_plot_functions_fragment, R.string.c_graph),
plotter_function_settings(CalculatorPlotFunctionSettingsActivity.CalculatorPlotFunctionSettingsFragment.class, R.layout.cpp_plot_function_settings_fragment, R.string.c_graph),
plotter_functions(CalculatorPlotFunctionsActivity.CalculatorPlotFunctionsFragment.class, R.layout.cpp_plot_functions_fragment, R.string.cpp_plot_functions),
plotter_function_settings(CalculatorPlotFunctionSettingsActivity.CalculatorPlotFunctionSettingsFragment.class, R.layout.cpp_plot_function_settings_fragment, R.string.cpp_plot_function_settings),
about(CalculatorAboutFragment.class, R.layout.about_fragment, R.string.c_about),
faq(CalculatorHelpFaqFragment.class, R.layout.help_faq_fragment, R.string.c_faq),

View File

@@ -453,11 +453,7 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
paint.setColor(plotLineDef.getLineColor());
paint.setStyle(Paint.Style.STROKE);
if ( plotLineDef.getLineWidth() == PlotLineDef.DEFAULT_LINE_WIDTH ) {
paint.setStrokeWidth(0);
} else {
paint.setStrokeWidth(plotLineDef.getLineWidth());
}
paint.setStrokeWidth(plotLineDef.getLineWidth());
final AndroidPlotLineStyle androidPlotLineStyle = AndroidPlotLineStyle.valueOf(plotLineDef.getLineStyle());
if (androidPlotLineStyle != null) {

View File

@@ -12,6 +12,7 @@ import android.widget.Scroller;
import android.widget.ZoomButtonsController;
import org.javia.arity.Function;
import org.jetbrains.annotations.NotNull;
import org.solovyev.common.math.Point2d;
import java.text.DecimalFormat;
import java.util.ArrayList;
@@ -27,6 +28,7 @@ public class CalculatorGraph2dView extends View implements GraphView {
*
**********************************************************************
*/
private static final int NO_TOUCH = -1;
private static final float TICKS_COUNT = 15;
public static final int TICK_SIZE_PXS = 3;
@@ -51,7 +53,7 @@ public class CalculatorGraph2dView extends View implements GraphView {
private int widthPxs;
private int heightPxs;
@NotNull
@NotNull
private final Matrix matrix = new Matrix();
// paints
@@ -80,15 +82,15 @@ public class CalculatorGraph2dView extends View implements GraphView {
private float y0;
// graph width in function units (NOT screen pixels)
private float graphWidth = 20;
private float gWidth = 20;
private float lastXMin;
private float lastYMin;
private float lastYMax;
private float lastTouchX, lastTouchY;
private float lastTouchXPxs = NO_TOUCH;
private float lastTouchYPxs = NO_TOUCH;
@NotNull
private TouchHandler touchHandler;
@@ -134,8 +136,8 @@ public class CalculatorGraph2dView extends View implements GraphView {
@Override
public void setXRange(float xMin, float xMax) {
this.graphWidth = xMax - xMin;
this.x0 = xMin + graphWidth / 2;
this.gWidth = xMax - xMin;
this.x0 = xMin + gWidth / 2;
this.y0 = 0;
}
@@ -418,6 +420,9 @@ public class CalculatorGraph2dView extends View implements GraphView {
}
final float tickStep = getStep(gWidth);
final int tickDigits = countTickDigits(tickStep);
{
// GRID
@@ -428,17 +433,14 @@ public class CalculatorGraph2dView extends View implements GraphView {
textPaint.setTextSize(12);
textPaint.setTextAlign(Paint.Align.CENTER);
final float step = getStep(graphWidth);
final int tickDigits = countTickDigits(step);
// round xMin and init first tick
float tick = ((int) (xMin / step)) * step;
float tick = ((int) (xMin / tickStep)) * tickStep;
final float y2 = y0px + TICK_SIZE_PXS;
final float stepPxs = step / ratio;
final float stepPxs = tickStep / ratio;
for (float xPxs = (tick - xMin) / ratio; xPxs <= widthPxs; xPxs += stepPxs, tick += step) {
for (float xPxs = (tick - xMin) / ratio; xPxs <= widthPxs; xPxs += stepPxs, tick += tickStep) {
// draw grid line
canvas.drawLine(xPxs, 0, xPxs, heightPxs, paint);
@@ -449,9 +451,9 @@ public class CalculatorGraph2dView extends View implements GraphView {
}
final float x1 = x0px - TICK_SIZE_PXS;
tick = ((int) (yMin / step)) * step;
tick = ((int) (yMin / tickStep)) * tickStep;
textPaint.setTextAlign(Paint.Align.RIGHT);
for (float y = heightPxs - (tick - yMin) / ratio; y >= 0; y -= stepPxs, tick += step) {
for (float y = heightPxs - (tick - yMin) / ratio; y >= 0; y -= stepPxs, tick += tickStep) {
canvas.drawLine(0, y, widthPxs, y, paint);
final CharSequence tickLabel = formatTick(tick, tickDigits);
@@ -471,6 +473,26 @@ public class CalculatorGraph2dView extends View implements GraphView {
canvas.drawLine(0, y0px, widthPxs, y0px, paint);
}
{
// TOUCH POSITION
if (lastTouchXPxs != NO_TOUCH && lastTouchYPxs != NO_TOUCH) {
paint.setColor(graphViewHelper.getFunctionViewDef().getGridColor());
paint.setAlpha(100);
canvas.drawLine(lastTouchXPxs, 0, lastTouchXPxs, heightPxs, paint);
canvas.drawLine(0, lastTouchYPxs, widthPxs, lastTouchYPxs, paint);
final Point2d lastTouch = toGraphCoordinates(lastTouchXPxs, lastTouchYPxs);
final String touchLabel = "[" + formatTick(lastTouch.getX(), tickDigits + 1) + ", " + formatTick(lastTouch.getY(), tickDigits + 1) + "]";
canvas.drawText(touchLabel, 0, touchLabel.length(), lastTouchXPxs - 40, lastTouchYPxs - 40, textPaint);
// restore alpha
paint.setAlpha(255);
}
}
matrix.reset();
matrix.preTranslate(-this.x0, -this.y0);
@@ -550,14 +572,18 @@ public class CalculatorGraph2dView extends View implements GraphView {
**********************************************************************
*/
private Point2d toGraphCoordinates(float xPxs, float yPxs) {
return new Point2d(xPxs * getRatio() + getXMin(), - (yPxs * getRatio() + getYMin()));
}
// X
public float getXMin() {
return x0 - graphWidth / 2;
return x0 - gWidth / 2;
}
private float getXMax(float minX) {
return minX + graphWidth;
return minX + gWidth;
}
public float getXMax() {
@@ -587,20 +613,20 @@ public class CalculatorGraph2dView extends View implements GraphView {
}
private float getGraphHeight() {
return graphWidth * getAspectRatio();
return gWidth * getAspectRatio();
}
private float getRatio() {
if (widthPxs != 0) {
return graphWidth / widthPxs;
return gWidth / widthPxs;
} else {
return 0;
}
}
private int getAspectRatio() {
private float getAspectRatio() {
if (widthPxs != 0) {
return heightPxs / widthPxs;
return ((float)heightPxs) / widthPxs;
} else {
return 0;
}
@@ -628,12 +654,12 @@ public class CalculatorGraph2dView extends View implements GraphView {
public void onZoom(boolean zoomIn) {
if (zoomIn) {
if (canZoomIn()) {
graphWidth /= 2;
gWidth /= 2;
invalidateGraphs();
}
} else {
if (canZoomOut()) {
graphWidth *= 2;
gWidth *= 2;
invalidateGraphs();
}
}
@@ -663,17 +689,19 @@ public class CalculatorGraph2dView extends View implements GraphView {
if (!scroller.isFinished()) {
scroller.abortAnimation();
}
lastTouchX = x;
lastTouchY = y;
lastTouchXPxs = x;
lastTouchYPxs = y;
}
public void onTouchMove(float x, float y) {
float deltaX = x - lastTouchX;
float deltaY = y - lastTouchY;
float deltaX = x - lastTouchXPxs;
float deltaY = y - lastTouchYPxs;
if (deltaX < -1 || deltaX > 1 || deltaY < -1 || deltaY > 1) {
scroll(-deltaX, deltaY);
lastTouchX = x;
lastTouchY = y;
lastTouchXPxs = x;
lastTouchYPxs = y;
invalidate();
}
}
@@ -681,6 +709,9 @@ public class CalculatorGraph2dView extends View implements GraphView {
public void onTouchUp(float x, float y) {
final float ratio = getRatio();
lastTouchXPxs = NO_TOUCH;
lastTouchYPxs = NO_TOUCH;
float sx = -touchHandler.getXVelocity();
float sy = touchHandler.getYVelocity();
@@ -696,7 +727,7 @@ public class CalculatorGraph2dView extends View implements GraphView {
}
public void onTouchZoomDown(float x1, float y1, float x2, float y2) {
zoomTracker.start(graphWidth, x1, y1, x2, y2);
zoomTracker.start(gWidth, x1, y1, x2, y2);
}
public void onTouchZoomMove(float x1, float y1, float x2, float y2) {
@@ -705,7 +736,7 @@ public class CalculatorGraph2dView extends View implements GraphView {
}
float targetGwidth = zoomTracker.value;
if (targetGwidth > .25f && targetGwidth < 200) {
graphWidth = targetGwidth;
gWidth = targetGwidth;
}
// scroll(-zoomTracker.moveX, zoomTracker.moveY);
invalidateGraphs();
@@ -719,7 +750,7 @@ public class CalculatorGraph2dView extends View implements GraphView {
}
private void scroll(float deltaX, float deltaY) {
final float scale = graphWidth / widthPxs;
final float scale = gWidth / widthPxs;
float dx = deltaX * scale;
float dy = deltaY * scale;
final float adx = Math.abs(dx);

View File

@@ -4,11 +4,14 @@ import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.Spinner;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import org.jetbrains.annotations.NotNull;
@@ -27,7 +30,6 @@ public class CalculatorPlotFunctionSettingsActivity extends SherlockFragmentActi
final Intent intent = new Intent(context, CalculatorPlotFunctionSettingsActivity.class);
intent.putExtra(INPUT_FUNCTION_ID, plotFunction.getXyFunction().getId());
context.startActivity(intent);
}
@Override
@@ -55,9 +57,42 @@ public class CalculatorPlotFunctionSettingsActivity extends SherlockFragmentActi
public static class CalculatorPlotFunctionSettingsFragment extends CalculatorFragment {
/*
**********************************************************************
*
* STATIC
*
**********************************************************************
*/
public static final int LINE_WIDTH_DELAY = 1000;
public static final int MESSAGE_ID = 1;
@Nullable
private PlotFunction plotFunction;
@NotNull
private final CalculatorPlotter plotter = Locator.getInstance().getPlotter();
@NotNull
private final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (plotFunction != null) {
switch (msg.what) {
case MESSAGE_ID:
final PlotLineDef newPlotLineDef = PlotLineDef.changeLineWidth(plotFunction.getPlotLineDef(), msg.arg1);
final PlotFunction newPlotFunction = PlotFunction.changePlotLineDef(plotFunction, newPlotLineDef);
if(plotter.updateFunction(newPlotFunction)) {
plotFunction = newPlotFunction;
}
break;
}
}
}
};
public CalculatorPlotFunctionSettingsFragment() {
super(CalculatorFragmentType.plotter_function_settings);
}
@@ -69,6 +104,9 @@ public class CalculatorPlotFunctionSettingsActivity extends SherlockFragmentActi
final String functionId = getArguments().getString(INPUT_FUNCTION_ID);
if (functionId != null) {
plotFunction = Locator.getInstance().getPlotter().getFunctionById(functionId);
if ( plotFunction != null ) {
getActivity().setTitle(plotFunction.getXyFunction().getExpressionString());
}
}
}
@@ -81,14 +119,16 @@ public class CalculatorPlotFunctionSettingsActivity extends SherlockFragmentActi
public void onViewCreated(View root, Bundle savedInstanceState) {
super.onViewCreated(root, savedInstanceState);
final CalculatorPlotter plotter = Locator.getInstance().getPlotter();
final Spinner plotLineColorSpinner = (Spinner)root.findViewById(R.id.cpp_plot_function_line_color_spinner);
final Spinner plotLineColorTypeSpinner = (Spinner)root.findViewById(R.id.cpp_plot_function_line_color_type_spinner);
final Spinner plotLineStyleSpinner = (Spinner)root.findViewById(R.id.cpp_plot_function_line_style_spinner);
final SeekBar plotLineWidthSeekBar = (SeekBar)root.findViewById(R.id.cpp_plot_functions_line_width_seekbar);
final Button okButton = (Button)root.findViewById(R.id.cpp_ok_button);
plotLineWidthSeekBar.setMax(10);
if (plotFunction != null) {
plotLineWidthSeekBar.setProgress((int)plotFunction.getPlotLineDef().getLineWidth());
plotLineColorSpinner.setSelection(PlotLineColor.valueOf(plotFunction.getPlotLineDef().getLineColor()).ordinal());
plotLineColorSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@@ -150,6 +190,25 @@ public class CalculatorPlotFunctionSettingsActivity extends SherlockFragmentActi
}
});
plotLineWidthSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// remove old messages
handler.removeMessages(MESSAGE_ID);
// send new message
handler.sendMessageDelayed(Message.obtain(handler, MESSAGE_ID, progress, 0), LINE_WIDTH_DELAY);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
okButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -161,6 +220,7 @@ public class CalculatorPlotFunctionSettingsActivity extends SherlockFragmentActi
});
} else {
plotLineWidthSeekBar.setEnabled(false);
plotLineColorSpinner.setEnabled(false);
plotLineColorTypeSpinner.setEnabled(false);
plotLineStyleSpinner.setEnabled(false);