plotting
This commit is contained in:
parent
7822663989
commit
def00244a5
@ -12,7 +12,8 @@
|
|||||||
a:targetSdkVersion="8"/>
|
a:targetSdkVersion="8"/>
|
||||||
|
|
||||||
<application a:icon="@drawable/icon"
|
<application a:icon="@drawable/icon"
|
||||||
a:label="@string/c_app_name">
|
a:label="@string/c_app_name"
|
||||||
|
a:name=".ApplicationContext">
|
||||||
|
|
||||||
<activity a:name=".CalculatorActivity"
|
<activity a:name=".CalculatorActivity"
|
||||||
a:label="@string/c_app_name">
|
a:label="@string/c_app_name">
|
||||||
@ -30,8 +31,7 @@
|
|||||||
|
|
||||||
<activity a:name=".CalculatorHistoryActivity"
|
<activity a:name=".CalculatorHistoryActivity"
|
||||||
a:label="@string/c_app_history"
|
a:label="@string/c_app_history"
|
||||||
a:configChanges="orientation|keyboardHidden">
|
a:configChanges="orientation|keyboardHidden"/>
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity a:name=".AboutActivity"
|
<activity a:name=".AboutActivity"
|
||||||
a:label="@string/c_about"
|
a:label="@string/c_about"
|
||||||
@ -55,23 +55,18 @@
|
|||||||
|
|
||||||
<activity a:name=".CalculatorFunctionsActivity"
|
<activity a:name=".CalculatorFunctionsActivity"
|
||||||
a:label="@string/c_functions"
|
a:label="@string/c_functions"
|
||||||
a:configChanges="orientation|keyboardHidden">
|
a:configChanges="orientation|keyboardHidden"/>
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity a:name=".CalculatorOperatorsActivity"
|
<activity a:name=".CalculatorOperatorsActivity"
|
||||||
a:label="@string/c_operators"
|
a:label="@string/c_operators"
|
||||||
a:configChanges="orientation|keyboardHidden">
|
a:configChanges="orientation|keyboardHidden"/>
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity a:name=".CalculatorVarsActivity"
|
<activity a:name=".CalculatorVarsActivity"
|
||||||
a:label="@string/c_vars_and_constants"
|
a:label="@string/c_vars_and_constants"
|
||||||
a:configChanges="orientation|keyboardHidden">
|
a:configChanges="orientation|keyboardHidden"/>
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity a:name=".CalculatorPlotActivity"
|
<activity a:name=".CalculatorPlotActivity"
|
||||||
a:label="@string/c_plot_graph"
|
a:label="@string/c_plot_graph"/>
|
||||||
a:configChanges="orientation|keyboardHidden">
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
48
res/layout-land/calc_plot_view.xml
Normal file
48
res/layout-land/calc_plot_view.xml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
|
a:id="@+id/plot_view_container"
|
||||||
|
a:orientation="horizontal"
|
||||||
|
a:layout_width="fill_parent"
|
||||||
|
a:layout_height="fill_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
a:id="@+id/plot_graph_container"
|
||||||
|
a:orientation="vertical"
|
||||||
|
a:layout_width="wrap_content"
|
||||||
|
a:layout_height="wrap_content"
|
||||||
|
a:layout_weight="3">
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
a:orientation="vertical"
|
||||||
|
a:layout_width="wrap_content"
|
||||||
|
a:layout_height="wrap_content"
|
||||||
|
a:layout_weight="1">
|
||||||
|
|
||||||
|
<TextView a:layout_height="wrap_content"
|
||||||
|
a:layout_width="fill_parent"
|
||||||
|
a:padding="6dp"
|
||||||
|
style="@style/default_text_size"
|
||||||
|
a:text="@string/c_min_x_value"/>
|
||||||
|
|
||||||
|
<org.solovyev.android.view.widgets.NumberPicker
|
||||||
|
a:id="@+id/plot_x_min_value"
|
||||||
|
a:layout_width="wrap_content"
|
||||||
|
a:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<TextView a:layout_height="wrap_content"
|
||||||
|
a:layout_width="fill_parent"
|
||||||
|
a:padding="6dp"
|
||||||
|
style="@style/default_text_size"
|
||||||
|
a:text="@string/c_max_x_value"/>
|
||||||
|
|
||||||
|
<org.solovyev.android.view.widgets.NumberPicker
|
||||||
|
a:id="@+id/plot_x_max_value"
|
||||||
|
a:layout_width="wrap_content"
|
||||||
|
a:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
48
res/layout-port/calc_plot_view.xml
Normal file
48
res/layout-port/calc_plot_view.xml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
|
a:id="@+id/plot_view_container"
|
||||||
|
a:orientation="vertical"
|
||||||
|
a:layout_width="fill_parent"
|
||||||
|
a:layout_height="fill_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
a:id="@+id/plot_graph_container"
|
||||||
|
a:orientation="horizontal"
|
||||||
|
a:layout_width="wrap_content"
|
||||||
|
a:layout_height="wrap_content"
|
||||||
|
a:layout_weight="3">
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
a:orientation="horizontal"
|
||||||
|
a:layout_width="wrap_content"
|
||||||
|
a:layout_height="wrap_content"
|
||||||
|
a:layout_weight="1">
|
||||||
|
|
||||||
|
<TextView a:layout_height="wrap_content"
|
||||||
|
a:layout_width="fill_parent"
|
||||||
|
a:padding="6dp"
|
||||||
|
style="@style/default_text_size"
|
||||||
|
a:text="@string/c_min_x_value"/>
|
||||||
|
|
||||||
|
<org.solovyev.android.view.widgets.NumberPicker
|
||||||
|
a:id="@+id/plot_x_min_value"
|
||||||
|
a:layout_width="wrap_content"
|
||||||
|
a:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<TextView a:layout_height="wrap_content"
|
||||||
|
a:layout_width="fill_parent"
|
||||||
|
a:padding="6dp"
|
||||||
|
style="@style/default_text_size"
|
||||||
|
a:text="@string/c_max_x_value"/>
|
||||||
|
|
||||||
|
<org.solovyev.android.view.widgets.NumberPicker
|
||||||
|
a:id="@+id/plot_x_max_value"
|
||||||
|
a:layout_width="wrap_content"
|
||||||
|
a:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -277,5 +277,7 @@ Check the \'Round result\' preference in application settings - it should be tur
|
|||||||
<string name="msg_6">Infinite loop is detected in expression</string>
|
<string name="msg_6">Infinite loop is detected in expression</string>
|
||||||
|
|
||||||
<string name="c_plot_graph">Graph</string>
|
<string name="c_plot_graph">Graph</string>
|
||||||
|
<string name="c_min_x_value">From</string>
|
||||||
|
<string name="c_max_x_value">To</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 12/1/11
|
||||||
|
* Time: 1:21 PM
|
||||||
|
*/
|
||||||
|
public class ApplicationContext extends android.app.Application {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static ApplicationContext instance;
|
||||||
|
|
||||||
|
public ApplicationContext() {
|
||||||
|
instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static ApplicationContext getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
@ -74,7 +74,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setLayout(preferences);
|
setLayout(preferences);
|
||||||
|
|
||||||
ResourceCache.instance.initCaptions(R.string.class, this);
|
ResourceCache.instance.initCaptions(ApplicationContext.getInstance(), R.string.class);
|
||||||
firstTimeInit(preferences);
|
firstTimeInit(preferences);
|
||||||
|
|
||||||
vibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE);
|
vibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE);
|
||||||
|
@ -16,7 +16,9 @@ import org.achartengine.model.XYMultipleSeriesDataset;
|
|||||||
import org.achartengine.model.XYSeries;
|
import org.achartengine.model.XYSeries;
|
||||||
import org.achartengine.renderer.XYMultipleSeriesRenderer;
|
import org.achartengine.renderer.XYMultipleSeriesRenderer;
|
||||||
import org.achartengine.renderer.XYSeriesRenderer;
|
import org.achartengine.renderer.XYSeriesRenderer;
|
||||||
|
import org.achartengine.util.MathHelper;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.calculator.help.HelpActivity;
|
import org.solovyev.android.calculator.help.HelpActivity;
|
||||||
import org.solovyev.common.utils.StringUtils;
|
import org.solovyev.common.utils.StringUtils;
|
||||||
|
|
||||||
@ -56,47 +58,12 @@ public class CalculatorActivityLauncher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void plotGraph(@NotNull final Context context, @NotNull Generic generic, @NotNull Constant constant) throws ArithmeticException {
|
public static void plotGraph(@NotNull final Context context, @NotNull Generic generic, @NotNull Constant constant) throws ArithmeticException {
|
||||||
|
final Intent intent = new Intent();
|
||||||
final XYSeries series = new XYSeries(generic.toString());
|
intent.putExtra(CalculatorPlotActivity.INPUT, new CalculatorPlotActivity.Input(generic.toString(), constant.getName()));
|
||||||
|
|
||||||
final double min = -10;
|
|
||||||
final double max = 10;
|
|
||||||
final double step = 0.5;
|
|
||||||
double x = min;
|
|
||||||
while (x <= max) {
|
|
||||||
Generic numeric = generic.substitute(constant, Expression.valueOf(x)).numeric();
|
|
||||||
series.add(x, unwrap(numeric));
|
|
||||||
x += step;
|
|
||||||
}
|
|
||||||
final XYMultipleSeriesDataset data = new XYMultipleSeriesDataset();
|
|
||||||
data.addSeries(series);
|
|
||||||
final XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
|
|
||||||
renderer.addSeriesRenderer(new XYSeriesRenderer());
|
|
||||||
final Intent intent = ChartFactory.getLineChartIntent(context, data, renderer);
|
|
||||||
intent.setClass(context, CalculatorPlotActivity.class);
|
intent.setClass(context, CalculatorPlotActivity.class);
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double unwrap(Generic numeric) {
|
|
||||||
if ( numeric instanceof JsclInteger) {
|
|
||||||
return ((JsclInteger) numeric).intValue();
|
|
||||||
} else if ( numeric instanceof NumericWrapper ) {
|
|
||||||
return unwrap(((NumericWrapper) numeric).content());
|
|
||||||
} else {
|
|
||||||
throw new ArithmeticException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double unwrap(Numeric content) {
|
|
||||||
if (content instanceof Real) {
|
|
||||||
return ((Real) content).doubleValue();
|
|
||||||
} else if ( content instanceof Complex) {
|
|
||||||
return ((Complex) content).realPart();
|
|
||||||
} else {
|
|
||||||
throw new ArithmeticException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void createVar(@NotNull final Context context, @NotNull CalculatorModel calculatorModel) {
|
public static void createVar(@NotNull final Context context, @NotNull CalculatorModel calculatorModel) {
|
||||||
if (calculatorModel.getDisplay().isValid() ) {
|
if (calculatorModel.getDisplay().isValid() ) {
|
||||||
final String varValue = calculatorModel.getDisplay().getText().toString();
|
final String varValue = calculatorModel.getDisplay().getText().toString();
|
||||||
|
@ -6,12 +6,262 @@
|
|||||||
|
|
||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import org.achartengine.GraphicalActivity;
|
import android.app.Activity;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.widget.Toast;
|
||||||
|
import jscl.math.Expression;
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import jscl.math.JsclInteger;
|
||||||
|
import jscl.math.NumericWrapper;
|
||||||
|
import jscl.math.function.Constant;
|
||||||
|
import jscl.math.numeric.Complex;
|
||||||
|
import jscl.math.numeric.Numeric;
|
||||||
|
import jscl.math.numeric.Real;
|
||||||
|
import jscl.text.ParseException;
|
||||||
|
import org.achartengine.ChartFactory;
|
||||||
|
import org.achartengine.GraphicalView;
|
||||||
|
import org.achartengine.chart.AbstractChart;
|
||||||
|
import org.achartengine.chart.LineChart;
|
||||||
|
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.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.android.view.widgets.NumberPicker;
|
||||||
|
import org.solovyev.common.utils.MutableObject;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 12/1/11
|
* Date: 12/1/11
|
||||||
* Time: 12:40 AM
|
* Time: 12:40 AM
|
||||||
*/
|
*/
|
||||||
public class CalculatorPlotActivity extends GraphicalActivity{
|
public class CalculatorPlotActivity extends Activity {
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
public static final String INPUT = "org.solovyev.android.calculator.CalculatorPlotActivity_input";
|
||||||
|
|
||||||
|
public static final long EVAL_DELAY_MILLIS = 1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The encapsulated graphical view.
|
||||||
|
*/
|
||||||
|
private GraphicalView graphicalView;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Generic expression;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Constant variable;
|
||||||
|
|
||||||
|
private double minValue = DEFAULT_MIN_NUMBER;
|
||||||
|
|
||||||
|
private double maxValue = DEFAULT_MAX_NUMBER;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
Bundle extras = getIntent().getExtras();
|
||||||
|
|
||||||
|
final Input input = (Input) extras.getSerializable(INPUT);
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.expression = Expression.valueOf(input.getExpression());
|
||||||
|
this.variable = new Constant(input.getVariableName());
|
||||||
|
|
||||||
|
String title = extras.getString(ChartFactory.TITLE);
|
||||||
|
if (title == null) {
|
||||||
|
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||||
|
} else if (title.length() > 0) {
|
||||||
|
setTitle(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
setContentView(R.layout.calc_plot_view);
|
||||||
|
|
||||||
|
setGraphicalView(minValue, maxValue);
|
||||||
|
|
||||||
|
final NumberPicker minXNumberPicker = (NumberPicker)findViewById(R.id.plot_x_min_value);
|
||||||
|
final NumberPicker maxXNumberPicker = (NumberPicker)findViewById(R.id.plot_x_max_value);
|
||||||
|
|
||||||
|
minXNumberPicker.setRange(Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||||
|
minXNumberPicker.setCurrent(DEFAULT_MIN_NUMBER);
|
||||||
|
maxXNumberPicker.setRange(Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||||
|
maxXNumberPicker.setCurrent(DEFAULT_MAX_NUMBER);
|
||||||
|
|
||||||
|
|
||||||
|
minXNumberPicker.setOnChangeListener(new BoundariesChangeListener(true));
|
||||||
|
maxXNumberPicker.setOnChangeListener(new BoundariesChangeListener(false));
|
||||||
|
|
||||||
|
} catch (ParseException e) {
|
||||||
|
Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setGraphicalView(final double minValue, final double maxValue) {
|
||||||
|
final ViewGroup graphContainer = (ViewGroup) findViewById(R.id.plot_graph_container);
|
||||||
|
|
||||||
|
if (graphicalView != null) {
|
||||||
|
graphContainer.removeView(graphicalView);
|
||||||
|
}
|
||||||
|
|
||||||
|
graphicalView = new GraphicalView(this, prepareChart(minValue, maxValue, expression, variable));
|
||||||
|
graphContainer.addView(graphicalView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final static MutableObject<Runnable> pendingOperation = new MutableObject<Runnable>();
|
||||||
|
|
||||||
|
private class BoundariesChangeListener implements NumberPicker.OnChangedListener {
|
||||||
|
|
||||||
|
private boolean min;
|
||||||
|
|
||||||
|
private BoundariesChangeListener(boolean min) {
|
||||||
|
this.min = min;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChanged(NumberPicker picker, int oldVal, final int newVal) {
|
||||||
|
if (min) {
|
||||||
|
minValue = newVal;
|
||||||
|
} else {
|
||||||
|
maxValue = newVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
// actually nothing shall be logged while text operations are done
|
||||||
|
setGraphicalView(CalculatorPlotActivity.this.minValue, CalculatorPlotActivity.this.maxValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
new Handler().postDelayed(pendingOperation.getObject(), EVAL_DELAY_MILLIS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AbstractChart prepareChart(final double minValue, final double maxValue, @NotNull final Generic expression, @NotNull final Constant variable) {
|
||||||
|
final XYSeries realSeries = new XYSeries(expression.toString());
|
||||||
|
final XYSeries imagSeries = new XYSeries("Im(" + expression.toString() + ")");
|
||||||
|
|
||||||
|
boolean imagExists = false;
|
||||||
|
|
||||||
|
final double min = Math.min(minValue, maxValue);
|
||||||
|
final double max = Math.max(minValue, maxValue);
|
||||||
|
final int numberOfSteps = DEFAULT_NUMBER_OF_STEPS;
|
||||||
|
final double step = Math.max((max - min) / numberOfSteps, 0.001);
|
||||||
|
double x = min;
|
||||||
|
while (x <= max) {
|
||||||
|
Generic numeric = expression.substitute(variable, Expression.valueOf(x)).numeric();
|
||||||
|
final Complex c = unwrap(numeric);
|
||||||
|
realSeries.add(x, prepareY(c.realPart()));
|
||||||
|
imagSeries.add(x, prepareY(c.imaginaryPart()));
|
||||||
|
if (c.imaginaryPart() != 0d) {
|
||||||
|
imagExists = true;
|
||||||
|
}
|
||||||
|
x += step;
|
||||||
|
}
|
||||||
|
|
||||||
|
final XYMultipleSeriesDataset data = new XYMultipleSeriesDataset();
|
||||||
|
data.addSeries(realSeries);
|
||||||
|
if (imagExists) {
|
||||||
|
data.addSeries(imagSeries);
|
||||||
|
}
|
||||||
|
|
||||||
|
final XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
|
||||||
|
renderer.setZoomEnabled(false);
|
||||||
|
renderer.setZoomEnabled(false, false);
|
||||||
|
renderer.addSeriesRenderer(createCommonRenderer());
|
||||||
|
renderer.setPanEnabled(false);
|
||||||
|
renderer.setPanEnabled(false, false);
|
||||||
|
if (imagExists) {
|
||||||
|
final XYSeriesRenderer imagRenderer = createCommonRenderer();
|
||||||
|
imagRenderer.setStroke(BasicStroke.DOTTED);
|
||||||
|
renderer.addSeriesRenderer(imagRenderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LineChart(data, renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static XYSeriesRenderer createCommonRenderer() {
|
||||||
|
final XYSeriesRenderer renderer = new XYSeriesRenderer();
|
||||||
|
renderer.setColor(Color.WHITE);
|
||||||
|
renderer.setStroke(BasicStroke.SOLID);
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double prepareY(double y) {
|
||||||
|
if (Double.isNaN(y) || Double.isInfinite(y)) {
|
||||||
|
return 0d;
|
||||||
|
} else {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static Complex unwrap(@Nullable Generic numeric) {
|
||||||
|
if (numeric instanceof JsclInteger) {
|
||||||
|
return Complex.valueOf(((JsclInteger) numeric).intValue(), 0d);
|
||||||
|
} else if (numeric instanceof NumericWrapper) {
|
||||||
|
return unwrap(((NumericWrapper) numeric).content());
|
||||||
|
} else {
|
||||||
|
throw new ArithmeticException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static Complex unwrap(@Nullable Numeric content) {
|
||||||
|
if (content instanceof Real) {
|
||||||
|
return Complex.valueOf(((Real) content).doubleValue(), 0d);
|
||||||
|
} else if (content instanceof Complex) {
|
||||||
|
return ((Complex) content);
|
||||||
|
} else {
|
||||||
|
throw new ArithmeticException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Input implements Serializable {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String expression;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String variableName;
|
||||||
|
|
||||||
|
public Input(@NotNull String expression, @NotNull String variableName) {
|
||||||
|
this.expression = expression;
|
||||||
|
this.variableName = variableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public String getExpression() {
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public String getVariableName() {
|
||||||
|
return variableName;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
package org.solovyev.android.calculator.jscl;
|
package org.solovyev.android.calculator.jscl;
|
||||||
|
|
||||||
import jscl.text.Messages;
|
import jscl.text.msg.Messages;
|
||||||
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.math.MathType;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
|
@ -29,6 +29,8 @@ public class AutoResizeTextView extends TextView {
|
|||||||
// Minimum text size for this text view
|
// Minimum text size for this text view
|
||||||
public static final float MIN_TEXT_SIZE = 20;
|
public static final float MIN_TEXT_SIZE = 20;
|
||||||
|
|
||||||
|
private float initialTextSize = 100;
|
||||||
|
|
||||||
// Interface for resize notifications
|
// Interface for resize notifications
|
||||||
public interface OnTextResizeListener {
|
public interface OnTextResizeListener {
|
||||||
public void onTextResize(TextView textView, float oldSize, float newSize);
|
public void onTextResize(TextView textView, float oldSize, float newSize);
|
||||||
@ -207,7 +209,8 @@ public class AutoResizeTextView extends TextView {
|
|||||||
Log.d(this.getClass().getName(), "Old text size: " + oldTextSize);
|
Log.d(this.getClass().getName(), "Old text size: " + oldTextSize);
|
||||||
|
|
||||||
// If there is a max text size set, use the lesser of that and the default text size
|
// If there is a max text size set, use the lesser of that and the default text size
|
||||||
float newTextSize = 100;
|
// todo serso: +2 is a workaround => to be checked boundary constraints
|
||||||
|
float newTextSize = initialTextSize + 2;
|
||||||
|
|
||||||
int newTextHeight;
|
int newTextHeight;
|
||||||
|
|
||||||
@ -227,7 +230,7 @@ public class AutoResizeTextView extends TextView {
|
|||||||
if (newTextSize <= minTextSize) {
|
if (newTextSize <= minTextSize) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
newTextSize = Math.max(newTextSize - 2, minTextSize);
|
newTextSize = Math.max(newTextSize - 1, minTextSize);
|
||||||
newTextHeight = getTextRect(text, textPaint, width, newTextSize);
|
newTextHeight = getTextRect(text, textPaint, width, newTextSize);
|
||||||
logDimensions(newTextSize, newTextHeight);
|
logDimensions(newTextSize, newTextHeight);
|
||||||
}
|
}
|
||||||
@ -236,7 +239,7 @@ public class AutoResizeTextView extends TextView {
|
|||||||
if (newTextSize <= minTextSize) {
|
if (newTextSize <= minTextSize) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
newTextSize = Math.max(newTextSize + 2, minTextSize);
|
newTextSize = Math.max(newTextSize + 1, minTextSize);
|
||||||
newTextHeight = getTextRect(text, textPaint, width, newTextSize);
|
newTextHeight = getTextRect(text, textPaint, width, newTextSize);
|
||||||
logDimensions(newTextSize, newTextHeight);
|
logDimensions(newTextSize, newTextHeight);
|
||||||
}
|
}
|
||||||
@ -247,6 +250,8 @@ public class AutoResizeTextView extends TextView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initialTextSize = newTextSize;
|
||||||
|
|
||||||
// If we had reached our minimum text size and still don't fit, append an ellipsis
|
// If we had reached our minimum text size and still don't fit, append an ellipsis
|
||||||
if (addEllipsis && newTextSize == minTextSize && newTextHeight > height) {
|
if (addEllipsis && newTextSize == minTextSize && newTextHeight > height) {
|
||||||
// Draw using a static layout
|
// Draw using a static layout
|
||||||
|
@ -7,11 +7,14 @@
|
|||||||
package org.solovyev.android.view.prefs;
|
package org.solovyev.android.view.prefs;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
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.CalculatorActivity;
|
||||||
import org.solovyev.android.view.widgets.DragButton;
|
import org.solovyev.android.view.widgets.DragButton;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
@ -33,7 +36,13 @@ public enum ResourceCache {
|
|||||||
// ids of buttons in R.class
|
// ids of buttons in R.class
|
||||||
private List<Integer> buttonIds = null;
|
private List<Integer> buttonIds = null;
|
||||||
|
|
||||||
private static final Map<String, Map<String, String>> captions = new HashMap<String, Map<String, String>>();
|
// first map: key: language id, value: map of captions and translations
|
||||||
|
// second mal: key: caption id, value: translation
|
||||||
|
private final Map<String, Map<String, String>> captions = new HashMap<String, Map<String, String>>();
|
||||||
|
|
||||||
|
private Class<?> resourceClass;
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
|
||||||
public List<Integer> getDragButtonIds() {
|
public List<Integer> getDragButtonIds() {
|
||||||
return dragButtonIds;
|
return dragButtonIds;
|
||||||
@ -43,11 +52,28 @@ public enum ResourceCache {
|
|||||||
return buttonIds;
|
return buttonIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initCaptions(@NotNull Class<?> resourceClass, @NotNull Activity activity) {
|
/**
|
||||||
final Locale locale = Locale.getDefault();
|
* Method load captions for default locale using android R class
|
||||||
|
* @param context STATIC CONTEXT
|
||||||
|
* @param resourceClass class of captions in android (SUBCLASS of R class)
|
||||||
|
*/
|
||||||
|
public void initCaptions(@NotNull Context context, @NotNull Class<?> resourceClass) {
|
||||||
|
initCaptions(context, resourceClass, Locale.getDefault());
|
||||||
|
}
|
||||||
|
|
||||||
if (!captions.containsKey(locale.getLanguage())) {
|
/**
|
||||||
|
* Method load captions for specified locale using android R class
|
||||||
|
* @param context STATIC CONTEXT
|
||||||
|
* @param resourceClass class of captions in android (SUBCLASS of R class)
|
||||||
|
* @param locale language to be used for translation
|
||||||
|
*/
|
||||||
|
public void initCaptions(@NotNull Context context, @NotNull Class<?> resourceClass, @NotNull Locale locale) {
|
||||||
|
assert this.resourceClass == null || this.resourceClass.equals(resourceClass);
|
||||||
|
|
||||||
|
this.context = context;
|
||||||
|
this.resourceClass = resourceClass;
|
||||||
|
|
||||||
|
if (!initialized(locale)) {
|
||||||
final Map<String, String> captionsByLanguage = new HashMap<String, String>();
|
final Map<String, String> captionsByLanguage = new HashMap<String, String>();
|
||||||
|
|
||||||
for (Field field : resourceClass.getDeclaredFields()) {
|
for (Field field : resourceClass.getDeclaredFields()) {
|
||||||
@ -55,7 +81,7 @@ public enum ResourceCache {
|
|||||||
if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) {
|
if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) {
|
||||||
try {
|
try {
|
||||||
int captionId = field.getInt(resourceClass);
|
int captionId = field.getInt(resourceClass);
|
||||||
captionsByLanguage.put(field.getName(), activity.getString(captionId));
|
captionsByLanguage.put(field.getName(), context.getString(captionId));
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
Log.e(ResourceCache.class.getName(), e.getMessage());
|
Log.e(ResourceCache.class.getName(), e.getMessage());
|
||||||
}
|
}
|
||||||
@ -66,13 +92,39 @@ public enum ResourceCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean initialized(@NotNull Locale locale) {
|
||||||
|
return captions.containsKey(locale.getLanguage());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param captionId id of caption to be translated
|
||||||
|
* @return translation by caption id in default language, null if no translation in default language present
|
||||||
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public String getCaption(@NotNull String captionId) {
|
public String getCaption(@NotNull String captionId) {
|
||||||
final Locale locale = Locale.getDefault();
|
return getCaption(captionId, Locale.getDefault());
|
||||||
|
}
|
||||||
|
|
||||||
final Map<String, String> captionsByLanguage = captions.get(locale.getLanguage());
|
|
||||||
|
/**
|
||||||
|
* @param captionId id of caption to be translated
|
||||||
|
* @param locale language to be used for translation
|
||||||
|
* @return translation by caption id in specified language, null if no translation in specified language present
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getCaption(@NotNull String captionId, @NotNull final Locale locale) {
|
||||||
|
Map<String, String> captionsByLanguage = captions.get(locale.getLanguage());
|
||||||
if (captionsByLanguage != null) {
|
if (captionsByLanguage != null) {
|
||||||
return captionsByLanguage.get(captionId);
|
return captionsByLanguage.get(captionId);
|
||||||
|
} else {
|
||||||
|
assert resourceClass != null && context != null;
|
||||||
|
|
||||||
|
initCaptions(context, resourceClass, locale);
|
||||||
|
|
||||||
|
captionsByLanguage = captions.get(locale.getLanguage());
|
||||||
|
if (captionsByLanguage != null) {
|
||||||
|
return captionsByLanguage.get(captionId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -412,7 +412,7 @@ public class NumberPicker extends LinearLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final char[] DIGIT_CHARACTERS = new char[] {
|
private static final char[] DIGIT_CHARACTERS = new char[] {
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
|
'-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
|
||||||
};
|
};
|
||||||
|
|
||||||
private NumberPickerButton mIncrementButton;
|
private NumberPickerButton mIncrementButton;
|
||||||
|
Loading…
Reference in New Issue
Block a user