Number format preferences screen

This commit is contained in:
serso 2016-05-04 23:39:46 +02:00
parent 49ab48a44c
commit eb1c733153
15 changed files with 358 additions and 239 deletions

View File

@ -22,35 +22,12 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes; import android.support.annotation.StringRes;
import android.text.TextUtils; import android.text.TextUtils;
import com.squareup.otto.Bus; import com.squareup.otto.Bus;
import org.solovyev.android.Check;
import org.solovyev.android.calculator.functions.FunctionsRegistry;
import org.solovyev.android.calculator.operators.OperatorsRegistry;
import org.solovyev.android.calculator.operators.PostfixFunctionsRegistry;
import org.solovyev.android.prefs.BooleanPreference;
import org.solovyev.android.prefs.CharacterPreference;
import org.solovyev.android.prefs.IntegerPreference;
import org.solovyev.android.prefs.Preference;
import org.solovyev.android.prefs.StringPreference;
import org.solovyev.common.NumberFormatter;
import org.solovyev.common.text.EnumMapper;
import org.solovyev.common.text.NumberMapper;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import jscl.AngleUnit; import jscl.AngleUnit;
import jscl.JsclMathEngine; import jscl.JsclMathEngine;
import jscl.MathEngine; import jscl.MathEngine;
@ -59,6 +36,25 @@ import jscl.math.operator.Operator;
import jscl.text.Identifier; import jscl.text.Identifier;
import jscl.text.Parser; import jscl.text.Parser;
import midpcalc.Real; import midpcalc.Real;
import org.solovyev.android.Check;
import org.solovyev.android.calculator.functions.FunctionsRegistry;
import org.solovyev.android.calculator.operators.OperatorsRegistry;
import org.solovyev.android.calculator.operators.PostfixFunctionsRegistry;
import org.solovyev.android.calculator.preferences.PreferenceEntry;
import org.solovyev.android.prefs.*;
import org.solovyev.common.text.CharacterMapper;
import org.solovyev.common.NumberFormatter;
import org.solovyev.common.text.EnumMapper;
import org.solovyev.common.text.NumberMapper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;
@Singleton @Singleton
public class Engine implements SharedPreferences.OnSharedPreferenceChangeListener { public class Engine implements SharedPreferences.OnSharedPreferenceChangeListener {
@ -98,13 +94,6 @@ public class Engine implements SharedPreferences.OnSharedPreferenceChangeListene
this.mathEngine.setGroupingSeparator(JsclMathEngine.GROUPING_SEPARATOR_DEFAULT); this.mathEngine.setGroupingSeparator(JsclMathEngine.GROUPING_SEPARATOR_DEFAULT);
} }
private static void migratePreference(@Nonnull SharedPreferences preferences, @Nonnull BooleanPreference preference, @Nonnull String oldKey, @Nonnull SharedPreferences.Editor editor) {
if (!preferences.contains(oldKey)) {
return;
}
editor.putBoolean(preference.getKey(), preferences.getBoolean(oldKey, false));
}
private static void migratePreference(@Nonnull SharedPreferences preferences, @Nonnull StringPreference<?> preference, @Nonnull String oldKey, @Nonnull SharedPreferences.Editor editor) { private static void migratePreference(@Nonnull SharedPreferences preferences, @Nonnull StringPreference<?> preference, @Nonnull String oldKey, @Nonnull SharedPreferences.Editor editor) {
if (!preferences.contains(oldKey)) { if (!preferences.contains(oldKey)) {
return; return;
@ -112,15 +101,6 @@ public class Engine implements SharedPreferences.OnSharedPreferenceChangeListene
editor.putString(preference.getKey(), preferences.getString(oldKey, null)); editor.putString(preference.getKey(), preferences.getString(oldKey, null));
} }
private static void migratePreference(@Nonnull SharedPreferences preferences, @Nonnull CharacterPreference preference, @Nonnull String oldKey, @Nonnull SharedPreferences.Editor editor) {
if (!preferences.contains(oldKey)) {
return;
}
final String s = preferences.getString(oldKey, null);
editor.putInt(preference.getKey(), TextUtils.isEmpty(s) ? 0 : s.charAt(0));
}
public static boolean isValidName(@Nullable String name) { public static boolean isValidName(@Nullable String name) {
if (!TextUtils.isEmpty(name)) { if (!TextUtils.isEmpty(name)) {
try { try {
@ -261,7 +241,7 @@ public class Engine implements SharedPreferences.OnSharedPreferenceChangeListene
} }
} }
public enum Notation { public enum Notation implements PreferenceEntry {
dec(Real.NumberFormat.FSE_NONE, R.string.cpp_number_format_dec), dec(Real.NumberFormat.FSE_NONE, R.string.cpp_number_format_dec),
eng(Real.NumberFormat.FSE_ENG, R.string.cpp_number_format_eng), eng(Real.NumberFormat.FSE_ENG, R.string.cpp_number_format_eng),
sci(Real.NumberFormat.FSE_SCI, R.string.cpp_number_format_sci); sci(Real.NumberFormat.FSE_SCI, R.string.cpp_number_format_sci);
@ -274,6 +254,18 @@ public class Engine implements SharedPreferences.OnSharedPreferenceChangeListene
this.id = id; this.id = id;
this.name = name; this.name = name;
} }
@NonNull
@Override
public CharSequence getName(@NonNull Context context) {
return context.getString(name);
}
@NonNull
@Override
public CharSequence getId() {
return name();
}
} }
public static class ChangedEvent { public static class ChangedEvent {
@ -307,7 +299,7 @@ public class Engine implements SharedPreferences.OnSharedPreferenceChangeListene
public static class Output { public static class Output {
public static final StringPreference<Integer> precision = StringPreference.ofTypedValue("engine.output.precision", "5", NumberMapper.of(Integer.class)); public static final StringPreference<Integer> precision = StringPreference.ofTypedValue("engine.output.precision", "5", NumberMapper.of(Integer.class));
public static final StringPreference<Notation> notation = StringPreference.ofEnum("engine.output.notation", Notation.dec, Notation.class); public static final StringPreference<Notation> notation = StringPreference.ofEnum("engine.output.notation", Notation.dec, Notation.class);
public static final CharacterPreference separator = CharacterPreference.of("engine.output.separator", JsclMathEngine.GROUPING_SEPARATOR_DEFAULT); public static final StringPreference<Character> separator = StringPreference.ofTypedValue("engine.output.separator", JsclMathEngine.GROUPING_SEPARATOR_DEFAULT, CharacterMapper.INSTANCE);
} }
} }
} }

