preferences added

This commit is contained in:
serso 2011-09-26 23:46:47 +04:00
parent e81a1ef27b
commit 769d8068f2
27 changed files with 404 additions and 133 deletions

View File

@ -12,4 +12,10 @@
<string name="p_drag_angle">0;45</string>
<string name="p_drag_duration_key">org.solovyev.android.calculator.DragButtonCalibrationActivity_duration</string>
<string name="p_drag_duration">40;2500</string>
<string name="p_calc_result_precision_key">org.solovyev.android.calculator.CalculatorModel_result_precision</string>
<string name="p_calc_result_precision">5</string>
<string name="p_calc_color_display_key">org.solovyev.android.calculator.CalculatorModel_color_display</string>
<string name="p_calc_color_display">true</string>
</resources>

View File

@ -4,14 +4,16 @@
xmlns:range="http://schemas.android.com/apk/res/org.solovyev.android.calculator">
<PreferenceCategory a:title="@string/c_prefs_drag_button_category">
<org.solovyev.android.view.prefs.SeekBarPreference a:key="duration"
a:title="Duration of something"
a:summary="How long something will last"
a:dialogMessage="Something duration"
<org.solovyev.android.view.prefs.NumberPickerDialogPreference
a:key="@string/p_calc_result_precision_key"
a:title="Precision of result value"
a:defaultValue="5"
a:text=" minutes"
a:max="60"/>
range:boundaries="0;10"/>
<android.preference.CheckBoxPreference
a:key="@string/p_calc_color_display_key"
a:title="Highlight expressions in brackets"
a:defaultValue="true"/>
<org.solovyev.android.view.prefs.FloatRangeSeekBarPreference
a:key="@string/p_drag_distance_key"

View File

@ -20,6 +20,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.view.FontSizeAdjuster;
import org.solovyev.android.view.widgets.*;
import org.solovyev.common.BooleanMapper;
import org.solovyev.common.NumberMapper;
import org.solovyev.common.utils.Announcer;
import org.solovyev.common.utils.history.HistoryAction;
@ -104,7 +106,10 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
registerReceiver(preferencesChangesReceiver, new IntentFilter(DragButtonCalibrationActivity.INTENT_ACTION));
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
final SharedPreferences defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
defaultSharedPreferences.registerOnSharedPreferenceChangeListener(this);
this.onSharedPreferenceChanged(defaultSharedPreferences, null);
}
@Override
@ -236,5 +241,12 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
dpclRegister.announce().onDragPreferencesChange(DragButtonCalibrationActivity.getPreferences(CalculatorActivity.this));
final NumberMapper<Integer> integerNumberMapper = new NumberMapper<Integer>(Integer.class);
this.calculatorModel.setNumberOfFractionDigits(integerNumberMapper.parseValue(sharedPreferences.getString(this.getString(R.string.p_calc_result_precision_key), this.getString(R.string.p_calc_result_precision))));
final Boolean colorExpressionsInBracketsDefault = new BooleanMapper().parseValue(this.getString(R.string.p_calc_color_display));
assert colorExpressionsInBracketsDefault != null;
this.calculatorView.getEditor().setHighlightExpressionInBrackets(sharedPreferences.getBoolean(this.getString(R.string.p_calc_color_display_key), colorExpressionsInBracketsDefault));
}
}

View File

