Plotter preferences

This commit is contained in:
Sergey Solovyev 2012-10-04 22:39:32 +04:00
parent d8015e48c7
commit 8a525e270a
14 changed files with 1443 additions and 1217 deletions

View File

@ -35,6 +35,7 @@
<activity android:label="@string/c_vars_and_constants" android:name=".math.edit.CalculatorVarsActivity"/>
<activity android:label="@string/c_plot_graph" android:name=".plot.CalculatorPlotActivity"/>
<activity android:label="@string/c_settings" android:name=".plot.CalculatorPlotPreferenceActivity"/>
<activity android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" android:name="com.google.ads.AdActivity"/>

View File

@ -87,4 +87,19 @@
<item>bin</item>
</string-array>
<string-array name="graph_line_color_names">
<item>White</item>
<item>Grey</item>
<item>Red</item>
<item>Blue</item>
<item>Green</item>
</string-array>
<string-array name="graph_line_color_values">
<item>white</item>
<item>grey</item>
<item>red</item>
<item>blue</item>
<item>green</item>
</string-array>
</resources>

View File

@ -108,6 +108,8 @@
<!-- action bar-->
<item name="actionBarTabStyle">@style/default_actionbar_tab_style</item>
<item name="android:actionBarTabStyle">@style/default_actionbar_tab_style</item>
<item name="actionBarStyle">@style/default_actionbar_style</item>
<item name="android:actionBarStyle">@style/default_actionbar_style</item>
</style>
</resources>

View File

@ -38,7 +38,9 @@
<!--action bar-->
<item name="actionBarTabStyle">@style/metro_blue_actionbar_tab_style</item>
<item name="android:actionBarTabStyle">@style/metro_blue_actionbar_tab_style</item>
<item name="actionBarStyle">@style/metro_blue_actionbar_style</item>
<item name="android:actionBarStyle">@style/metro_blue_actionbar_style</item>
</style>
</resources>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:a="http://schemas.android.com/apk/res/android">
<android.preference.CheckBoxPreference
a:key="graph_interpolate"
a:title="Interpolate function's graph"
a:summary="If checked cubic interpolation will be used in function graph drawing"/>
<ListPreference a:key="graph_line_color_real"
a:title="Color of real part of functions graph"
a:summary="Sets color of real part functions graph"
a:entries="@array/graph_line_color_names"
a:entryValues="@array/graph_line_color_values"/>
<ListPreference a:key="graph_line_color_imag"
a:title="Color of imaginary part of functions graph"
a:summary="Sets color of imaginary part functions graph"
a:entries="@array/graph_line_color_names"
a:entryValues="@array/graph_line_color_values"/>
</PreferenceScreen>

View File

@ -48,6 +48,11 @@ public interface CalculatorActivityHelper {
@Nullable Bundle fragmentArgs,
int parentViewId);
void setFragment(@NotNull SherlockFragmentActivity activity,
@NotNull CalculatorFragmentType fragmentType,
@Nullable Bundle fragmentArgs,
int parentViewId);
void logDebug(@NotNull String message);

View File