View File

@ -0,0 +1,59 @@
package org.solovyev.android.calculator.preferences;
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import jscl.JsclMathEngine;
import org.solovyev.android.material.preferences.Preference;
@SuppressWarnings("unused")
public class NumberFormatExamplesPreference extends Preference {
public NumberFormatExamplesPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public NumberFormatExamplesPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public NumberFormatExamplesPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NumberFormatExamplesPreference(Context context) {
super(context);
}
public void update(JsclMathEngine engine) {
final StringBuilder examples = new StringBuilder();
examples.append(" 1/3 = ").append(engine.format(1d / 3)).append("\n");
examples.append(" √2 = ").append(engine.format(Math.sqrt(2d))).append("\n");
examples.append("\n");
examples.append(" 1000 = ").append(engine.format(1000d)).append("\n");
examples.append(" 1000000 = ").append(engine.format(1000000d)).append("\n");
examples.append(" 11^10 = ").append(engine.format(Math.pow(11d, 10))).append("\n");
examples.append(" 10^24 = ").append(engine.format(Math.pow(10d, 24))).append("\n");
examples.append("\n");
examples.append(" 0.001 = ").append(engine.format(0.001d)).append("\n");
examples.append("0.000001 = ").append(engine.format(0.000001d)).append("\n");
examples.append(" 11^10 = ").append(engine.format(Math.pow(11d, -10))).append("\n");
examples.append(" 10^24 = ").append(engine.format(Math.pow(10d, -24)));
setSummary(examples);
}
@Override
protected View onCreateView(ViewGroup parent) {
final View view = super.onCreateView(parent);
final View summary = view.findViewById(android.R.id.summary);
if (summary instanceof TextView) {
final TextView textView = (TextView) summary;
textView.setMaxLines(12);
textView.setLines(12);
textView.setTypeface(Typeface.MONOSPACE);
}
return view;
}
}

