From e321155585f10e0faecd552198257c30bd16f5bd Mon Sep 17 00:00:00 2001 From: Sergey Solovyev Date: Sat, 19 Jan 2013 18:12:44 +0400 Subject: [PATCH] new plotter --- .../solovyev/android/calculator/Threads.java | 31 ++++ .../plot/AndroidCalculatorPlotter.java | 7 +- .../res/layout/cpp_drag_button_equals.xml | 2 +- .../plot/AbstractCalculatorPlotFragment.java | 154 +++--------------- .../plot/CalculatorPlotFragment.java | 9 +- .../calculator/CalculatorEventType.java | 2 + .../calculator/plot/CalculatorPlotter.java | 2 + .../plot/CalculatorPlotterImpl.java | 18 +- .../calculator/plot/PlotBoundaries.java | 103 ++++++++++++ .../android/calculator/plot/PlotData.java | 13 +- 10 files changed, 204 insertions(+), 137 deletions(-) create mode 100644 android-app-core/src/main/java/org/solovyev/android/calculator/Threads.java create mode 100644 core/src/main/java/org/solovyev/android/calculator/plot/PlotBoundaries.java diff --git a/android-app-core/src/main/java/org/solovyev/android/calculator/Threads.java b/android-app-core/src/main/java/org/solovyev/android/calculator/Threads.java new file mode 100644 index 00000000..7a547641 --- /dev/null +++ b/android-app-core/src/main/java/org/solovyev/android/calculator/Threads.java @@ -0,0 +1,31 @@ +package org.solovyev.android.calculator; + +import android.app.Activity; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * User: serso + * Date: 1/19/13 + * Time: 5:04 PM + */ +public final class Threads { + + private Threads() { + throw new AssertionError(); + } + + public static void tryRunOnUiThread(@Nullable final Activity activity, @NotNull final Runnable runnable) { + if (activity != null && !activity.isFinishing()) { + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + // some time may pass and activity might be closing + if (!activity.isFinishing()) { + runnable.run(); + } + } + }); + } + } +} diff --git a/android-app-core/src/main/java/org/solovyev/android/calculator/plot/AndroidCalculatorPlotter.java b/android-app-core/src/main/java/org/solovyev/android/calculator/plot/AndroidCalculatorPlotter.java index 18203b21..69ee93a5 100644 --- a/android-app-core/src/main/java/org/solovyev/android/calculator/plot/AndroidCalculatorPlotter.java +++ b/android-app-core/src/main/java/org/solovyev/android/calculator/plot/AndroidCalculatorPlotter.java @@ -6,7 +6,7 @@ import android.preference.PreferenceManager; import jscl.math.Generic; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.CalculatorPreferences; +import org.solovyev.android.calculator.*; import java.util.List; @@ -158,6 +158,11 @@ public class AndroidCalculatorPlotter implements CalculatorPlotter, SharedPrefer plotter.setPlotImag(plotImag); } + @Override + public void setPlotBoundaries(@NotNull PlotBoundaries plotBoundaries) { + plotter.setPlotBoundaries(plotBoundaries); + } + @Override public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { if (CalculatorPreferences.Graph.plotImag.getKey().equals(key)) { diff --git a/android-app/res/layout/cpp_drag_button_equals.xml b/android-app/res/layout/cpp_drag_button_equals.xml index 80aa5baf..49e6ee34 100644 --- a/android-app/res/layout/cpp_drag_button_equals.xml +++ b/android-app/res/layout/cpp_drag_button_equals.xml @@ -12,7 +12,7 @@ c:textUp="≡" a:text="=" c:textDown="@string/cpp_plot_button_text" - c:directionTextScale="0.5" + c:directionTextScale="0.5;0.5;0.33;0.5" a:layout_width="fill_parent" a:layout_height="fill_parent" style="?cpp_control_button_style" diff --git a/android-app/src/main/java/org/solovyev/android/calculator/plot/AbstractCalculatorPlotFragment.java b/android-app/src/main/java/org/solovyev/android/calculator/plot/AbstractCalculatorPlotFragment.java index dbf90e6a..2924bea2 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/plot/AbstractCalculatorPlotFragment.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/plot/AbstractCalculatorPlotFragment.java @@ -6,24 +6,16 @@ import android.graphics.Bitmap; import android.graphics.Paint; import android.os.Bundle; import android.os.Environment; -import android.os.Handler; import android.support.v4.app.FragmentActivity; import android.view.View; +import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.solovyev.android.AndroidUtils2; -import org.solovyev.android.calculator.CalculatorApplication; -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.CalculatorUtils; -import org.solovyev.android.calculator.Locator; -import org.solovyev.android.calculator.R; +import org.solovyev.android.calculator.*; import org.solovyev.android.menu.AMenuItem; import org.solovyev.android.menu.ActivityMenu; import org.solovyev.android.menu.IdentifiableMenuItem; @@ -33,7 +25,6 @@ import org.solovyev.common.JPredicate; import org.solovyev.common.msg.MessageType; import java.io.File; -import java.io.Serializable; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; @@ -59,12 +50,6 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment protected static final String TAG = "CalculatorPlotFragment"; - protected static final String PLOT_BOUNDARIES = "plot_boundaries"; - - private static final int DEFAULT_MIN_NUMBER = -10; - - private static final int DEFAULT_MAX_NUMBER = 10; - /* ********************************************************************** * @@ -75,16 +60,8 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment private int bgColor; - // thread for applying UI changes @NotNull - private final Handler uiHandler = new Handler(); - - @NotNull - private PlotData plotData = new PlotData(Collections.emptyList(), false); - - @NotNull - private PlotBoundaries initialPlotBoundaries; - + private PlotData plotData = new PlotData(Collections.emptyList(), false, PlotBoundaries.newDefaultInstance()); @NotNull private ActivityMenu fragmentMenu; @@ -103,7 +80,7 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment @Override - public void onCreate(Bundle in) { + public void onCreate(@Nullable Bundle in) { super.onCreate(in); if (isPaneFragment()) { @@ -112,42 +89,33 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment this.bgColor = getResources().getColor(android.R.color.transparent); } - final PlotBoundaries savedPlotBoundaries; - if (in != null) { - savedPlotBoundaries = (PlotBoundaries) in.getSerializable(PLOT_BOUNDARIES); - } else { - savedPlotBoundaries = null; - } - - if (savedPlotBoundaries != null) { - initialPlotBoundaries = savedPlotBoundaries; - } else { - initialPlotBoundaries = PlotBoundaries.newDefaultInstance(); - } - setHasOptionsMenu(true); } - @Override - public void onSaveInstanceState(Bundle out) { - super.onSaveInstanceState(out); - - final PlotBoundaries plotBoundaries = getPlotBoundaries(); - if (plotBoundaries != null) { - out.putSerializable(PLOT_BOUNDARIES, plotBoundaries); - } + private void saveBoundaries(@NotNull PlotBoundaries boundaries) { + Locator.getInstance().getPlotter().setPlotBoundaries(boundaries); } @Nullable protected abstract PlotBoundaries getPlotBoundaries(); + @Override + public void onPause() { + final PlotBoundaries plotBoundaries = getPlotBoundaries(); + if (plotBoundaries != null) { + saveBoundaries(plotBoundaries); + } + + super.onPause(); + } + @Override public void onResume() { super.onResume(); plotData = Locator.getInstance().getPlotter().getPlotData(); - createChart(plotData, initialPlotBoundaries); - createGraphicalView(getView(), plotData, initialPlotBoundaries); + createChart(plotData); + createGraphicalView(getView(), plotData); getSherlockActivity().invalidateOptionsMenu(); } @@ -164,16 +132,17 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment private void onNewPlotData(@NotNull final PlotData plotData) { this.plotData = plotData; - getUiHandler().post(new Runnable() { + final SherlockFragmentActivity activity = getSherlockActivity(); + Threads.tryRunOnUiThread(activity, new Runnable() { @Override public void run() { - getSherlockActivity().invalidateOptionsMenu(); + activity.invalidateOptionsMenu(); - createChart(plotData, initialPlotBoundaries); + createChart(plotData); final View view = getView(); if (view != null) { - createGraphicalView(view, plotData, initialPlotBoundaries); + createGraphicalView(view, plotData); } } }); @@ -181,18 +150,9 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment protected abstract void onError(); - protected abstract void createGraphicalView(@NotNull View view, @NotNull PlotData plotData, @NotNull PlotBoundaries plotBoundaries); + protected abstract void createGraphicalView(@NotNull View view, @NotNull PlotData plotData); - protected abstract void createChart(@NotNull PlotData plotData, @NotNull PlotBoundaries plotBoundaries); - - - protected double getMaxXValue(@Nullable PlotBoundaries plotBoundaries) { - return plotBoundaries == null ? DEFAULT_MAX_NUMBER : plotBoundaries.getXMax(); - } - - protected double getMinXValue(@Nullable PlotBoundaries plotBoundaries) { - return plotBoundaries == null ? DEFAULT_MIN_NUMBER : plotBoundaries.getXMin(); - } + protected abstract void createChart(@NotNull PlotData plotData); /* ********************************************************************** @@ -202,11 +162,6 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment ********************************************************************** */ - @NotNull - public Handler getUiHandler() { - return uiHandler; - } - public int getBgColor() { return bgColor; } @@ -380,65 +335,6 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment } } - public static final class PlotBoundaries implements Serializable { - - private double xMin; - private double xMax; - private double yMin; - private double yMax; - - public PlotBoundaries() { - } - - private PlotBoundaries(double xMin, double xMax, double yMin, double yMax) { - this.xMin = xMin; - this.xMax = xMax; - this.yMin = yMin; - this.yMax = yMax; - } - - @NotNull - public static PlotBoundaries newInstance(double xMin, double xMax, double yMin, double yMax) { - return new PlotBoundaries(xMin, xMax, yMin, yMax); - } - - public double getXMin() { - return xMin; - } - - public double getXMax() { - return xMax; - } - - public double getYMin() { - return yMin; - } - - public double getYMax() { - return yMax; - } - - @Override - public String toString() { - return "PlotBoundaries{" + - "yMax=" + yMax + - ", yMin=" + yMin + - ", xMax=" + xMax + - ", xMin=" + xMin + - '}'; - } - - @NotNull - public static PlotBoundaries newDefaultInstance() { - PlotBoundaries plotBoundaries = new PlotBoundaries(); - plotBoundaries.xMin = DEFAULT_MIN_NUMBER; - plotBoundaries.yMin = DEFAULT_MIN_NUMBER; - plotBoundaries.xMax = DEFAULT_MAX_NUMBER; - plotBoundaries.yMax = DEFAULT_MAX_NUMBER; - return plotBoundaries; - } - } - public static void applyToPaint(@NotNull PlotLineDef plotLineDef, @NotNull Paint paint) { paint.setColor(plotLineDef.getLineColor()); paint.setStyle(Paint.Style.STROKE); diff --git a/android-app/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotFragment.java b/android-app/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotFragment.java index f103fc50..6a5143e3 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotFragment.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotFragment.java @@ -29,7 +29,7 @@ public class CalculatorPlotFragment extends AbstractCalculatorPlotFragment { } @Override - protected void createGraphicalView(@NotNull View root, @NotNull PlotData plotData, @NotNull PlotBoundaries plotBoundaries) { + protected void createGraphicalView(@NotNull View root, @NotNull PlotData plotData) { // remove old final ViewGroup graphContainer = (ViewGroup) root.findViewById(R.id.main_fragment_layout); @@ -47,7 +47,7 @@ public class CalculatorPlotFragment extends AbstractCalculatorPlotFragment { // todo serso: investigate (after switching from 3d to 2d - blank screen) graphView.init(PlotViewDef.newInstance(Color.WHITE, Color.WHITE, Color.DKGRAY, getBgColor())); - //graphView.setXRange((float)plotBoundaries.getXMin(), (float)plotBoundaries.getXMax()); + graphView.setXRange(plotData.getBoundaries().getXMin(), plotData.getBoundaries().getXMax()); graphView.setPlotFunctions(plotData.getFunctions()); if (graphView instanceof View) { @@ -56,7 +56,7 @@ public class CalculatorPlotFragment extends AbstractCalculatorPlotFragment { } @Override - protected void createChart(@NotNull PlotData plotData, @NotNull PlotBoundaries plotBoundaries) { + protected void createChart(@NotNull PlotData plotData) { } @Override @@ -97,10 +97,11 @@ public class CalculatorPlotFragment extends AbstractCalculatorPlotFragment { @Override public void onPause() { - super.onPause(); if (this.graphView != null) { this.graphView.onPause(); } + + super.onPause(); } } diff --git a/core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java b/core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java index 5af19aed..073ccab4 100644 --- a/core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java +++ b/core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java @@ -160,6 +160,8 @@ public enum CalculatorEventType { show_create_function_dialog, plot_graph, + + /** {@link org.solovyev.android.calculator.plot.PlotData} */ plot_data_changed, //String diff --git a/core/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotter.java b/core/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotter.java index 35ce9f4e..338c778a 100644 --- a/core/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotter.java +++ b/core/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotter.java @@ -62,4 +62,6 @@ public interface CalculatorPlotter { void removeAllUnpinned(); void setPlotImag(boolean plotImag); + + void setPlotBoundaries(@NotNull PlotBoundaries plotBoundaries); } diff --git a/core/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotterImpl.java b/core/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotterImpl.java index 4f27c88d..23bca29b 100644 --- a/core/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotterImpl.java +++ b/core/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotterImpl.java @@ -35,6 +35,9 @@ public class CalculatorPlotterImpl implements CalculatorPlotter { private int arity = 0; + @NotNull + private PlotBoundaries plotBoundaries = PlotBoundaries.newDefaultInstance(); + public CalculatorPlotterImpl(@NotNull Calculator calculator) { this.calculator = calculator; } @@ -42,7 +45,7 @@ public class CalculatorPlotterImpl implements CalculatorPlotter { @NotNull @Override public PlotData getPlotData() { - return new PlotData(getVisibleFunctions(), plot3d); + return new PlotData(getVisibleFunctions(), plot3d, plotBoundaries); } @Override @@ -298,6 +301,11 @@ public class CalculatorPlotterImpl implements CalculatorPlotter { plot3d = false; } + if ( functions.isEmpty() ) { + // no functions => new plot => default boundaries + this.plotBoundaries = PlotBoundaries.newDefaultInstance(); + } + arity = maxArity; firePlotDataChangedEvent(); @@ -374,6 +382,14 @@ public class CalculatorPlotterImpl implements CalculatorPlotter { } } + @Override + public void setPlotBoundaries(@NotNull PlotBoundaries plotBoundaries) { + if ( !this.plotBoundaries.equals(plotBoundaries) ) { + this.plotBoundaries = plotBoundaries; + firePlotDataChangedEvent(); + } + } + private boolean toggleImagFunctions(boolean show) { boolean changed = false; diff --git a/core/src/main/java/org/solovyev/android/calculator/plot/PlotBoundaries.java b/core/src/main/java/org/solovyev/android/calculator/plot/PlotBoundaries.java new file mode 100644 index 00000000..b8cc83ef --- /dev/null +++ b/core/src/main/java/org/solovyev/android/calculator/plot/PlotBoundaries.java @@ -0,0 +1,103 @@ +package org.solovyev.android.calculator.plot; + +import org.jetbrains.annotations.NotNull; + +import java.io.Serializable; + +/** +* User: serso +* Date: 1/19/13 +* Time: 4:51 PM +*/ +public final class PlotBoundaries implements Serializable { + + private static final float DEFAULT_MIN_NUMBER = -10f; + + private static final float DEFAULT_MAX_NUMBER = 10f; + + + private float xMin; + private float xMax; + private float yMin; + private float yMax; + + public PlotBoundaries() { + } + + PlotBoundaries(float xMin, float xMax, float yMin, float yMax) { + this.xMin = xMin; + this.xMax = xMax; + this.yMin = yMin; + this.yMax = yMax; + } + + @NotNull + public static PlotBoundaries newInstance(float xMin, float xMax, float yMin, float yMax) { + return new PlotBoundaries(xMin, xMax, yMin, yMax); + } + + @NotNull + public static PlotBoundaries newInstance(float xMin, float xMax) { + return newInstance(xMin, xMax, DEFAULT_MIN_NUMBER, DEFAULT_MAX_NUMBER); + } + + public float getXMin() { + return xMin; + } + + public float getXMax() { + return xMax; + } + + public float getYMin() { + return yMin; + } + + public float getYMax() { + return yMax; + } + + @Override + public String toString() { + return "PlotBoundaries{" + + "yMax=" + yMax + + ", yMin=" + yMin + + ", xMax=" + xMax + + ", xMin=" + xMin + + '}'; + } + + @NotNull + public static PlotBoundaries newDefaultInstance() { + PlotBoundaries plotBoundaries = new PlotBoundaries(); + plotBoundaries.xMin = DEFAULT_MIN_NUMBER; + plotBoundaries.yMin = DEFAULT_MIN_NUMBER; + plotBoundaries.xMax = DEFAULT_MAX_NUMBER; + plotBoundaries.yMax = DEFAULT_MAX_NUMBER; + return plotBoundaries; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof PlotBoundaries)) return false; + + PlotBoundaries that = (PlotBoundaries) o; + + if (Float.compare(that.xMax, xMax) != 0) return false; + if (Float.compare(that.xMin, xMin) != 0) return false; + if (Float.compare(that.yMax, yMax) != 0) return false; + if (Float.compare(that.yMin, yMin) != 0) return false; + + return true; + } + + @Override + public int hashCode() { + int result = (xMin != +0.0f ? Float.floatToIntBits(xMin) : 0); + result = 31 * result + (xMax != +0.0f ? Float.floatToIntBits(xMax) : 0); + result = 31 * result + (yMin != +0.0f ? Float.floatToIntBits(yMin) : 0); + result = 31 * result + (yMax != +0.0f ? Float.floatToIntBits(yMax) : 0); + return result; + } +} diff --git a/core/src/main/java/org/solovyev/android/calculator/plot/PlotData.java b/core/src/main/java/org/solovyev/android/calculator/plot/PlotData.java index 82ce8797..c3a3daf5 100644 --- a/core/src/main/java/org/solovyev/android/calculator/plot/PlotData.java +++ b/core/src/main/java/org/solovyev/android/calculator/plot/PlotData.java @@ -16,9 +16,15 @@ public class PlotData { private boolean plot3d; - public PlotData(@NotNull List functions, boolean plot3d) { + @NotNull + private PlotBoundaries boundaries; + + public PlotData(@NotNull List functions, + boolean plot3d, + @NotNull PlotBoundaries boundaries) { this.functions = functions; this.plot3d = plot3d; + this.boundaries = boundaries; } @NotNull @@ -29,4 +35,9 @@ public class PlotData { public boolean isPlot3d() { return plot3d; } + + @NotNull + public PlotBoundaries getBoundaries() { + return boundaries; + } }