@ -6,6 +6,8 @@ import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.View;
import com.actionbarsherlock.app.ActionBar;
@ -197,6 +199,15 @@ public class CalculatorActivityHelperImpl extends AbstractCalculatorHelper imple
addTab(activity, fragmentType.getFragmentTag(), fragmentType.getFragmentClass(), fragmentArgs, fragmentType.getDefaultTitleResId(), parentViewId);
}
@Override
public void setFragment(@NotNull SherlockFragmentActivity activity, @NotNull CalculatorFragmentType fragmentType, @Nullable Bundle fragmentArgs, int parentViewId) {
final Fragment fragment = Fragment.instantiate(activity, fragmentType.getFragmentClass().getName(), fragmentArgs);
final FragmentManager fm = activity.getSupportFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
ft.add(parentViewId, fragment);
ft.commit();
}
@Override
public int getLayoutId() {
return layoutId;

View File

@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull;
import org.solovyev.android.AndroidUtils;
import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
import org.solovyev.android.calculator.plot.GraphLineColor;
import org.solovyev.android.prefs.BooleanPreference;
import org.solovyev.android.prefs.IntegerPreference;
import org.solovyev.android.prefs.Preference;
@ -98,7 +99,9 @@ public final class CalculatorPreferences {
}
public static class Graph {
public static final Preference<Boolean> showComplexGraph = new BooleanPreference("show_complex_graph", false);
public static final Preference<Boolean> interpolate = new BooleanPreference("graph_interpolate", true);
public static final Preference<GraphLineColor> lineColorReal = StringPreference.newInstance("graph_line_color_real", GraphLineColor.white, GraphLineColor.class);
public static final Preference<GraphLineColor> lineColorImag = StringPreference.newInstance("graph_line_color_imag", GraphLineColor.blue, GraphLineColor.class);
}

View File

@ -39,7 +39,10 @@ public class CalculatorPreferencesActivity extends SherlockPreferenceActivity im
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
//noinspection deprecation
addPreferencesFromResource(R.xml.preferences);
//noinspection deprecation
addPreferencesFromResource(R.xml.plot_preferences);
final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY);
adFreePreference.setEnabled(false);

View File

@ -1,5 +1,6 @@
package org.solovyev.android.calculator.plot;
import android.app.ActionBar;
import android.content.Intent;
import android.os.Bundle;
import org.jetbrains.annotations.Nullable;
@ -27,6 +28,7 @@ public class CalculatorPlotActivity extends CalculatorFragmentActivity {
arguments = null;
}
getActivityHelper().addTab(this, CalculatorFragmentType.plotter, arguments, R.id.main_layout);
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
getActivityHelper().setFragment(this, CalculatorFragmentType.plotter, arguments, R.id.main_layout);
}
}

View File