View File

@ -1,119 +0,0 @@
package org.solovyev.android.calculator.preferences;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.preference.DialogPreference;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.Engine;
import org.solovyev.android.calculator.Named;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.text.NaturalComparator;
import org.solovyev.android.views.DiscreteSeekBar;
import org.solovyev.common.NumberFormatter;
import butterknife.Bind;
import butterknife.ButterKnife;
import static org.solovyev.android.calculator.Engine.Preferences.Output;
public class NumberFormatPreference extends DialogPreference {
@Bind(R.id.nf_notation_spinner)
Spinner notationSpinner;
ArrayAdapter<Named<Engine.Notation>> notationAdapter;
@Bind(R.id.nf_precision_seekbar)
DiscreteSeekBar precisionSeekBar;
@Bind(R.id.nf_separator_spinner)
Spinner separatorSpinner;
ArrayAdapter<Named<Character>> separatorAdapter;
{
setPersistent(false);
setDialogLayoutResource(R.layout.preference_number_format);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public NumberFormatPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public NumberFormatPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public NumberFormatPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public NumberFormatPreference(Context context) {
super(context);
}
@Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
ButterKnife.bind(this, view);
final SharedPreferences preferences = getSharedPreferences();
precisionSeekBar.setMax(NumberFormatter.MAX_PRECISION);
precisionSeekBar.setCurrentTick(Math.max(0, Math.min(NumberFormatter.MAX_PRECISION, Output.precision.getPreference(preferences))));
notationAdapter = makeNotationAdapter();
notationSpinner.setAdapter(notationAdapter);
notationSpinner.setSelection(indexOf(notationAdapter, Output.notation.getPreference(preferences)));
separatorAdapter = makeSeparatorAdapter();
separatorSpinner.setAdapter(separatorAdapter);
separatorSpinner.setSelection(indexOf(separatorAdapter, Output.separator.getPreference(preferences)));
}
@Override
protected void onDialogClosed(boolean save) {
super.onDialogClosed(save);
if (!save) {
return;
}
final SharedPreferences.Editor editor = getSharedPreferences().edit();
Output.precision.putPreference(editor, precisionSeekBar.getCurrentTick());
Output.notation.putPreference(editor, notationAdapter.getItem(notationSpinner.getSelectedItemPosition()).item);
Output.separator.putPreference(editor, separatorAdapter.getItem(separatorSpinner.getSelectedItemPosition()).item);
editor.apply();
}
private <T> int indexOf(ArrayAdapter<Named<T>> adapter, T item) {
for (int i = 0; i < adapter.getCount(); i++) {
if (adapter.getItem(i).item.equals(item)) {
return i;
}
}
return -1;
}
@NonNull
private ArrayAdapter<Named<Engine.Notation>> makeNotationAdapter() {
final Context context = getContext();
final ArrayAdapter<Named<Engine.Notation>> adapter = App.makeSimpleSpinnerAdapter(context);
for (Engine.Notation notation : Engine.Notation.values()) {
adapter.add(Named.create(notation, notation.name, context));
}
adapter.sort(NaturalComparator.INSTANCE);
return adapter;
}
@NonNull
private ArrayAdapter<Named<Character>> makeSeparatorAdapter() {
final Context context = getContext();
final ArrayAdapter<Named<Character>> adapter = App.makeSimpleSpinnerAdapter(context);
adapter.add(Named.create(NumberFormatter.NO_GROUPING, R.string.p_grouping_separator_no, context));
adapter.add(Named.create('\'', R.string.p_grouping_separator_apostrophe, context));
adapter.add(Named.create(' ', R.string.p_grouping_separator_space, context));
return adapter;
}
}

