Plotter preferences

This commit is contained in:
Sergey Solovyev 2012-10-04 23:37:19 +04:00
parent 8a525e270a
commit d84e5437b4
2 changed files with 294 additions and 249 deletions

View File

@ -27,6 +27,10 @@ public abstract class CalculatorFragment extends SherlockFragment {
fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(fragmentType.getDefaultLayoutId(), fragmentType.getDefaultTitleResId()); fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(fragmentType.getDefaultLayoutId(), fragmentType.getDefaultTitleResId());
} }
protected CalculatorFragment(@NotNull CalculatorFragmentHelper fragmentHelper) {
this.fragmentHelper = fragmentHelper;
}
@Override @Override
public void onAttach(Activity activity) { public void onAttach(Activity activity) {
super.onAttach(activity); super.onAttach(activity);

View File

@ -12,12 +12,11 @@ import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.v4.app.FragmentActivity;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Toast; import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragment;
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;
@ -51,7 +50,7 @@ import java.util.concurrent.Executors;
* Date: 12/1/11 * Date: 12/1/11
* Time: 12:40 AM * Time: 12:40 AM
*/ */
public class CalculatorPlotFragment extends SherlockFragment implements CalculatorEventListener, SharedPreferences.OnSharedPreferenceChangeListener { public class CalculatorPlotFragment extends CalculatorFragment implements CalculatorEventListener {
private static final String TAG = CalculatorPlotFragment.class.getSimpleName(); private static final String TAG = CalculatorPlotFragment.class.getSimpleName();
@ -64,32 +63,25 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
public static final long EVAL_DELAY_MILLIS = 200; public static final long EVAL_DELAY_MILLIS = 200;
@Nullable
private XYChart chart; private XYChart chart;
/** /**
* The encapsulated graphical view. * The encapsulated graphical view.
*/ */
@Nullable
private GraphicalView graphicalView; private GraphicalView graphicalView;
@NotNull // thread which calculated data for graph view
private Generic expression;
@NotNull
private Constant variable;
@NotNull
private final CalculatorFragmentHelper fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(R.layout.plot_fragment, R.string.c_graph, false);
@NotNull @NotNull
private final Executor plotExecutor = Executors.newSingleThreadExecutor(); private final Executor plotExecutor = Executors.newSingleThreadExecutor();
// thread for applying UI changes
@NotNull @NotNull
private final Handler uiHandler = new Handler(); private final Handler uiHandler = new Handler();
@Nullable @NotNull
private Input input = null; private PreparedInput preparedInput;
private boolean inputFromArgs = true;
@NotNull @NotNull
private CalculatorEventData lastCalculatorEventData = CalculatorUtils.createFirstEventDataId(); private CalculatorEventData lastCalculatorEventData = CalculatorUtils.createFirstEventDataId();
@ -102,91 +94,89 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
@NotNull @NotNull
private ActivityMenu<Menu, MenuItem> fragmentMenu = ListActivityMenu.fromList(PlotMenu.class, SherlockMenuHelper.getInstance()); private ActivityMenu<Menu, MenuItem> fragmentMenu = ListActivityMenu.fromList(PlotMenu.class, SherlockMenuHelper.getInstance());
public CalculatorPlotFragment() {
super(CalculatorApplication.getInstance().createFragmentHelper(R.layout.plot_fragment, R.string.c_graph, false));
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
this.fragmentHelper.onCreate(this);
final Bundle arguments = getArguments(); final Bundle arguments = getArguments();
Input input = null;
if (arguments != null) { if (arguments != null) {
input = (Input) arguments.getSerializable(INPUT); input = (Input) arguments.getSerializable(INPUT);
} }
if (input == null) { if (input == null) {
inputFromArgs = false; this.preparedInput = prepareInputFromDisplay(CalculatorLocatorImpl.getInstance().getDisplay().getViewState());
createInputFromDisplayState(CalculatorLocatorImpl.getInstance().getDisplay().getViewState());
this.bgColor = getResources().getColor(R.color.pane_background); this.bgColor = getResources().getColor(R.color.pane_background);
} else { } else {
this.preparedInput = prepareInput(input, true);
this.bgColor = getResources().getColor(android.R.color.transparent); this.bgColor = getResources().getColor(android.R.color.transparent);
prepareData();
} }
PreferenceManager.getDefaultSharedPreferences(this.getActivity()).registerOnSharedPreferenceChangeListener(this);
setRetainInstance(true); setRetainInstance(true);
setHasOptionsMenu(true); setHasOptionsMenu(true);
} }
private void createInputFromDisplayState(@NotNull CalculatorDisplayViewState displayState) { @NotNull
private static PreparedInput prepareInputFromDisplay(@NotNull CalculatorDisplayViewState displayState) {
try { try {
if (displayState.isValid() && displayState.getResult() != null) { if (displayState.isValid() && displayState.getResult() != null) {
final Generic expression = displayState.getResult(); final Generic expression = displayState.getResult();
if (CalculatorUtils.isPlotPossible(expression, displayState.getOperation())) { if (CalculatorUtils.isPlotPossible(expression, displayState.getOperation())) {
final Constant constant = CollectionsUtils.getFirstCollectionElement(CalculatorUtils.getNotSystemConstants(expression)); final Constant constant = CollectionsUtils.getFirstCollectionElement(CalculatorUtils.getNotSystemConstants(expression));
input = new Input(expression.toString(), constant.getName());
prepareData(); final Input input = new Input(expression.toString(), constant.getName());
return prepareInput(input, false);
} }
} }
} catch (RuntimeException e) { } catch (RuntimeException e) {
this.input = null;
Log.e(TAG, e.getLocalizedMessage(), e); Log.e(TAG, e.getLocalizedMessage(), e);
} }
return PreparedInput.newErrorInstance(false);
} }
private void prepareData(){ @NotNull
private static PreparedInput prepareInput(@NotNull Input input, boolean fromInputArgs) {
PreparedInput result;
try { try {
if (input != null) { final PreparedExpression preparedExpression = ToJsclTextProcessor.getInstance().process(input.getExpression());
final PreparedExpression preparedExpression = ToJsclTextProcessor.getInstance().process(input.getExpression()); final Generic expression = Expression.valueOf(preparedExpression.getExpression());
this.expression = Expression.valueOf(preparedExpression.getExpression()); final Constant variable = new Constant(input.getVariableName());
this.variable = new Constant(input.getVariableName());
initChart(); result = PreparedInput.newInstance(input, expression, variable, fromInputArgs);
}
} catch (ParseException e) { } catch (ParseException e) {
this.input = null; result = PreparedInput.newErrorInstance(fromInputArgs);
Toast.makeText(this.getActivity(), e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); CalculatorLocatorImpl.getInstance().getNotifier().showMessage(e);
} catch (CalculatorParseException e) { } catch (CalculatorParseException e) {
this.input = null; result = PreparedInput.newErrorInstance(fromInputArgs);
Toast.makeText(this.getActivity(), e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); CalculatorLocatorImpl.getInstance().getNotifier().showMessage(e);
} }
return result;
} }
private void initChart() { private void createChart() {
if (input != null) { if (!preparedInput.isError()) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity()); final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
final Boolean interpolate = CalculatorPreferences.Graph.interpolate.getPreference(preferences); final Boolean interpolate = CalculatorPreferences.Graph.interpolate.getPreference(preferences);
final GraphLineColor realLineColor = CalculatorPreferences.Graph.lineColorReal.getPreference(preferences); final GraphLineColor realLineColor = CalculatorPreferences.Graph.lineColorReal.getPreference(preferences);
final GraphLineColor imagLineColor = CalculatorPreferences.Graph.lineColorImag.getPreference(preferences); final GraphLineColor imagLineColor = CalculatorPreferences.Graph.lineColorImag.getPreference(preferences);
this.chart = PlotUtils.prepareChart(getMinValue(null), getMaxValue(null), this.expression, variable, bgColor, interpolate, realLineColor.getColor(), imagLineColor.getColor()); //noinspection ConstantConditions
this.chart = PlotUtils.prepareChart(getMinValue(null), getMaxValue(null), preparedInput.getExpression(), preparedInput.getVariable(), bgColor, interpolate, realLineColor.getColor(), imagLineColor.getColor());
} }
} }
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return this.fragmentHelper.onCreateView(this, inflater, container);
}
@Override @Override
public void onViewCreated(View root, Bundle savedInstanceState) { public void onViewCreated(View root, Bundle savedInstanceState) {
super.onViewCreated(root, savedInstanceState); super.onViewCreated(root, savedInstanceState);
this.fragmentHelper.onViewCreated(this, root);
/*if ( savedInstanceState != null ) { /*if ( savedInstanceState != null ) {
final Object object = savedInstanceState.getSerializable(PLOT_BOUNDARIES); final Object object = savedInstanceState.getSerializable(PLOT_BOUNDARIES);
@ -195,120 +185,103 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
} }
}*/ }*/
updateGraphicalView(root, plotBoundaries); if (preparedInput.isFromInputArgs()) {
createChart();
createGraphicalView(root, null);
}
} }
@Override @Override
public void onSaveInstanceState(Bundle out) { public void onSaveInstanceState(Bundle out) {
super.onSaveInstanceState(out); super.onSaveInstanceState(out);
/*if (chart != null) { if (chart != null) {
out.putSerializable(PLOT_BOUNDARIES, new PlotBoundaries(chart.getRenderer())); out.putSerializable(PLOT_BOUNDARIES, new PlotBoundaries(chart.getRenderer()));
}*/ }
} }
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
this.fragmentHelper.onResume(this); if (!preparedInput.isFromInputArgs()) {
this.preparedInput = prepareInputFromDisplay(CalculatorLocatorImpl.getInstance().getDisplay().getViewState());
if ( !inputFromArgs ) {
createInputFromDisplayState(CalculatorLocatorImpl.getInstance().getDisplay().getViewState());
updateGraphicalView(getView(), null);
} }
createChart();
createGraphicalView(getView(), plotBoundaries);
} }
@Override private void createGraphicalView(@NotNull View root, @Nullable PlotBoundaries plotBoundaries) {
public void onPause() { if (!preparedInput.isError()) {
this.fragmentHelper.onPause(this); final XYChart chart = this.chart;
assert chart != null;
super.onPause(); double minValue = getMinValue(plotBoundaries);
} double maxValue = getMaxValue(plotBoundaries);
private void updateGraphicalView(@NotNull View root, @Nullable PlotBoundaries plotBoundaries) { final ViewGroup graphContainer = (ViewGroup) root.findViewById(R.id.main_fragment_layout);
if (input != null) {
setGraphicalView(root, plotBoundaries); if (graphicalView != null) {
graphContainer.removeView(graphicalView);
}
// 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 (plotBoundaries == null) {
chart.getRenderer().setXAxisMin(Math.max(minX, minValue));
chart.getRenderer().setYAxisMin(Math.max(minY, minValue));
chart.getRenderer().setXAxisMax(Math.min(maxX, maxValue));
chart.getRenderer().setYAxisMax(Math.min(maxY, maxValue));
} else {
chart.getRenderer().setXAxisMin(plotBoundaries.xMin);
chart.getRenderer().setYAxisMin(plotBoundaries.yMin);
chart.getRenderer().setXAxisMax(plotBoundaries.xMax);
chart.getRenderer().setYAxisMax(plotBoundaries.yMax);
}
graphicalView = new GraphicalView(this.getActivity(), chart);
graphicalView.setBackgroundColor(this.bgColor);
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() {
Log.d(TAG, "org.achartengine.tools.PanListener.panApplied");
updateDataSets(chart);
}
});
graphContainer.addView(graphicalView);
updateDataSets(chart, 50);
} else { } else {
Toast.makeText(this.getActivity(), "Plot is not possible!", Toast.LENGTH_LONG).show(); Toast.makeText(this.getActivity(), "Plot is not possible!", Toast.LENGTH_LONG).show();
} }
}
@Override
public void onDestroy() {
this.fragmentHelper.onDestroy(this);
PreferenceManager.getDefaultSharedPreferences(this.getActivity()).unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
private void setGraphicalView(@NotNull View root, @Nullable PlotBoundaries plotBoundaries) {
double minValue = getMinValue(plotBoundaries);
double maxValue = getMaxValue(plotBoundaries);
final ViewGroup graphContainer = (ViewGroup) root.findViewById(R.id.main_fragment_layout);
if (graphicalView != null) {
graphContainer.removeView(graphicalView);
}
// 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());
}
Log.d(CalculatorPlotFragment.class.getName(), "min x: " + minX + ", min y: " + minY + ", max x: " + maxX + ", max y: " + maxY);
Log.d(CalculatorPlotFragment.class.getName(), "Plot boundaries are " + plotBoundaries);
if (plotBoundaries == null) {
chart.getRenderer().setXAxisMin(Math.max(minX, minValue));
chart.getRenderer().setYAxisMin(Math.max(minY, minValue));
chart.getRenderer().setXAxisMax(Math.min(maxX, maxValue));
chart.getRenderer().setYAxisMax(Math.min(maxY, maxValue));
} else {
chart.getRenderer().setXAxisMin(plotBoundaries.xMin);
chart.getRenderer().setYAxisMin(plotBoundaries.yMin);
chart.getRenderer().setXAxisMax(plotBoundaries.xMax);
chart.getRenderer().setYAxisMax(plotBoundaries.yMax);
}
graphicalView = new GraphicalView(this.getActivity(), chart);
graphicalView.setBackgroundColor(this.bgColor);
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() {
Log.d(TAG, "org.achartengine.tools.PanListener.panApplied");
updateDataSets(chart);
}
});
graphContainer.addView(graphicalView);
updateDataSets(chart, 50);
} }
private double getMaxValue(@Nullable PlotBoundaries plotBoundaries) { private double getMaxValue(@Nullable PlotBoundaries plotBoundaries) {
@ -328,6 +301,9 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity()); final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
final GraphLineColor imagLineColor = CalculatorPreferences.Graph.lineColorImag.getPreference(preferences); final GraphLineColor imagLineColor = CalculatorPreferences.Graph.lineColorImag.getPreference(preferences);
final Generic expression = preparedInput.getExpression();
final Constant variable = preparedInput.getVariable();
pendingOperation.setObject(new Runnable() { pendingOperation.setObject(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -351,7 +327,7 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
if (chart.getDataset().getSeriesCount() > 1) { if (chart.getDataset().getSeriesCount() > 1) {
imagSeries = (MyXYSeries) chart.getDataset().getSeriesAt(1); imagSeries = (MyXYSeries) chart.getDataset().getSeriesAt(1);
} else { } else {
imagSeries = new MyXYSeries(PlotUtils.getImagFunctionName(CalculatorPlotFragment.this.variable), PlotUtils.DEFAULT_NUMBER_OF_STEPS * 2); imagSeries = new MyXYSeries(PlotUtils.getImagFunctionName(variable), PlotUtils.DEFAULT_NUMBER_OF_STEPS * 2);
} }
try { try {
@ -390,19 +366,21 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
@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.display_state_changed)) {
if ( !inputFromArgs ) { if (!preparedInput.isFromInputArgs()) {
if ( calculatorEventData.isAfter(this.lastCalculatorEventData) ) { if (calculatorEventData.isAfter(this.lastCalculatorEventData)) {
this.lastCalculatorEventData = calculatorEventData; this.lastCalculatorEventData = calculatorEventData;
createInputFromDisplayState(((CalculatorDisplayChangeEventData) data).getNewValue()); this.preparedInput = prepareInputFromDisplay(((CalculatorDisplayChangeEventData) data).getNewValue());
createChart();
uiHandler.post(new Runnable() { uiHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
final View view = getView(); final View view = getView();
if (view != null) { if (view != null) {
updateGraphicalView(view, null); createGraphicalView(view, null);
} }
} }
}); });
@ -411,29 +389,19 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
} }
} }
@Override
public void onSharedPreferenceChanged(@NotNull SharedPreferences preferences, @NotNull String key) {
if ( CalculatorPreferences.Graph.interpolate.getKey().equals(key) ||
CalculatorPreferences.Graph.lineColorReal.getKey().equals(key) ||
CalculatorPreferences.Graph.lineColorImag.getKey().equals(key)) {
initChart();
updateGraphicalView(getView(), plotBoundaries);
}
}
/*@Override /*@Override
public Object onRetainNonConfigurationInstance() { public Object onRetainNonConfigurationInstance() {
return new PlotBoundaries(chart.getRenderer()); return new PlotBoundaries(chart.getRenderer());
}*/ }*/
public void zoomInClickHandler(@NotNull View v) { /* public void zoomInClickHandler(@NotNull View v) {
this.graphicalView.zoomIn(); this.graphicalView.zoomIn();
} }
public void zoomOutClickHandler(@NotNull View v) { public void zoomOutClickHandler(@NotNull View v) {
this.graphicalView.zoomOut(); this.graphicalView.zoomOut();
} }*/
/* /*
********************************************************************** **********************************************************************
@ -447,14 +415,20 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);
fragmentMenu.onCreateOptionsMenu(this.getActivity(), menu); final FragmentActivity activity = this.getActivity();
if (activity != null) {
fragmentMenu.onCreateOptionsMenu(activity, menu);
}
} }
@Override @Override
public void onPrepareOptionsMenu(Menu menu) { public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu); super.onPrepareOptionsMenu(menu);
fragmentMenu.onPrepareOptionsMenu(this.getActivity(), menu); final FragmentActivity activity = this.getActivity();
if (activity != null) {
fragmentMenu.onPrepareOptionsMenu(activity, menu);
}
} }
@Override @Override
@ -492,12 +466,15 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
} }
} }
private static final class PlotBoundaries implements Serializable { public static final class PlotBoundaries implements Serializable {
private final double xMin; private double xMin;
private final double xMax; private double xMax;
private final double yMin; private double yMin;
private final double yMax; private double yMax;
public PlotBoundaries() {
}
public PlotBoundaries(@NotNull XYMultipleSeriesRenderer renderer) { public PlotBoundaries(@NotNull XYMultipleSeriesRenderer renderer) {
this.xMin = renderer.getXAxisMin(); this.xMin = renderer.getXAxisMin();
@ -517,6 +494,70 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
} }
} }
public static class PreparedInput {
@Nullable
private Input input;
@Nullable
private Generic expression;
@Nullable
private Constant variable;
private boolean fromInputArgs;
private PreparedInput() {
}
@NotNull
public static PreparedInput newInstance(@NotNull Input input, @NotNull Generic expression, @NotNull Constant variable, boolean fromInputArgs) {
final PreparedInput result = new PreparedInput();
result.input = input;
result.expression = expression;
result.variable = variable;
result.fromInputArgs = fromInputArgs;
return result;
}
@NotNull
public static PreparedInput newErrorInstance(boolean fromInputArgs) {
final PreparedInput result = new PreparedInput();
result.input = null;
result.expression = null;
result.variable = null;
result.fromInputArgs = fromInputArgs;
return result;
}
public boolean isFromInputArgs() {
return fromInputArgs;
}
@Nullable
public Input getInput() {
return input;
}
@Nullable
public Generic getExpression() {
return expression;
}
@Nullable
public Constant getVariable() {
return variable;
}
public boolean isError() {
return input == null || expression == null || variable == null;
}
}
public static class Input implements Serializable { public static class Input implements Serializable {
@NotNull @NotNull