diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 8ac9c420..1624bd8a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -56,7 +56,11 @@
+ android:label="@string/cpp_settings">
+
+
+
+
ArrayAdapter makeSimpleSpinnerAdapter(@NonNull Context context) {
+ return new ArrayAdapter<>(context, R.layout.support_simple_spinner_dropdown_item);
+ }
+
public interface ViewProcessor {
void process(@Nonnull V view);
}
diff --git a/app/src/main/java/org/solovyev/android/calculator/Engine.java b/app/src/main/java/org/solovyev/android/calculator/Engine.java
index 244881f9..d9d0f779 100644
--- a/app/src/main/java/org/solovyev/android/calculator/Engine.java
+++ b/app/src/main/java/org/solovyev/android/calculator/Engine.java
@@ -22,7 +22,10 @@
package org.solovyev.android.calculator;
+import android.content.Context;
import android.content.SharedPreferences;
+import android.support.annotation.NonNull;
+import android.support.annotation.StringRes;
import android.text.TextUtils;
import com.squareup.otto.Bus;
import jscl.AngleUnit;
@@ -32,14 +35,15 @@ import jscl.NumeralBase;
import jscl.math.operator.Operator;
import jscl.text.Identifier;
import jscl.text.Parser;
+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.prefs.BooleanPreference;
-import org.solovyev.android.prefs.IntegerPreference;
-import org.solovyev.android.prefs.Preference;
-import org.solovyev.android.prefs.StringPreference;
+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;
@@ -86,15 +90,8 @@ public class Engine implements SharedPreferences.OnSharedPreferenceChangeListene
public Engine(@Nonnull JsclMathEngine mathEngine) {
this.mathEngine = mathEngine;
- this.mathEngine.setRoundResult(true);
- this.mathEngine.setUseGroupingSeparator(true);
- }
-
- 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));
+ this.mathEngine.setPrecision(5);
+ this.mathEngine.setGroupingSeparator(JsclMathEngine.GROUPING_SEPARATOR_DEFAULT);
}
private static void migratePreference(@Nonnull SharedPreferences preferences, @Nonnull StringPreference> preference, @Nonnull String oldKey, @Nonnull SharedPreferences.Editor editor) {
@@ -168,13 +165,33 @@ public class Engine implements SharedPreferences.OnSharedPreferenceChangeListene
}
final SharedPreferences.Editor editor = preferences.edit();
if (oldVersion == 0) {
- migratePreference(preferences, Preferences.groupingSeparator, "org.solovyev.android.calculator.CalculatorActivity_calc_grouping_separator", editor);
+ migratePreference(preferences, Preferences.Output.separator, "org.solovyev.android.calculator.CalculatorActivity_calc_grouping_separator", editor);
migratePreference(preferences, Preferences.multiplicationSign, "org.solovyev.android.calculator.CalculatorActivity_calc_multiplication_sign", editor);
migratePreference(preferences, Preferences.numeralBase, "org.solovyev.android.calculator.CalculatorActivity_numeral_bases", editor);
migratePreference(preferences, Preferences.angleUnit, "org.solovyev.android.calculator.CalculatorActivity_angle_units", editor);
migratePreference(preferences, Preferences.Output.precision, "org.solovyev.android.calculator.CalculatorModel_result_precision", editor);
- migratePreference(preferences, Preferences.Output.scientificNotation, "calculation.output.science_notation", editor);
- migratePreference(preferences, Preferences.Output.round, "org.solovyev.android.calculator.CalculatorModel_round_result", editor);
+ if (preferences.contains("engine.output.science_notation")) {
+ final boolean scientific = preferences.getBoolean("engine.output.science_notation", false);
+ Preferences.Output.notation.putPreference(editor, scientific ? Notation.sci : Notation.dec);
+ }
+ if (preferences.contains("org.solovyev.android.calculator.CalculatorModel_round_result")) {
+ final boolean round = preferences.getBoolean("org.solovyev.android.calculator.CalculatorModel_round_result", true);
+ if (!round) {
+ Preferences.Output.precision.putPreference(editor, NumberFormatter.MAX_PRECISION);
+ }
+ }
+ } else if (oldVersion == 1) {
+ migratePreference(preferences, Preferences.Output.separator, "engine.groupingSeparator", editor);
+ if (preferences.contains("engine.output.scientificNotation")) {
+ final boolean scientific = preferences.getBoolean("engine.output.scientificNotation", false);
+ Preferences.Output.notation.putPreference(editor, scientific ? Notation.sci : Notation.dec);
+ }
+ if (preferences.contains("engine.output.round")) {
+ final boolean round = preferences.getBoolean("engine.output.round", true);
+ if (!round) {
+ Preferences.Output.precision.putPreference(editor, NumberFormatter.MAX_PRECISION);
+ }
+ }
}
Preferences.version.putDefault(editor);
editor.apply();
@@ -202,16 +219,9 @@ public class Engine implements SharedPreferences.OnSharedPreferenceChangeListene
setMultiplicationSign(Preferences.multiplicationSign.getPreference(preferences));
mathEngine.setPrecision(Preferences.Output.precision.getPreference(preferences));
- mathEngine.setScienceNotation(Preferences.Output.scientificNotation.getPreference(preferences));
- mathEngine.setRoundResult(Preferences.Output.round.getPreference(preferences));
+ mathEngine.setNotation(Preferences.Output.notation.getPreference(preferences).id);
+ mathEngine.setGroupingSeparator(Preferences.Output.separator.getPreference(preferences));
- final String groupingSeparator = Preferences.groupingSeparator.getPreference(preferences);
- if (TextUtils.isEmpty(groupingSeparator)) {
- mathEngine.setUseGroupingSeparator(false);
- } else {
- mathEngine.setUseGroupingSeparator(true);
- mathEngine.setGroupingSeparator(groupingSeparator.charAt(0));
- }
bus.post(ChangedEvent.INSTANCE);
}
@@ -231,28 +241,54 @@ public class Engine implements SharedPreferences.OnSharedPreferenceChangeListene
}
}
+ public enum Notation implements PreferenceEntry {
+ dec(Real.NumberFormat.FSE_NONE, R.string.cpp_number_format_dec),
+ eng(Real.NumberFormat.FSE_ENG, R.string.cpp_number_format_eng),
+ sci(Real.NumberFormat.FSE_SCI, R.string.cpp_number_format_sci);
+
+ public final int id;
+ @StringRes
+ public final int name;
+
+ Notation(int id, @StringRes int name) {
+ this.id = id;
+ 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 {
static final ChangedEvent INSTANCE = new ChangedEvent();
+
private ChangedEvent() {
}
}
public static class Preferences {
- public static final StringPreference groupingSeparator = StringPreference.of("engine.groupingSeparator", String.valueOf(JsclMathEngine.GROUPING_SEPARATOR_DEFAULT));
public static final StringPreference multiplicationSign = StringPreference.of("engine.multiplicationSign", "×");
public static final StringPreference numeralBase = StringPreference.ofTypedValue("engine.numeralBase", "dec", EnumMapper.of(NumeralBase.class));
public static final StringPreference angleUnit = StringPreference.ofTypedValue("engine.angleUnit", "deg", EnumMapper.of(AngleUnit.class));
- public static final Preference version = IntegerPreference.of("engine.version", 1);
+ public static final Preference version = IntegerPreference.of("engine.version", 2);
private static final List preferenceKeys = new ArrayList<>();
static {
- preferenceKeys.add(groupingSeparator.getKey());
preferenceKeys.add(multiplicationSign.getKey());
preferenceKeys.add(numeralBase.getKey());
preferenceKeys.add(angleUnit.getKey());
preferenceKeys.add(Output.precision.getKey());
- preferenceKeys.add(Output.scientificNotation.getKey());
- preferenceKeys.add(Output.round.getKey());
+ preferenceKeys.add(Output.notation.getKey());
+ preferenceKeys.add(Output.separator.getKey());
}
@Nonnull
@@ -262,8 +298,8 @@ public class Engine implements SharedPreferences.OnSharedPreferenceChangeListene
public static class Output {
public static final StringPreference precision = StringPreference.ofTypedValue("engine.output.precision", "5", NumberMapper.of(Integer.class));
- public static final BooleanPreference scientificNotation = BooleanPreference.of("engine.output.scientificNotation", false);
- public static final BooleanPreference round = BooleanPreference.of("engine.output.round", true);
+ public static final StringPreference notation = StringPreference.ofEnum("engine.output.notation", Notation.dec, Notation.class);
+ public static final StringPreference separator = StringPreference.ofTypedValue("engine.output.separator", JsclMathEngine.GROUPING_SEPARATOR_DEFAULT, CharacterMapper.INSTANCE);
}
}
}
diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/Named.java b/app/src/main/java/org/solovyev/android/calculator/Named.java
similarity index 79%
rename from app/src/main/java/org/solovyev/android/calculator/converter/Named.java
rename to app/src/main/java/org/solovyev/android/calculator/Named.java
index c22059ad..bea042f6 100644
--- a/app/src/main/java/org/solovyev/android/calculator/converter/Named.java
+++ b/app/src/main/java/org/solovyev/android/calculator/Named.java
@@ -1,4 +1,4 @@
-package org.solovyev.android.calculator.converter;
+package org.solovyev.android.calculator;
import android.content.Context;
import android.support.annotation.NonNull;
@@ -6,7 +6,7 @@ import android.support.annotation.StringRes;
import javax.annotation.Nonnull;
-class Named {
+public class Named {
@NonNull
public final T item;
@NonNull
@@ -18,12 +18,12 @@ class Named {
}
@NonNull
- static Named create(@NonNull T item, @Nonnull String name) {
+ public static Named create(@NonNull T item, @Nonnull String name) {
return new Named(item, name);
}
@NonNull
- static Named create(@NonNull T item, @StringRes int name, @NonNull Context context) {
+ public static Named create(@NonNull T item, @StringRes int name, @NonNull Context context) {
return create(item, name == 0 ? item.toString() : context.getString(name));
}
diff --git a/app/src/main/java/org/solovyev/android/calculator/Preferences.java b/app/src/main/java/org/solovyev/android/calculator/Preferences.java
index 0622d50e..a51da55c 100644
--- a/app/src/main/java/org/solovyev/android/calculator/Preferences.java
+++ b/app/src/main/java/org/solovyev/android/calculator/Preferences.java
@@ -53,6 +53,8 @@ import java.util.EnumMap;
import java.util.Locale;
import java.util.Map;
+import jscl.JsclMathEngine;
+
import static org.solovyev.android.prefs.IntegerPreference.DEF_VALUE;
public final class Preferences {
@@ -108,19 +110,19 @@ public final class Preferences {
}
private static void setInitialDefaultValues(@Nonnull Application application, @Nonnull SharedPreferences preferences, @Nonnull SharedPreferences.Editor editor) {
- if (!Engine.Preferences.groupingSeparator.isSet(preferences)) {
+ if (!Engine.Preferences.Output.separator.isSet(preferences)) {
final Locale locale = Locale.getDefault();
if (locale != null) {
final DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(locale);
- int index = MathType.grouping_separator.getTokens().indexOf(String.valueOf(decimalFormatSymbols.getGroupingSeparator()));
- final String groupingSeparator;
+ final int index = MathType.grouping_separator.getTokens().indexOf(String.valueOf(decimalFormatSymbols.getGroupingSeparator()));
+ final char separator;
if (index >= 0) {
- groupingSeparator = MathType.grouping_separator.getTokens().get(index);
+ separator = MathType.grouping_separator.getTokens().get(index).charAt(0);
} else {
- groupingSeparator = " ";
+ separator = JsclMathEngine.GROUPING_SEPARATOR_DEFAULT;
}
- Engine.Preferences.groupingSeparator.putPreference(editor, groupingSeparator);
+ Engine.Preferences.Output.separator.putPreference(editor, separator);
}
}
diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/ConverterFragment.java b/app/src/main/java/org/solovyev/android/calculator/converter/ConverterFragment.java
index c69ec60b..275f5173 100644
--- a/app/src/main/java/org/solovyev/android/calculator/converter/ConverterFragment.java
+++ b/app/src/main/java/org/solovyev/android/calculator/converter/ConverterFragment.java
@@ -21,21 +21,39 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
-import android.widget.*;
-import butterknife.Bind;
-import butterknife.ButterKnife;
-import org.solovyev.android.calculator.*;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import org.solovyev.android.calculator.App;
+import org.solovyev.android.calculator.AppComponent;
+import org.solovyev.android.calculator.AppModule;
+import org.solovyev.android.calculator.BaseDialogFragment;
+import org.solovyev.android.calculator.Clipboard;
+import org.solovyev.android.calculator.Editor;
+import org.solovyev.android.calculator.Keyboard;
+import org.solovyev.android.calculator.Named;
+import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.keyboard.FloatingKeyboard;
import org.solovyev.android.calculator.keyboard.FloatingKeyboardWindow;
import org.solovyev.android.calculator.keyboard.FloatingNumberKeyboard;
import org.solovyev.android.calculator.math.MathUtils;
+import org.solovyev.android.calculator.text.NaturalComparator;
import org.solovyev.android.calculator.view.EditTextCompat;
import javax.annotation.Nonnull;
import javax.inject.Inject;
-import java.util.Comparator;
-import static org.solovyev.android.calculator.UiPreferences.Converter.*;
+import butterknife.Bind;
+import butterknife.ButterKnife;
+
+import static org.solovyev.android.calculator.UiPreferences.Converter.lastDimension;
+import static org.solovyev.android.calculator.UiPreferences.Converter.lastUnitsFrom;
+import static org.solovyev.android.calculator.UiPreferences.Converter.lastUnitsTo;
public class ConverterFragment extends BaseDialogFragment
implements AdapterView.OnItemSelectedListener, View.OnFocusChangeListener, TextView.OnEditorActionListener, View.OnClickListener, TextWatcher {
@@ -44,7 +62,6 @@ public class ConverterFragment extends BaseDialogFragment
private static final String STATE_SELECTION_FROM = "selection.from";
private static final String STATE_SELECTION_TO = "selection.to";
private static final String EXTRA_VALUE = "value";
- private static final NamedItemComparator COMPARATOR = new NamedItemComparator();
public static final int NONE = -1;
@NonNull
@@ -96,11 +113,6 @@ public class ConverterFragment extends BaseDialogFragment
App.showDialog(fragment, "converter", activity.getSupportFragmentManager());
}
- @Nonnull
- private static ArrayAdapter makeAdapter(@NonNull Context context) {
- return new ArrayAdapter<>(context, R.layout.support_simple_spinner_dropdown_item);
- }
-
@NonNull
@Override
public AlertDialog onCreateDialog(@Nullable Bundle savedInstanceState) {
@@ -130,13 +142,13 @@ public class ConverterFragment extends BaseDialogFragment
final View view = inflater.inflate(R.layout.cpp_unit_converter, null);
ButterKnife.bind(this, view);
- dimensionsAdapter = makeAdapter(context);
+ dimensionsAdapter = App.makeSimpleSpinnerAdapter(context);
for (ConvertibleDimension dimension : UnitDimension.values()) {
dimensionsAdapter.add(dimension.named(context));
}
dimensionsAdapter.add(NumeralBaseDimension.get().named(context));
- adapterFrom = makeAdapter(context);
- adapterTo = makeAdapter(context);
+ adapterFrom = App.makeSimpleSpinnerAdapter(context);
+ adapterTo = App.makeSimpleSpinnerAdapter(context);
dimensionsSpinner.setAdapter(dimensionsAdapter);
spinnerFrom.setAdapter(adapterFrom);
@@ -235,7 +247,7 @@ public class ConverterFragment extends BaseDialogFragment
for (Convertible unit : dimension.getUnits()) {
adapterFrom.add(unit.named(getActivity()));
}
- adapterFrom.sort(COMPARATOR);
+ adapterFrom.sort(NaturalComparator.INSTANCE);
adapterFrom.setNotifyOnChange(true);
adapterFrom.notifyDataSetChanged();
if (pendingFromSelection != NONE) {
@@ -261,7 +273,7 @@ public class ConverterFragment extends BaseDialogFragment
adapterTo.add(unit.named(getActivity()));
}
}
- adapterTo.sort(COMPARATOR);
+ adapterTo.sort(NaturalComparator.INSTANCE);
adapterTo.setNotifyOnChange(true);
adapterTo.notifyDataSetChanged();
if (selectedUnit != null && !except.equals(selectedUnit)) {
@@ -431,13 +443,6 @@ public class ConverterFragment extends BaseDialogFragment
super.dismiss();
}
- private static class NamedItemComparator implements Comparator> {
- @Override
- public int compare(Named lhs, Named rhs) {
- return lhs.toString().compareTo(rhs.toString());
- }
- }
-
private class KeyboardUser implements FloatingKeyboard.User {
@NonNull
@Override
diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/Convertible.java b/app/src/main/java/org/solovyev/android/calculator/converter/Convertible.java
index d02017dc..701fe7b0 100644
--- a/app/src/main/java/org/solovyev/android/calculator/converter/Convertible.java
+++ b/app/src/main/java/org/solovyev/android/calculator/converter/Convertible.java
@@ -3,6 +3,8 @@ package org.solovyev.android.calculator.converter;
import android.content.Context;
import android.support.annotation.NonNull;
+import org.solovyev.android.calculator.Named;
+
interface Convertible {
@NonNull
String convert(@NonNull Convertible to, @NonNull String value) throws NumberFormatException;
diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/ConvertibleDimension.java b/app/src/main/java/org/solovyev/android/calculator/converter/ConvertibleDimension.java
index f33b6f1b..f945b4dc 100644
--- a/app/src/main/java/org/solovyev/android/calculator/converter/ConvertibleDimension.java
+++ b/app/src/main/java/org/solovyev/android/calculator/converter/ConvertibleDimension.java
@@ -3,6 +3,8 @@ package org.solovyev.android.calculator.converter;
import android.content.Context;
import android.support.annotation.NonNull;
+import org.solovyev.android.calculator.Named;
+
import java.util.List;
public interface ConvertibleDimension {
diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseConvertible.java b/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseConvertible.java
index f211340b..5c5dc63c 100644
--- a/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseConvertible.java
+++ b/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseConvertible.java
@@ -2,6 +2,9 @@ package org.solovyev.android.calculator.converter;
import android.content.Context;
import android.support.annotation.NonNull;
+
+import org.solovyev.android.calculator.Named;
+
import jscl.JsclMathEngine;
import jscl.NumeralBase;
import midpcalc.Real;
diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseDimension.java b/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseDimension.java
index 1834e257..8368101e 100644
--- a/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseDimension.java
+++ b/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseDimension.java
@@ -3,6 +3,8 @@ package org.solovyev.android.calculator.converter;
import android.content.Context;
import android.support.annotation.NonNull;
import jscl.NumeralBase;
+
+import org.solovyev.android.calculator.Named;
import org.solovyev.android.calculator.R;
import java.util.ArrayList;
diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/UnitConvertible.java b/app/src/main/java/org/solovyev/android/calculator/converter/UnitConvertible.java
index e8b3dded..91aadf3f 100644
--- a/app/src/main/java/org/solovyev/android/calculator/converter/UnitConvertible.java
+++ b/app/src/main/java/org/solovyev/android/calculator/converter/UnitConvertible.java
@@ -2,6 +2,9 @@ package org.solovyev.android.calculator.converter;
import android.content.Context;
import android.support.annotation.NonNull;
+
+import org.solovyev.android.calculator.Named;
+
import jscl.JsclMathEngine;
import jscl.NumeralBase;
diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/UnitDimension.java b/app/src/main/java/org/solovyev/android/calculator/converter/UnitDimension.java
index 6dc91974..9fbd4b35 100644
--- a/app/src/main/java/org/solovyev/android/calculator/converter/UnitDimension.java
+++ b/app/src/main/java/org/solovyev/android/calculator/converter/UnitDimension.java
@@ -4,6 +4,8 @@ import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
+
+import org.solovyev.android.calculator.Named;
import org.solovyev.android.calculator.R;
import javax.measure.unit.Dimension;
diff --git a/app/src/main/java/org/solovyev/android/calculator/history/History.java b/app/src/main/java/org/solovyev/android/calculator/history/History.java
index e4b90a9f..bb7ef9cf 100644
--- a/app/src/main/java/org/solovyev/android/calculator/history/History.java
+++ b/app/src/main/java/org/solovyev/android/calculator/history/History.java
@@ -27,22 +27,26 @@ import android.content.SharedPreferences;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.text.TextUtils;
+
import com.google.common.base.Strings;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
+
import org.json.JSONArray;
import org.json.JSONException;
import org.solovyev.android.Check;
-import org.solovyev.android.calculator.*;
+import org.solovyev.android.calculator.AppModule;
+import org.solovyev.android.calculator.Calculator;
+import org.solovyev.android.calculator.Display;
+import org.solovyev.android.calculator.DisplayState;
+import org.solovyev.android.calculator.Editor;
+import org.solovyev.android.calculator.EditorState;
import org.solovyev.android.calculator.Engine.Preferences;
+import org.solovyev.android.calculator.ErrorReporter;
+import org.solovyev.android.calculator.Runnables;
import org.solovyev.android.calculator.json.Json;
import org.solovyev.android.io.FileSystem;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -51,6 +55,12 @@ import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Executor;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
import static android.text.TextUtils.isEmpty;
@Singleton
@@ -115,15 +125,15 @@ public class History {
private static boolean isIntermediate(@Nonnull String olderText,
@Nonnull String newerText,
- @NonNull String groupingSeparator) {
+ char separator) {
if (TextUtils.isEmpty(olderText)) {
return true;
}
if (TextUtils.isEmpty(newerText)) {
return false;
}
- olderText = trimGroupingSeparators(olderText, groupingSeparator);
- newerText = trimGroupingSeparators(newerText, groupingSeparator);
+ olderText = trimGroupingSeparators(olderText, separator);
+ newerText = trimGroupingSeparators(newerText, separator);
final int diff = newerText.length() - olderText.length();
if (diff >= 1) {
@@ -138,11 +148,10 @@ public class History {
}
@NonNull
- static String trimGroupingSeparators(@NonNull String text, @NonNull String groupingSeparator) {
- if (TextUtils.isEmpty(groupingSeparator)) {
+ static String trimGroupingSeparators(@NonNull String text, char separator) {
+ if (separator == 0) {
return text;
}
- Check.isTrue(groupingSeparator.length() == 1);
final StringBuilder sb = new StringBuilder(text.length());
for (int i = 0; i < text.length(); i++) {
if (i == 0 || i == text.length() - 1) {
@@ -150,7 +159,7 @@ public class History {
sb.append(text.charAt(i));
continue;
}
- if (Character.isDigit(text.charAt(i - 1)) && text.charAt(i) == groupingSeparator.charAt(0) && Character.isDigit(text.charAt(i + 1))) {
+ if (Character.isDigit(text.charAt(i - 1)) && text.charAt(i) == separator && Character.isDigit(text.charAt(i + 1))) {
// grouping separator => skip
continue;
}
@@ -302,7 +311,7 @@ public class History {
final List result = new LinkedList<>();
- final String groupingSeparator = Preferences.groupingSeparator.getPreference(preferences);
+ final char separator = Preferences.Output.separator.getPreference(preferences);
final List states = recent.asList();
final int statesCount = states.size();
@@ -312,7 +321,7 @@ public class History {
final HistoryState newerState = states.get(i);
final String olderText = olderState.editor.getTextString();
final String newerText = newerState.editor.getTextString();
- if (streak >= MAX_INTERMEDIATE_STREAK || !isIntermediate(olderText, newerText, groupingSeparator)) {
+ if (streak >= MAX_INTERMEDIATE_STREAK || !isIntermediate(olderText, newerText, separator)) {
result.add(0, olderState);
streak = 0;
} else {
diff --git a/app/src/main/java/org/solovyev/android/calculator/preferences/NumberFormatExamplesPreference.java b/app/src/main/java/org/solovyev/android/calculator/preferences/NumberFormatExamplesPreference.java
new file mode 100644
index 00000000..9eabbbfe
--- /dev/null
+++ b/app/src/main/java/org/solovyev/android/calculator/preferences/NumberFormatExamplesPreference.java
@@ -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;
+ }
+}
diff --git a/app/src/main/java/org/solovyev/android/calculator/preferences/PrecisionPreference.java b/app/src/main/java/org/solovyev/android/calculator/preferences/PrecisionPreference.java
new file mode 100644
index 00000000..2b62f450
--- /dev/null
+++ b/app/src/main/java/org/solovyev/android/calculator/preferences/PrecisionPreference.java
@@ -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();
+ }
+ }
+}
diff --git a/app/src/main/java/org/solovyev/android/calculator/preferences/PreferencesActivity.java b/app/src/main/java/org/solovyev/android/calculator/preferences/PreferencesActivity.java
index ca7312cf..930f5313 100644
--- a/app/src/main/java/org/solovyev/android/calculator/preferences/PreferencesActivity.java
+++ b/app/src/main/java/org/solovyev/android/calculator/preferences/PreferencesActivity.java
@@ -35,6 +35,7 @@ public class PreferencesActivity extends BaseActivity implements SharedPreferenc
static {
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_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));
diff --git a/app/src/main/java/org/solovyev/android/calculator/preferences/PreferencesFragment.java b/app/src/main/java/org/solovyev/android/calculator/preferences/PreferencesFragment.java
index e18bd7cf..d46c5751 100644
--- a/app/src/main/java/org/solovyev/android/calculator/preferences/PreferencesFragment.java
+++ b/app/src/main/java/org/solovyev/android/calculator/preferences/PreferencesFragment.java
@@ -11,6 +11,9 @@ import android.support.v4.app.FragmentActivity;
import android.util.SparseArray;
import android.view.View;
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.Engine;
import org.solovyev.android.calculator.Preferences;
@@ -22,7 +25,9 @@ import org.solovyev.android.checkout.BillingRequests;
import org.solovyev.android.checkout.Checkout;
import org.solovyev.android.checkout.ProductTypes;
import org.solovyev.android.checkout.RequestListener;
+import org.solovyev.android.prefs.StringPreference;
import org.solovyev.android.wizard.Wizards;
+import org.solovyev.common.text.CharacterMapper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -47,11 +52,15 @@ public class PreferencesFragment extends org.solovyev.android.material.preferenc
Languages languages;
@Inject
Wizards wizards;
+ @Inject
+ JsclMathEngine engine;
+ @Inject
+ Bus bus;
@Nonnull
- public static PreferencesFragment create(int preferencesResId, int layoutResId) {
+ public static PreferencesFragment create(int preferences, int layout) {
final PreferencesFragment fragment = new PreferencesFragment();
- fragment.setArguments(createArguments(preferencesResId, layoutResId, NO_THEME));
+ fragment.setArguments(createArguments(preferences, layout, NO_THEME));
return fragment;
}
@@ -61,6 +70,7 @@ public class PreferencesFragment extends org.solovyev.android.material.preferenc
cast(this).getComponent().inject(this);
preferences.registerOnSharedPreferenceChangeListener(this);
+ bus.register(this);
}
private void setPreferenceIntent(int xml, @Nonnull PreferencesActivity.PrefDef def) {
@@ -107,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);
@@ -133,8 +148,73 @@ public class PreferencesFragment extends org.solovyev.android.material.preferenc
});
}
});
+ }
- onSharedPreferenceChanged(preferences, Engine.Preferences.Output.round.getKey());
+ 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 & PreferenceEntry> void prepareListPreference(@Nonnull final StringPreference p, @Nonnull Class 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) {
@@ -219,12 +299,11 @@ public class PreferencesFragment extends org.solovyev.android.material.preferenc
@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
- if (Engine.Preferences.Output.round.getKey().equals(key)) {
- final Preference preference = findPreference(Engine.Preferences.Output.precision.getKey());
- if (preference != null) {
- preference.setEnabled(preferences.getBoolean(key, Engine.Preferences.Output.round.getDefaultValue()));
- }
- }
+ }
+
+ @Subscribe
+ public void onEngineChanged(Engine.ChangedEvent e) {
+ prepareNumberFormatExamplesPreference();
}
@Override
@@ -253,6 +332,7 @@ public class PreferencesFragment extends org.solovyev.android.material.preferenc
@Override
public void onDestroy() {
+ bus.unregister(this);
preferences.unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
diff --git a/app/src/main/java/org/solovyev/android/calculator/text/NaturalComparator.java b/app/src/main/java/org/solovyev/android/calculator/text/NaturalComparator.java
new file mode 100644
index 00000000..bf219dfe
--- /dev/null
+++ b/app/src/main/java/org/solovyev/android/calculator/text/NaturalComparator.java
@@ -0,0 +1,12 @@
+package org.solovyev.android.calculator.text;
+
+import java.util.Comparator;
+
+public class NaturalComparator implements Comparator