View File

@ -0,0 +1,72 @@
package org.solovyev.android.calculator.preferences;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;
import butterknife.Bind;
import butterknife.ButterKnife;
import org.solovyev.android.calculator.Engine;
import org.solovyev.android.calculator.R;
import org.solovyev.android.views.DiscreteSeekBar;
import static org.solovyev.common.NumberFormatter.MAX_PRECISION;
import static org.solovyev.common.NumberFormatter.MIN_PRECISION;
@SuppressWarnings("unused")
public class PrecisionPreference extends DialogPreference {
@Bind(R.id.precision_seekbar)
DiscreteSeekBar seekBar;
{
setPersistent(false);
setDialogLayoutResource(R.layout.preference_precision);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public PrecisionPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public PrecisionPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public PrecisionPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public PrecisionPreference(Context context) {
super(context);
}
@Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
ButterKnife.bind(this, view);
final SharedPreferences preferences = getSharedPreferences();
seekBar.setMax(MAX_PRECISION - 1);
final int precision = Math.max(MIN_PRECISION, Math.min(MAX_PRECISION, Engine.Preferences.Output.precision.getPreference(preferences)));
seekBar.setCurrentTick(precision - 1);
}
@Override
protected void onDialogClosed(boolean save) {
super.onDialogClosed(save);
if (!save) {
return;
}
final int precision = seekBar.getCurrentTick() + 1;
if (callChangeListener(precision)) {
final SharedPreferences.Editor editor = getSharedPreferences().edit();
Engine.Preferences.Output.precision.putPreference(editor, precision);
editor.apply();
}
}
}

View File