@ -6,8 +6,9 @@
package org.solovyev.android.calculator.plot;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
@ -17,25 +18,27 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragment;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import jscl.math.Expression;
import jscl.math.Generic;
import jscl.math.function.Constant;
import jscl.text.ParseException;
import org.achartengine.GraphicalView;
import org.achartengine.chart.CubicLineChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.chart.XYChart;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.BasicStroke;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
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.*;
import org.solovyev.android.menu.ActivityMenu;
import org.solovyev.android.menu.LabeledMenuItem;
import org.solovyev.android.menu.ListActivityMenu;
import org.solovyev.android.sherlock.menu.SherlockMenuHelper;
import org.solovyev.common.MutableObject;
import org.solovyev.common.collections.CollectionsUtils;
@ -48,12 +51,10 @@ import java.util.concurrent.Executors;
* Date: 12/1/11
* Time: 12:40 AM
*/
public class CalculatorPlotFragment extends SherlockFragment implements CalculatorEventListener {
public class CalculatorPlotFragment extends SherlockFragment implements CalculatorEventListener, SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = CalculatorPlotFragment.class.getSimpleName();
private static final int DEFAULT_NUMBER_OF_STEPS = 100;
private static final int DEFAULT_MIN_NUMBER = -10;
private static final int DEFAULT_MAX_NUMBER = 10;
@ -95,6 +96,12 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
private int bgColor;
@Nullable
private PlotBoundaries plotBoundaries = null;
@NotNull
private ActivityMenu<Menu, MenuItem> fragmentMenu = ListActivityMenu.fromList(PlotMenu.class, SherlockMenuHelper.getInstance());
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -117,7 +124,10 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
prepareData();
}
PreferenceManager.getDefaultSharedPreferences(this.getActivity()).registerOnSharedPreferenceChangeListener(this);
setRetainInstance(true);
setHasOptionsMenu(true);
}
private void createInputFromDisplayState(@NotNull CalculatorDisplayViewState displayState) {
@ -144,7 +154,7 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
this.expression = Expression.valueOf(preparedExpression.getExpression());
this.variable = new Constant(input.getVariableName());
this.chart = prepareChart(getMinValue(null), getMaxValue(null), this.expression, variable, bgColor);
initChart();
}
} catch (ParseException e) {
this.input = null;
@ -155,6 +165,17 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
}
}
private void initChart() {
if (input != null) {
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);
this.chart = PlotUtils.prepareChart(getMinValue(null), getMaxValue(null), this.expression, variable, bgColor, interpolate, realLineColor.getColor(), imagLineColor.getColor());
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return this.fragmentHelper.onCreateView(this, inflater, container);
@ -167,7 +188,6 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
this.fragmentHelper.onViewCreated(this, root);
PlotBoundaries plotBoundaries = null;
/*if ( savedInstanceState != null ) {
final Object object = savedInstanceState.getSerializable(PLOT_BOUNDARIES);
if ( object instanceof PlotBoundaries) {
@ -218,6 +238,8 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
public void onDestroy() {
this.fragmentHelper.onDestroy(this);
PreferenceManager.getDefaultSharedPreferences(this.getActivity()).unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
@ -304,7 +326,7 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
private void updateDataSets(@NotNull final XYChart chart, long millisToWait) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
final boolean showComplexGraph = CalculatorPreferences.Graph.showComplexGraph.getPreference(preferences);
final GraphLineColor imagLineColor = CalculatorPreferences.Graph.lineColorImag.getPreference(preferences);
pendingOperation.setObject(new Runnable() {
@Override
@ -329,14 +351,14 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
if (chart.getDataset().getSeriesCount() > 1) {
imagSeries = (MyXYSeries) chart.getDataset().getSeriesAt(1);
} else {
imagSeries = new MyXYSeries(getImagFunctionName(CalculatorPlotFragment.this.variable), DEFAULT_NUMBER_OF_STEPS * 2);
imagSeries = new MyXYSeries(PlotUtils.getImagFunctionName(CalculatorPlotFragment.this.variable), PlotUtils.DEFAULT_NUMBER_OF_STEPS * 2);
}
try {
if (PlotUtils.addXY(dr.getXAxisMin(), dr.getXAxisMax(), expression, variable, realSeries, imagSeries, true, DEFAULT_NUMBER_OF_STEPS)) {
if (PlotUtils.addXY(dr.getXAxisMin(), dr.getXAxisMax(), expression, variable, realSeries, imagSeries, true, PlotUtils.DEFAULT_NUMBER_OF_STEPS)) {
if (chart.getDataset().getSeriesCount() <= 1) {
chart.getDataset().addSeries(imagSeries);
chart.getRenderer().addSeriesRenderer(createImagRenderer());
chart.getRenderer().addSeriesRenderer(PlotUtils.createImagRenderer(imagLineColor.getColor()));
}
}
} catch (ArithmeticException e) {
@ -363,59 +385,9 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
uiHandler.postDelayed(pendingOperation.getObject(), millisToWait);
}
@NotNull
private static String getImagFunctionName(@NotNull Constant variable) {
return "g(" + variable.getName() + ")" + " = " + "Im(ƒ(" + variable.getName() + "))";
}
@NotNull
private static String getRealFunctionName(@NotNull Generic expression, @NotNull Constant variable) {
return "ƒ(" + variable.getName() + ")" + " = " + expression.toString();
}
@NotNull
private final MutableObject<Runnable> pendingOperation = new MutableObject<Runnable>();
private static XYChart prepareChart(final double minValue, final double maxValue, @NotNull final Generic expression, @NotNull final Constant variable, int bgColor) {
final MyXYSeries realSeries = new MyXYSeries(getRealFunctionName(expression, variable), DEFAULT_NUMBER_OF_STEPS * 2);
final MyXYSeries imagSeries = new MyXYSeries(getImagFunctionName(variable), DEFAULT_NUMBER_OF_STEPS * 2);
boolean imagExists = PlotUtils.addXY(minValue, maxValue, expression, variable, realSeries, imagSeries, false, DEFAULT_NUMBER_OF_STEPS);
final XYMultipleSeriesDataset data = new XYMultipleSeriesDataset();
data.addSeries(realSeries);
if (imagExists) {
data.addSeries(imagSeries);
}
final XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
renderer.setShowGrid(true);
renderer.setXTitle(variable.getName());
renderer.setYTitle("f(" + variable.getName() + ")");
renderer.setChartTitleTextSize(20);
renderer.setApplyBackgroundColor(true);
renderer.setBackgroundColor(bgColor);
renderer.setMarginsColor(bgColor);
renderer.setZoomEnabled(true);
renderer.setZoomButtonsVisible(true);
renderer.addSeriesRenderer(createCommonRenderer());
if (imagExists) {
renderer.addSeriesRenderer(createImagRenderer());
}
return new CubicLineChart(data, renderer, 0.1f);
//return new ScatterChart(data, renderer);
}
private static XYSeriesRenderer createImagRenderer() {
final XYSeriesRenderer imagRenderer = createCommonRenderer();
imagRenderer.setStroke(BasicStroke.DASHED);
imagRenderer.setColor(Color.LTGRAY);
return imagRenderer;
}
@Override
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable final Object data) {
if ( calculatorEventType.isOfType(CalculatorEventType.display_state_changed) ) {
@ -439,11 +411,87 @@ 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
public Object onRetainNonConfigurationInstance() {
return new PlotBoundaries(chart.getRenderer());
}*/
public void zoomInClickHandler(@NotNull View v) {
this.graphicalView.zoomIn();
}
public void zoomOutClickHandler(@NotNull View v) {
this.graphicalView.zoomOut();
}
/*
**********************************************************************
*
* MENU
*
**********************************************************************
*/
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
fragmentMenu.onCreateOptionsMenu(this.getActivity(), menu);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
fragmentMenu.onPrepareOptionsMenu(this.getActivity(), menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item) || fragmentMenu.onOptionsItemSelected(this.getActivity(), item);
}
/*
**********************************************************************
*
* STATIC
*
**********************************************************************
*/
private static enum PlotMenu implements LabeledMenuItem<MenuItem> {
preferences(R.string.c_settings) {
@Override
public void onClick(@NotNull MenuItem data, @NotNull Context context) {
context.startActivity(new Intent(context, CalculatorPlotPreferenceActivity.class));
}
};
private final int captionResId;
private PlotMenu(int captionResId) {
this.captionResId = captionResId;
}
@NotNull
@Override
public String getCaption(@NotNull Context context) {
return context.getString(captionResId);
}
}
private static final class PlotBoundaries implements Serializable {
private final double xMin;
@ -469,27 +517,6 @@ public class CalculatorPlotFragment extends SherlockFragment implements Calculat
}
}
@NotNull
private static XYSeriesRenderer createCommonRenderer() {
final XYSeriesRenderer renderer = new XYSeriesRenderer();
renderer.setFillPoints(true);
renderer.setPointStyle(PointStyle.CIRCLE);
renderer.setLineWidth(3);
renderer.setColor(Color.WHITE);
renderer.setStroke(BasicStroke.SOLID);
return renderer;
}
public void zoomInClickHandler(@NotNull View v) {
this.graphicalView.zoomIn();
}
public void zoomOutClickHandler(@NotNull View v) {
this.graphicalView.zoomOut();
}
public static class Input implements Serializable {
@NotNull

View File

@ -0,0 +1,21 @@
package org.solovyev.android.calculator.plot;
import android.os.Bundle;
import com.actionbarsherlock.app.SherlockPreferenceActivity;
import org.solovyev.android.calculator.R;
/**
* User: serso
* Date: 10/4/12
* Time: 9:01 PM
*/
public class CalculatorPlotPreferenceActivity extends SherlockPreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//noinspection deprecation
addPreferencesFromResource(R.xml.plot_preferences);
}
}