@ -22,6 +22,7 @@ import org.solovyev.android.calculator.math.MathEntityType;
*/
public class CalculatorEditText extends EditText {
private boolean highlightExpressionInBrackets = true;
public CalculatorEditText(Context context) {
super(context);
@ -42,9 +43,12 @@ public class CalculatorEditText extends EditText {
public void redraw() {
String text = getText().toString();
int selectionStart = getSelectionStart();
int selectionEnd = getSelectionEnd();
if (highlightExpressionInBrackets) {
int maxNumberOfOpenGroupSymbols = 0;
int numberOfOpenGroupSymbols = 0;
for (int i = 0; i < text.length(); i++) {
@ -69,6 +73,9 @@ public class CalculatorEditText extends EditText {
} else {
super.setText(text, BufferType.EDITABLE);
}
} else {
super.setText(text, BufferType.EDITABLE);
}
setSelection(selectionStart, selectionEnd);
}
@ -106,10 +113,19 @@ public class CalculatorEditText extends EditText {
double c = 1;
int i = ((int)(255 * c)) * numberOfOpenings / (numberOfOpenGroupSymbols + 1);
int i = ((int) (255 * c)) * numberOfOpenings / (numberOfOpenGroupSymbols + 1);
int result = Color.rgb( Color.red(baseColor) - i, Color.green(baseColor) - i, Color.blue(baseColor) - i);
int result = Color.rgb(Color.red(baseColor) - i, Color.green(baseColor) - i, Color.blue(baseColor) - i);
return "#" + Integer.toHexString(result).substring(2);
}
public boolean isHighlightExpressionInBrackets() {
return highlightExpressionInBrackets;
}
public void setHighlightExpressionInBrackets(boolean highlightExpressionInBrackets) {
this.highlightExpressionInBrackets = highlightExpressionInBrackets;
redraw();
}
}

View File

@ -23,7 +23,7 @@ public class CalculatorModel {
@NotNull
private Interpreter interpreter;
private int NUMBER_OF_FRACTION_DIGITS = 5;
private int numberOfFractionDigits = 5;
@NotNull
public Preprocessor preprocessor = new ToJsclPreprocessor();
@ -96,7 +96,7 @@ public class CalculatorModel {
private Double round(@NotNull String result) {
final Double dResult = Double.valueOf(result);
return MathUtils.round(dResult, NUMBER_OF_FRACTION_DIGITS);
return MathUtils.round(dResult, numberOfFractionDigits);
}
public static class ParseException extends SersoException {
@ -105,4 +105,11 @@ public class CalculatorModel {
}
}
public int getNumberOfFractionDigits() {
return numberOfFractionDigits;
}
public void setNumberOfFractionDigits(int numberOfFractionDigits) {
this.numberOfFractionDigits = numberOfFractionDigits;
}
}

View File

@ -285,4 +285,9 @@ public class CalculatorView implements CursorControl, HistoryControl<CalculatorH
return result;
}
@NotNull
public CalculatorEditText getEditor() {
return editor;
}
}

View File

@ -19,7 +19,7 @@ import android.view.View;
import android.widget.ImageView;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.view.widgets.*;
import org.solovyev.common.FloatIntervalMapper;
import org.solovyev.common.NumberIntervalMapper;
import org.solovyev.common.collections.ManyValuedHashMap;
import org.solovyev.common.collections.ManyValuedMap;
import org.solovyev.common.utils.*;
@ -178,7 +178,7 @@ public class DragButtonCalibrationActivity extends Activity {
}
private void setPreferences(@NotNull Map<DragDirection, MathUtils.StatData> statData, @NotNull SharedPreferences.Editor editor, @NotNull PreferenceType preferenceType) {
final Mapper<Interval<Float>> mapper = new FloatIntervalMapper();
final Mapper<Interval<Float>> mapper = new NumberIntervalMapper<Float>(Float.class);
for (Map.Entry<DragDirection, MathUtils.StatData> entry : statData.entrySet()) {
final float min = (float) entry.getValue().getMean() - 2 * (float) entry.getValue().getStandardDeviation();
final float max = (float) entry.getValue().getMean() + 2 * (float) entry.getValue().getStandardDeviation();
@ -195,7 +195,7 @@ public class DragButtonCalibrationActivity extends Activity {
public static Preferences getPreferences(@NotNull Context context) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
final Mapper<Interval<Float>> mapper = new FloatIntervalMapper();
final Mapper<Interval<Float>> mapper = new NumberIntervalMapper<Float>(Float.class);
final Preferences result = new Preferences();

View File

@ -22,10 +22,11 @@ public class EditorHistoryState {
this.text = text;
}
public void setText(String text) {
public void setText(@Nullable String text) {
this.text = text;
}
@Nullable
public String getText() {
return text;
}

View File

@ -1,6 +1,7 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.android.calculator;

View File

@ -1,7 +1,12 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.android.calculator.math;
import jscl.math.Generic;
import jscl.math.JSCLInteger;
import jscl.math.NotIntegrableException;
import jscl.math.Variable;
import jscl.math.function.Function;

View File

@ -3,6 +3,7 @@ package org.solovyev.android.view.prefs;
import android.content.Context;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;
@ -19,7 +20,10 @@ import org.solovyev.common.utils.Mapper;
public abstract class AbstractDialogPreference<T> extends DialogPreference {
@NotNull
protected static final String androidns = "http://schemas.android.com/apk/res/android";
protected final static String localNameSpace = "http://schemas.android.com/apk/res/org.solovyev.android.calculator";
@NotNull
protected final static String androidns = "http://schemas.android.com/apk/res/android";
@NotNull
protected TextView valueTextView;
@ -127,21 +131,29 @@ public abstract class AbstractDialogPreference<T> extends DialogPreference {
}
protected void persistValue(@Nullable T value) {
Log.d(AbstractDialogPreference.class.getName(), "Trying to persist value: " + value);
this.value = value;
Log.d(AbstractDialogPreference.class.getName(), "android.preference.Preference.callChangeListener()");
if (callChangeListener(value)) {
Log.d(AbstractDialogPreference.class.getName(), "android.preference.Preference.shouldPersist()");
if (shouldPersist()) {
Log.d(AbstractDialogPreference.class.getName(), "org.solovyev.android.view.prefs.AbstractDialogPreference.persist()");
persist(value);
}
}
}
private void persist(@Nullable T value) {
if (value != null) {
final String toBePersistedString = getMapper().formatValue(value);
if (toBePersistedString != null) {
if ( callChangeListener(value) ) {
if ( callChangeListener(toBePersistedString) ) {
persistString(toBePersistedString);
}
}
}
}
@NotNull
protected abstract Mapper<T> getMapper();

View File

@ -9,7 +9,7 @@ package org.solovyev.android.view.prefs;
import android.content.Context;
import android.util.AttributeSet;
import org.jetbrains.annotations.NotNull;
import org.solovyev.common.FloatIntervalMapper;
import org.solovyev.common.NumberIntervalMapper;
import org.solovyev.common.utils.Interval;
import org.solovyev.common.utils.Mapper;
@ -27,6 +27,6 @@ public class FloatRangeSeekBarPreference extends RangeSeekBarPreference<Float> {
@NotNull
@Override
protected Mapper<Interval<Float>> getMapper() {
return new FloatIntervalMapper() ;
return new NumberIntervalMapper<Float>(Float.class);
}
}

View File

@ -9,7 +9,7 @@ package org.solovyev.android.view.prefs;
import android.content.Context;
import android.util.AttributeSet;
import org.jetbrains.annotations.NotNull;
import org.solovyev.common.IntegerIntervalMapper;
import org.solovyev.common.NumberIntervalMapper;
import org.solovyev.common.utils.*;
/**
@ -26,7 +26,7 @@ public class IntegerRangeSeekBarPreference extends RangeSeekBarPreference<Intege
@NotNull
@Override
protected Mapper<Interval<Integer>> getMapper() {
return new IntegerIntervalMapper();
return new NumberIntervalMapper<Integer>(Integer.class);
}
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.android.view.prefs;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.LinearLayout;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.view.widgets.NumberPicker;
import org.solovyev.common.GenericIntervalMapper;
import org.solovyev.common.utils.Interval;
import org.solovyev.common.utils.Mapper;
/**
* User: serso
* Date: 9/26/11
* Time: 10:31 PM
*/
public class NumberPickerDialogPreference extends AbstractDialogPreference<Integer> implements NumberPicker.OnChangedListener {
@NotNull
private NumberPicker numberPicker;
@NotNull
private final Interval<Integer> boundaries;
public NumberPickerDialogPreference(Context context, AttributeSet attrs) {
super(context, attrs, null);
//noinspection ConstantConditions
boundaries = new GenericIntervalMapper<Integer>(getMapper()).parseValue(attrs.getAttributeValue(localNameSpace, "boundaries"));
createPreferenceView();
}
@NotNull
@Override
protected LinearLayout onCreateDialogView() {
final LinearLayout result = super.onCreateDialogView();
createPreferenceView();
initPreferenceView();
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;
result.addView(numberPicker, params);
return result;
}
protected void createPreferenceView() {
this.numberPicker = new NumberPicker(context);
this.numberPicker.setOnChangeListener(this);
initPreferenceView();
}
@Override
protected void initPreferenceView() {
if (value != null) {
numberPicker.setRange(boundaries.getLeftBorder(), boundaries.getRightBorder());
numberPicker.setCurrent(value);
}
}
@NotNull
@Override
protected Mapper<Integer> getMapper() {
return new Mapper<Integer>() {
@Override
public String formatValue(@Nullable Integer value) throws IllegalArgumentException {
return String.valueOf(value);
}
@Override
public Integer parseValue(@Nullable String value) throws IllegalArgumentException {
return Integer.valueOf(value);
}
};
}
@Override
public void onChanged(NumberPicker picker, int oldVal, int newVal) {
persistValue(newVal);
}
}

View File

@ -16,8 +16,6 @@ import org.solovyev.common.utils.NumberInterval;
*/
public abstract class RangeSeekBarPreference<T extends Number> extends AbstractDialogPreference<Interval<T>> implements AbstractRangeSeekBar.OnRangeSeekBarChangeListener<T> {
public final static String localNameSpace = "http://schemas.android.com/apk/res/org.solovyev.android.calculator";
@NotNull
private AbstractRangeSeekBar<T> rangeSeekBar;

View File

@ -11,7 +11,7 @@ import android.util.AttributeSet;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.common.NumberMapper;
import org.solovyev.common.utils.Mapper;
@ -60,17 +60,7 @@ public class SeekBarPreference extends AbstractDialogPreference<Integer> impleme
@NotNull
@Override
protected Mapper<Integer> getMapper() {
return new Mapper<Integer>() {
@Override
public String formatValue(@Nullable Integer integer) throws IllegalArgumentException {
return integer == null ? null : String.valueOf(integer);
}
@Override
public Integer parseValue(@Nullable String s) throws IllegalArgumentException {
return s == null ? null : Integer.valueOf(s);
}
};
return new NumberMapper<Integer>(Integer.class);
}
public void onProgressChanged(SeekBar seek, int value, boolean fromTouch) {

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.common;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.common.math.ValueOfFormatter;
import org.solovyev.common.utils.Formatter;
import org.solovyev.common.utils.Mapper;
/**
* User: serso
* Date: 9/26/11
* Time: 11:27 PM
*/
public class BooleanMapper implements Mapper<Boolean>{
@NotNull
private final Formatter<Boolean> formatter = new ValueOfFormatter<Boolean>();
@Override
public String formatValue(@Nullable Boolean value) throws IllegalArgumentException {
return formatter.formatValue(value);
}
@Override
public Boolean parseValue(@Nullable String value) throws IllegalArgumentException {
return value == null ? null : Boolean.valueOf(value);
}
}

View File

@ -1,37 +0,0 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.common;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.common.math.ValueOfFormatter;
import org.solovyev.common.utils.Formatter;
import org.solovyev.common.utils.Parser;
/**
* User: serso
* Date: 9/21/11
* Time: 12:06 AM
*/
public class FloatIntervalMapper extends AbstractIntervalMapper<Float> {
@NotNull
@Override
protected Formatter<Float> getFormatter() {
return new ValueOfFormatter<Float>();
}
@NotNull
@Override
protected Parser<Float> getParser() {
return new Parser<Float>() {
@Override
public Float parseValue(@Nullable String s) throws IllegalArgumentException {
return Float.valueOf(s);
}
};
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.common;
import org.jetbrains.annotations.NotNull;
import org.solovyev.common.utils.Formatter;
import org.solovyev.common.utils.Mapper;
import org.solovyev.common.utils.Parser;
/**
* User: serso
* Date: 9/26/11
* Time: 10:45 PM
*/
public class GenericIntervalMapper<T> extends AbstractIntervalMapper<T> {
@NotNull
private final Mapper<T> mapper;
public GenericIntervalMapper(@NotNull Mapper<T> mapper) {
this.mapper = mapper;
}
@NotNull
@Override
protected Formatter<T> getFormatter() {
return mapper;
}
@NotNull
@Override
protected Parser<T> getParser() {
return mapper;
}
}

View File

@ -1,35 +0,0 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.common;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.common.math.ValueOfFormatter;
import org.solovyev.common.utils.*;
/**
* User: serso
* Date: 9/20/11
* Time: 11:56 PM
*/
public class IntegerIntervalMapper extends AbstractIntervalMapper<Integer> {
@NotNull
protected Formatter<Integer> getFormatter() {
return new ValueOfFormatter<Integer>();
}
@NotNull
protected Parser<Integer> getParser() {
return new Parser<Integer>() {
@Override
public Integer parseValue(@Nullable String s) throws IllegalArgumentException {
return Integer.valueOf(s);
}
};
}
}

View File

@ -0,0 +1,21 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.common;
import org.jetbrains.annotations.NotNull;
/**
* User: serso
* Date: 9/20/11
* Time: 11:56 PM
*/
public class NumberIntervalMapper<T extends Number> extends GenericIntervalMapper<T> {
public NumberIntervalMapper(@NotNull Class<T> clazz) {
super(new NumberMapper<T>(clazz));
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.common;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.common.math.ValueOfFormatter;
import org.solovyev.common.utils.Formatter;
import org.solovyev.common.utils.Mapper;
import org.solovyev.common.utils.Parser;
/**
* User: serso
* Date: 9/26/11
* Time: 11:10 PM
*/
public class NumberMapper<T extends Number> implements Mapper<T>{
@NotNull
private final Formatter<T> formatter = new ValueOfFormatter<T>();
@NotNull
private final Parser<T> parser;
public NumberMapper(@NotNull Class<T> clazz) {
this.parser = new NumberParser<T>(clazz);
}
@Override
public String formatValue(@Nullable T value) throws IllegalArgumentException {
return formatter.formatValue(value);
}
@Override
public T parseValue(@Nullable String value) throws IllegalArgumentException {
return this.parser.parseValue(value);
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.common;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.common.utils.Parser;
/**
* User: serso
* Date: 9/26/11
* Time: 11:07 PM
*/
public class NumberParser<T extends Number> implements Parser<T> {
@NotNull
private final Class<T> clazz;
public NumberParser(@NotNull Class<T> clazz) {
this.clazz = clazz;
}
@Override
public T parseValue(@Nullable String value) throws IllegalArgumentException {
T result;
if (value != null) {
if (this.clazz.equals(Integer.class)) {
result = (T) Integer.valueOf(value);
} else if (this.clazz.equals(Float.class)) {
result = (T) Float.valueOf(value);
} else {
throw new UnsupportedOperationException(this.clazz + " is not supported!");
}
} else {
result = null;
}
return result;
}
}

View File

@ -16,8 +16,19 @@ import org.solovyev.common.utils.Formatter;
*/
public class ValueOfFormatter<T> implements Formatter<T>{
private final boolean processNulls;
public ValueOfFormatter() {
this(false);
}
public ValueOfFormatter(boolean processNulls) {
this.processNulls = processNulls;
}
@Override
public String formatValue(@Nullable T t) throws IllegalArgumentException {
return String.valueOf(t);
return t == null ? (processNulls ? String.valueOf(t) : null) : String.valueOf(t);
}
}

View File

@ -5,10 +5,6 @@
package org.solovyev.android.calculator;
import de.congrace.exp4j.Calculable;
import de.congrace.exp4j.ExpressionBuilder;
import de.congrace.exp4j.UnknownFunctionException;
import de.congrace.exp4j.UnparsableExpressionException;
import org.junit.Assert;
import org.junit.Test;

View File

@ -1,3 +1,9 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.android.calculator;
import org.junit.Assert;

View File

@ -2,7 +2,9 @@ package org.solovyev.common;
import junit.framework.Assert;
import org.junit.Test;
import org.solovyev.common.utils.Interval;
import org.solovyev.common.utils.IntervalImpl;
import org.solovyev.common.utils.Mapper;
/**
* User: serso
@ -13,7 +15,7 @@ public class FloatIntervalMapperTest {
@Test
public void testParse() throws Exception {
final FloatIntervalMapper mapper = new FloatIntervalMapper();
final Mapper<Interval<Float>> mapper = new NumberIntervalMapper<Float>(Float.class);
Assert.assertEquals(new IntervalImpl<Float>(1.2f, 12.2f), mapper.parseValue("1.2;12.2"));
Assert.assertEquals(new IntervalImpl<Float>(0f, 0f), mapper.parseValue("0;0"));