@ -35,6 +35,7 @@ public class PreferencesActivity extends BaseActivity implements SharedPreferenc
static { static {
preferenceDefs.append(R.xml.preferences, new PrefDef("screen-main", R.string.cpp_settings)); preferenceDefs.append(R.xml.preferences, new PrefDef("screen-main", R.string.cpp_settings));
preferenceDefs.append(R.xml.preferences_number_format, new PrefDef("screen-number-format", R.string.c_prefs_calculations_category));
preferenceDefs.append(R.xml.preferences_calculations, new PrefDef("screen-calculations", R.string.c_prefs_calculations_category)); preferenceDefs.append(R.xml.preferences_calculations, new PrefDef("screen-calculations", R.string.c_prefs_calculations_category));
preferenceDefs.append(R.xml.preferences_appearance, new PrefDef("screen-appearance", R.string.c_prefs_appearance_category)); preferenceDefs.append(R.xml.preferences_appearance, new PrefDef("screen-appearance", R.string.c_prefs_appearance_category));
preferenceDefs.append(R.xml.preferences_other, new PrefDef("screen-other", R.string.c_prefs_other_category)); preferenceDefs.append(R.xml.preferences_other, new PrefDef("screen-other", R.string.c_prefs_other_category));

View File

@ -11,8 +11,11 @@ import android.support.v4.app.FragmentActivity;
import android.util.SparseArray; import android.util.SparseArray;
import android.view.View; import android.view.View;
import android.widget.ListView; import android.widget.ListView;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import jscl.JsclMathEngine;
import org.solovyev.android.calculator.AdView; import org.solovyev.android.calculator.AdView;
import org.solovyev.android.calculator.Engine;
import org.solovyev.android.calculator.Preferences; import org.solovyev.android.calculator.Preferences;
import org.solovyev.android.calculator.Preferences.Gui.Theme; import org.solovyev.android.calculator.Preferences.Gui.Theme;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
@ -22,14 +25,15 @@ import org.solovyev.android.checkout.BillingRequests;
import org.solovyev.android.checkout.Checkout; import org.solovyev.android.checkout.Checkout;
import org.solovyev.android.checkout.ProductTypes; import org.solovyev.android.checkout.ProductTypes;
import org.solovyev.android.checkout.RequestListener; import org.solovyev.android.checkout.RequestListener;
import org.solovyev.android.prefs.StringPreference;
import org.solovyev.android.wizard.Wizards; import org.solovyev.android.wizard.Wizards;
import org.solovyev.common.text.CharacterMapper;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.Arrays;
import java.util.List;
import static org.solovyev.android.calculator.App.cast; import static org.solovyev.android.calculator.App.cast;
import static org.solovyev.android.calculator.wizard.CalculatorWizards.DEFAULT_WIZARD_FLOW; import static org.solovyev.android.calculator.wizard.CalculatorWizards.DEFAULT_WIZARD_FLOW;
@ -48,11 +52,15 @@ public class PreferencesFragment extends org.solovyev.android.material.preferenc
Languages languages; Languages languages;
@Inject @Inject
Wizards wizards; Wizards wizards;
@Inject
JsclMathEngine engine;
@Inject
Bus bus;
@Nonnull @Nonnull
public static PreferencesFragment create(int preferencesResId, int layoutResId) { public static PreferencesFragment create(int preferences, int layout) {
final PreferencesFragment fragment = new PreferencesFragment(); final PreferencesFragment fragment = new PreferencesFragment();
fragment.setArguments(createArguments(preferencesResId, layoutResId, NO_THEME)); fragment.setArguments(createArguments(preferences, layout, NO_THEME));
return fragment; return fragment;
} }
@ -62,6 +70,7 @@ public class PreferencesFragment extends org.solovyev.android.material.preferenc
cast(this).getComponent().inject(this); cast(this).getComponent().inject(this);
preferences.registerOnSharedPreferenceChangeListener(this); preferences.registerOnSharedPreferenceChangeListener(this);
bus.register(this);
} }
private void setPreferenceIntent(int xml, @Nonnull PreferencesActivity.PrefDef def) { private void setPreferenceIntent(int xml, @Nonnull PreferencesActivity.PrefDef def) {
@ -108,6 +117,11 @@ public class PreferencesFragment extends org.solovyev.android.material.preferenc
} }
}); });
} }
} else if (preference == R.xml.preferences_number_format) {
prepareListPreference(Engine.Preferences.Output.notation, Engine.Notation.class);
preparePrecisionPreference();
prepareSeparatorPreference();
prepareNumberFormatExamplesPreference();
} }
prepareLanguagePreference(preference); prepareLanguagePreference(preference);
@ -136,6 +150,73 @@ public class PreferencesFragment extends org.solovyev.android.material.preferenc
}); });
} }
private void prepareNumberFormatExamplesPreference() {
final NumberFormatExamplesPreference preference = (NumberFormatExamplesPreference) preferenceManager.findPreference("numberFormat.examples");
if (preference == null) {
return;
}
preference.update(engine);
}
private void prepareSeparatorPreference() {
final ListPreference preference = (ListPreference) preferenceManager.findPreference(Engine.Preferences.Output.separator.getKey());
preference.setSummary(separatorName(Engine.Preferences.Output.separator.getPreference(preferences)));
preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference p, Object newValue) {
preference.setSummary(separatorName(CharacterMapper.INSTANCE.parseValue(String.valueOf(newValue))));
return true;
}
});
}
private int separatorName(char separator) {
switch (separator) {
case '\'':
return R.string.p_grouping_separator_apostrophe;
case ' ':
return R.string.p_grouping_separator_space;
case 0:
return R.string.p_grouping_separator_no;
}
return R.string.p_grouping_separator_no;
}
private void preparePrecisionPreference() {
final PrecisionPreference preference = (PrecisionPreference) preferenceManager.findPreference(Engine.Preferences.Output.precision.getKey());
preference.setSummary(String.valueOf(Engine.Preferences.Output.precision.getPreference(preferences)));
preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference p, Object newValue) {
preference.setSummary(String.valueOf(newValue));
return true;
}
});
}
private <E extends Enum<E> & PreferenceEntry> void prepareListPreference(@Nonnull final StringPreference<E> p, @Nonnull Class<E> type) {
final ListPreference preference = (ListPreference) preferenceManager.findPreference(p.getKey());
if (preference == null) {
return;
}
final E[] entries = type.getEnumConstants();
final FragmentActivity activity = getActivity();
populate(preference, entries);
preference.setSummary(p.getPreference(preferences).getName(activity));
preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference p, Object newValue) {
for (E entry : entries) {
if (entry.getId().equals(newValue)) {
preference.setSummary(entry.getName(activity));
break;
}
}
return true;
}
});
}
private void prepareLayoutPreference(int preference) { private void prepareLayoutPreference(int preference) {
if (preference != R.xml.preferences_appearance) { if (preference != R.xml.preferences_appearance) {
return; return;
@ -220,6 +301,11 @@ public class PreferencesFragment extends org.solovyev.android.material.preferenc
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
} }
@Subscribe
public void onEngineChanged(Engine.ChangedEvent e) {
prepareNumberFormatExamplesPreference();
}
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
@ -246,6 +332,7 @@ public class PreferencesFragment extends org.solovyev.android.material.preferenc
@Override @Override
public void onDestroy() { public void onDestroy() {
bus.unregister(this);
preferences.unregisterOnSharedPreferenceChangeListener(this); preferences.unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy(); super.onDestroy();
} }

View File

@ -56,6 +56,11 @@ public final class StringPreference<T> extends AbstractPreference<T> {
return new StringPreference<T>(key, mapper.parseValue(defaultValue), mapper); return new StringPreference<T>(key, mapper.parseValue(defaultValue), mapper);
} }
@Nonnull
public static <T> StringPreference<T> ofTypedValue(@Nonnull String key, @Nullable T defaultValue, @Nonnull Mapper<T> mapper) {
return new StringPreference<T>(key, defaultValue, mapper);
}
@Nonnull @Nonnull
public static <T extends Enum> StringPreference<T> ofEnum(@Nonnull String key, @Nullable T defaultValue, @Nonnull Class<T> enumType) { public static <T extends Enum> StringPreference<T> ofEnum(@Nonnull String key, @Nullable T defaultValue, @Nonnull Class<T> enumType) {
return new StringPreference<T>(key, defaultValue, EnumMapper.of(enumType)); return new StringPreference<T>(key, defaultValue, EnumMapper.of(enumType));

View File

@ -0,0 +1,27 @@
package org.solovyev.common.text;
import android.text.TextUtils;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class CharacterMapper implements Mapper<Character> {
@Nonnull
public static final CharacterMapper INSTANCE = new CharacterMapper();
private CharacterMapper() {
}
@Nonnull
@Override
public String formatValue(@Nullable Character value) throws IllegalArgumentException {
return value == null || value == 0 ? "" : String.valueOf(value);
}
@Nonnull
@Override
public Character parseValue(@Nullable String value) throws IllegalArgumentException {
return TextUtils.isEmpty(value) ? 0 : value.charAt(0);
}
}

View File

@ -1,45 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/cpp_dialog_spacing">
<TextView
style="@style/CppLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Notation"/>
<Spinner
android:id="@+id/nf_notation_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
style="@style/CppLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Precision"/>
<org.solovyev.android.views.DiscreteSeekBar
android:id="@+id/nf_precision_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:labelsColor="?android:attr/textColorSecondary"
app:labelsSize="12sp"
app:values="@array/cpp_prefs_precisions"/>
<TextView
style="@style/CppLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Separator"/>
<Spinner
android:id="@+id/nf_separator_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<org.solovyev.android.views.DiscreteSeekBar android:id="@+id/precision_seekbar"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/cpp_dialog_spacing"
app:labelsColor="?android:attr/textColorSecondary"
app:labelsSize="12sp"
app:values="@array/cpp_prefs_precisions" />

View File

@ -18,7 +18,6 @@
<string name="cpp_exponent" translatable="false">E</string> <string name="cpp_exponent" translatable="false">E</string>
<string name="cpp_theme_black" translatable="false">%1$s (AMOLED)</string> <string name="cpp_theme_black" translatable="false">%1$s (AMOLED)</string>
<string-array name="cpp_prefs_precisions" translatable="false"> <string-array name="cpp_prefs_precisions" translatable="false">
<item>0</item>
<item>1</item> <item>1</item>
<item>2</item> <item>2</item>
<item>3</item> <item>3</item>

View File

@ -35,6 +35,10 @@
a:key="restart_wizard" a:key="restart_wizard"
a:title="@string/cpp_restart_wizard" /> a:title="@string/cpp_restart_wizard" />
<Preference
a:key="screen-number-format"
a:title="Number format" />
<Preference <Preference
a:key="screen-calculations" a:key="screen-calculations"
a:title="@string/c_prefs_calculations_category" /> a:title="@string/c_prefs_calculations_category" />

View File

@ -24,30 +24,6 @@
<PreferenceScreen xmlns:a="http://schemas.android.com/apk/res/android"> <PreferenceScreen xmlns:a="http://schemas.android.com/apk/res/android">
<org.solovyev.android.calculator.preferences.NumberFormatPreference
a:key="engine.output.numberFormat"
a:title="Number format" />
<ListPreference
a:entries="@array/cpp_prefs_precisions"
a:entryValues="@array/cpp_prefs_precisions"
a:key="engine.output.precision"
a:summary="@string/c_calc_result_precision_summary"
a:title="@string/p_calc_result_precision_title" />
<android.preference.CheckBoxPreference
a:defaultValue="false"
a:key="engine.output.scientificNotation"
a:summary="@string/c_calc_science_notation_summary"
a:title="@string/c_calc_science_notation_title" />
<ListPreference
a:entries="@array/p_grouping_separator_names"
a:entryValues="@array/p_grouping_separator_values"
a:key="engine.groupingSeparator"
a:summary="@string/c_calc_grouping_separator_summary"
a:title="@string/c_calc_grouping_separator" />
<ListPreference <ListPreference
a:entries="@array/p_angle_units_names" a:entries="@array/p_angle_units_names"
a:entryValues="@array/p_angle_units" a:entryValues="@array/p_angle_units"

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2016 serso aka se.solovyev
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ Contact details
~
~ Email: se.solovyev@gmail.com
~ Site: http://se.solovyev.org
-->
<PreferenceScreen xmlns:a="http://schemas.android.com/apk/res/android"
xmlns:m="http://schemas.android.com/apk/res-auto">
<org.solovyev.android.material.preferences.ListPreference
a:key="engine.output.notation"
a:title="Notation"
m:materialColor="@color/material_text_selector" />
<org.solovyev.android.calculator.preferences.PrecisionPreference
a:key="engine.output.precision"
a:title="@string/p_calc_result_precision_title" />
<org.solovyev.android.material.preferences.ListPreference
a:entries="@array/p_grouping_separator_names"
a:entryValues="@array/p_grouping_separator_values"
a:key="engine.output.separator"
a:title="@string/c_calc_grouping_separator"
m:materialColor="@color/material_text_selector" />
<org.solovyev.android.calculator.preferences.NumberFormatExamplesPreference
a:key="numberFormat.examples"
a:selectable="false"
a:title="Examples" />
</PreferenceScreen>

View File

@ -14,6 +14,7 @@ public class NumberFormatter {
public static final char NO_GROUPING = 0; public static final char NO_GROUPING = 0;
public static final int NO_ROUNDING = -1; public static final int NO_ROUNDING = -1;
public static final int DEFAULT_MAGNITUDE = 5; public static final int DEFAULT_MAGNITUDE = 5;
public static final int MIN_PRECISION = 1;
public static final int MAX_PRECISION = 15; public static final int MAX_PRECISION = 15;
private final Real.NumberFormat numberFormat = new Real.NumberFormat(); private final Real.NumberFormat numberFormat = new Real.NumberFormat();
@ -39,7 +40,7 @@ public class NumberFormatter {
} }
public void setPrecision(int precision) { public void setPrecision(int precision) {
this.precision = precision; this.precision = Math.max(MIN_PRECISION, Math.min(precision, MAX_PRECISION));
} }
public void setGroupingSeparator(char groupingSeparator) { public void setGroupingSeparator(char groupingSeparator) {