View File

@ -0,0 +1,28 @@
package org.solovyev.android.calculator.plot;
import android.graphics.Color;
/**
* User: serso
* Date: 10/4/12
* Time: 10:08 PM
*/
public enum GraphLineColor {
white(Color.WHITE),
grey(Color.GRAY),
red(Color.RED),
blue(Color.rgb(16, 100, 140)),
green(Color.GREEN);
private final int color;
private GraphLineColor(int color) {
this.color = color;
}
public int getColor() {
return this.color;
}
}

View File

@ -15,6 +15,14 @@ import jscl.math.function.Constant;
import jscl.math.numeric.Complex;
import jscl.math.numeric.Numeric;
import jscl.math.numeric.Real;
import org.achartengine.chart.CubicLineChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.chart.ScatterChart;
import org.achartengine.chart.XYChart;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.renderer.BasicStroke;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import org.achartengine.util.MathHelper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -28,8 +36,9 @@ public final class PlotUtils {
private static final double MAX_Y_DIFF = 1;
private static final double MAX_X_DIFF = 1;
static final int DEFAULT_NUMBER_OF_STEPS = 100;
// not intended for instantiation
// not intended for instantiation
private PlotUtils() {
throw new AssertionError();
}
@ -113,6 +122,81 @@ public final class PlotUtils {
return imagExists;
}
@NotNull
static String getImagFunctionName(@NotNull Constant variable) {
return "g(" + variable.getName() + ")" + " = " + "Im(ƒ(" + variable.getName() + "))";
}
@NotNull
private static String getRealFunctionName(@NotNull Generic expression, @NotNull Constant variable) {
return "ƒ(" + variable.getName() + ")" + " = " + expression.toString();
}
@NotNull
static XYChart prepareChart(final double minValue,
final double maxValue,
@NotNull final Generic expression,
@NotNull final Constant variable,
int bgColor,
boolean interpolate,
int realLineColor,
int imagLineColor) {
final MyXYSeries realSeries = new MyXYSeries(getRealFunctionName(expression, variable), DEFAULT_NUMBER_OF_STEPS * 2);
final MyXYSeries imagSeries = new MyXYSeries(getImagFunctionName(variable), DEFAULT_NUMBER_OF_STEPS * 2);
boolean imagExists = addXY(minValue, maxValue, expression, variable, realSeries, imagSeries, false, DEFAULT_NUMBER_OF_STEPS);
final XYMultipleSeriesDataset data = new XYMultipleSeriesDataset();
data.addSeries(realSeries);
if (imagExists) {
data.addSeries(imagSeries);
}
final XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
renderer.setShowGrid(true);
renderer.setXTitle(variable.getName());
renderer.setYTitle("f(" + variable.getName() + ")");
renderer.setChartTitleTextSize(25);
renderer.setAxisTitleTextSize(25);
renderer.setLabelsTextSize(25);
renderer.setLegendTextSize(25);
renderer.setMargins(new int[]{25, 25, 25, 25});
renderer.setApplyBackgroundColor(true);
renderer.setBackgroundColor(bgColor);
renderer.setMarginsColor(bgColor);
renderer.setZoomEnabled(true);
renderer.setZoomButtonsVisible(true);
renderer.addSeriesRenderer(createCommonRenderer(realLineColor));
if (imagExists) {
renderer.addSeriesRenderer(createImagRenderer(imagLineColor));
}
if (interpolate) {
return new CubicLineChart(data, renderer, 0.1f);
} else {
return new ScatterChart(data, renderer);
}
}
static XYSeriesRenderer createImagRenderer(int color) {
final XYSeriesRenderer imagRenderer = createCommonRenderer(color);
imagRenderer.setStroke(BasicStroke.DASHED);
return imagRenderer;
}
@NotNull
private static XYSeriesRenderer createCommonRenderer(int color) {
final XYSeriesRenderer renderer = new XYSeriesRenderer();
renderer.setFillPoints(true);
renderer.setPointStyle(PointStyle.CIRCLE);
renderer.setLineWidth(3);
renderer.setColor(color);
renderer.setStroke(BasicStroke.SOLID);
return renderer;
}
private static class Point {
private static final double DEFAULT = Double.MIN_VALUE;