From 5a9bcdede73e6ce16b03bfa310bf1dcae7ab9ab4 Mon Sep 17 00:00:00 2001 From: serso Date: Thu, 28 Apr 2016 12:18:35 +0200 Subject: [PATCH] Number format preference --- app/src/main/AndroidManifest.xml | 6 +- .../org/solovyev/android/calculator/App.java | 18 +- .../solovyev/android/calculator/Engine.java | 45 +++- .../converter/ConverterFragment.java | 52 ++-- .../preferences/NumberFormatPreference.java | 100 ++++++++ .../preferences/PreferencesFragment.java | 6 +- .../calculator/text/NaturalComparator.java | 12 + .../android/views/DiscreteSeekBar.java | 224 ++++++++++++++++++ .../layout/fragment_plot_function_edit.xml | 8 +- .../res/layout/preference_number_format.xml | 34 +++ app/src/main/res/values/attrs_dsb.xml | 8 + app/src/main/res/values/styles.xml | 5 + .../main/res/values/text_non_translatable.xml | 1 - app/src/main/res/values/text_strings.xml | 3 + .../main/res/xml/preferences_calculations.xml | 8 +- 15 files changed, 477 insertions(+), 53 deletions(-) create mode 100644 app/src/main/java/org/solovyev/android/calculator/preferences/NumberFormatPreference.java create mode 100644 app/src/main/java/org/solovyev/android/calculator/text/NaturalComparator.java create mode 100644 app/src/main/java/org/solovyev/android/views/DiscreteSeekBar.java create mode 100644 app/src/main/res/layout/preference_number_format.xml create mode 100644 app/src/main/res/values/attrs_dsb.xml 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..36ceb743 100644 --- a/app/src/main/java/org/solovyev/android/calculator/Engine.java +++ b/app/src/main/java/org/solovyev/android/calculator/Engine.java @@ -23,15 +23,11 @@ package org.solovyev.android.calculator; import android.content.SharedPreferences; +import android.support.annotation.StringRes; import android.text.TextUtils; + import com.squareup.otto.Bus; -import jscl.AngleUnit; -import jscl.JsclMathEngine; -import jscl.MathEngine; -import jscl.NumeralBase; -import jscl.math.operator.Operator; -import jscl.text.Identifier; -import jscl.text.Parser; + import org.solovyev.android.Check; import org.solovyev.android.calculator.functions.FunctionsRegistry; import org.solovyev.android.calculator.operators.OperatorsRegistry; @@ -43,15 +39,25 @@ import org.solovyev.android.prefs.StringPreference; 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; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.inject.Inject; +import javax.inject.Singleton; + +import jscl.AngleUnit; +import jscl.JsclMathEngine; +import jscl.MathEngine; +import jscl.NumeralBase; +import jscl.math.operator.Operator; +import jscl.text.Identifier; +import jscl.text.Parser; +import midpcalc.Real; + @Singleton public class Engine implements SharedPreferences.OnSharedPreferenceChangeListener { @@ -231,8 +237,24 @@ public class Engine implements SharedPreferences.OnSharedPreferenceChangeListene } } + public enum Notation { + simple(Real.NumberFormat.FSE_NONE, R.string.cpp_number_format_simple), + 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; + } + } + public static class ChangedEvent { static final ChangedEvent INSTANCE = new ChangedEvent(); + private ChangedEvent() { } } @@ -264,6 +286,7 @@ public class Engine implements SharedPreferences.OnSharedPreferenceChangeListene 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.simple, Notation.class); } } } 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..448a6b8d 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,38 @@ 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.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 +61,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 +112,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 +141,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 +246,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 +272,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 +442,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/preferences/NumberFormatPreference.java b/app/src/main/java/org/solovyev/android/calculator/preferences/NumberFormatPreference.java new file mode 100644 index 00000000..2edb24db --- /dev/null +++ b/app/src/main/java/org/solovyev/android/calculator/preferences/NumberFormatPreference.java @@ -0,0 +1,100 @@ +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.SeekBar; +import android.widget.Spinner; + +import org.solovyev.android.calculator.App; +import org.solovyev.android.calculator.Engine; +import org.solovyev.android.calculator.R; +import org.solovyev.android.calculator.text.NaturalComparator; + +import butterknife.Bind; +import butterknife.ButterKnife; + +public class NumberFormatPreference extends DialogPreference { + @Bind(R.id.nf_notation_spinner) + Spinner notationSpinner; + @Bind(R.id.nf_precision_seekbar) + SeekBar precisionSeekBar; + + { + 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(15); + precisionSeekBar.setProgress(Math.max(0, Math.min(15, Engine.Preferences.Output.precision.getPreference(preferences)))); + final ArrayAdapter adapter = makeNumberFormatAdapter(); + notationSpinner.setAdapter(adapter); + notationSpinner.setSelection(indexOf(adapter, Engine.Preferences.Output.notation.getPreference(preferences))); + } + + private int indexOf(ArrayAdapter adapter, Engine.Notation notation) { + for (int i = 0; i < adapter.getCount(); i++) { + if (adapter.getItem(i).notation == notation) { + return i; + } + } + return -1; + } + + @NonNull + private ArrayAdapter makeNumberFormatAdapter() { + final ArrayAdapter adapter = App.makeSimpleSpinnerAdapter(getContext()); + for (Engine.Notation format : Engine.Notation.values()) { + adapter.add(new NotationItem(format)); + } + adapter.sort(NaturalComparator.INSTANCE); + return adapter; + } + + private final class NotationItem { + @NonNull + final Engine.Notation notation; + @NonNull + final String name; + + private NotationItem(@NonNull Engine.Notation notation) { + this.notation = notation; + this.name = getContext().getString(notation.name); + } + + @Override + public String toString() { + return name; + } + } +} 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..b360c9e1 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,7 @@ import android.support.v4.app.FragmentActivity; import android.util.SparseArray; import android.view.View; import android.widget.ListView; + import org.solovyev.android.calculator.AdView; import org.solovyev.android.calculator.Engine; import org.solovyev.android.calculator.Preferences; @@ -24,11 +25,12 @@ import org.solovyev.android.checkout.ProductTypes; import org.solovyev.android.checkout.RequestListener; import org.solovyev.android.wizard.Wizards; +import java.util.Arrays; +import java.util.List; + import javax.annotation.Nonnull; import javax.annotation.Nullable; 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.wizard.CalculatorWizards.DEFAULT_WIZARD_FLOW; 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 { + public static final NaturalComparator INSTANCE = new NaturalComparator(); + + @Override + public int compare(Object lhs, Object rhs) { + return lhs.toString().compareTo(rhs.toString()); + } +} diff --git a/app/src/main/java/org/solovyev/android/views/DiscreteSeekBar.java b/app/src/main/java/org/solovyev/android/views/DiscreteSeekBar.java new file mode 100644 index 00000000..eed1180c --- /dev/null +++ b/app/src/main/java/org/solovyev/android/views/DiscreteSeekBar.java @@ -0,0 +1,224 @@ +package org.solovyev.android.views; + +import android.animation.ObjectAnimator; +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.os.Build; +import android.util.AttributeSet; +import android.view.animation.DecelerateInterpolator; +import android.widget.SeekBar; + +import org.solovyev.android.Check; +import org.solovyev.android.calculator.R; + +/** + * SeekBar for discrete values with a label displayed underneath the active tick + */ +public class DiscreteSeekBar extends SeekBar { + // Duration of how quick the SeekBar thumb should snap to its destination value + private static final int THUMB_SNAP_DURATION_TIME = 100; + private final Paint mPaint = new Paint(); + private ObjectAnimator mObjectAnimator; + private OnChangeListener mOnChangeListener; + private int mCurrentTick = 0; + private CharSequence[] mTickLabels; + private ColorStateList mLabelColor; + + public DiscreteSeekBar(Context context) { + super(context); + init(context, null, 0); + } + + public DiscreteSeekBar(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs, 0); + } + + public DiscreteSeekBar(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(context, attrs, defStyle); + } + + private void init(Context context, AttributeSet attrs, int defStyle) { + final TypedArray a = context.obtainStyledAttributes( + attrs, R.styleable.DiscreteSeekBar, defStyle, 0); + mTickLabels = a.getTextArray(R.styleable.DiscreteSeekBar_values); + final int labelsSize = a.getDimensionPixelSize(R.styleable.DiscreteSeekBar_labelsSize, 0); + final ColorStateList labelsColor = a.getColorStateList(R.styleable.DiscreteSeekBar_labelsColor); + a.recycle(); + + Check.isNotNull(mTickLabels); + Check.isTrue(mTickLabels.length > 0); + Check.isTrue(labelsSize > 0); + + mPaint.setStyle(Paint.Style.FILL); + mPaint.setFlags(Paint.ANTI_ALIAS_FLAG); + mPaint.setTextSize(labelsSize); + + if (labelsColor != null) { + setLabelColor(labelsColor); + } else { + mPaint.setColor(Color.BLACK); + } + + // Extend the bottom padding to include tick label height (including descent in order to not + // clip glyphs that extends below the baseline). + Paint.FontMetricsInt fi = mPaint.getFontMetricsInt(); + setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), + getPaddingBottom() + labelsSize + fi.descent); + + super.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + cancelAnimator(); + } + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + private void cancelAnimator() { + if (mObjectAnimator != null) { + mObjectAnimator.cancel(); + } + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + mCurrentTick = getClosestTick(seekBar.getProgress()); + final int endProgress = getProgressForTick(mCurrentTick); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + startAnimator(seekBar, endProgress); + } else { + seekBar.setProgress(endProgress); + } + if (mOnChangeListener != null) { + mOnChangeListener.onValueChanged(mCurrentTick); + } + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + private void startAnimator(SeekBar seekBar, int endProgress) { + mObjectAnimator = ObjectAnimator.ofInt( + seekBar, "progress", seekBar.getProgress(), endProgress); + mObjectAnimator.setInterpolator(new DecelerateInterpolator()); + mObjectAnimator.setDuration(THUMB_SNAP_DURATION_TIME); + mObjectAnimator.start(); + } + }); + } + + private int getClosestTick(int progress) { + float normalizedValue = (float) progress / getMax(); + return Math.round(normalizedValue * getMaxTick()); + } + + private int getProgressForTick(int tick) { + return (getMax() / getMaxTick()) * tick; + } + + @Override + public void setOnSeekBarChangeListener(OnSeekBarChangeListener seekBarChangeListener) { + // It doesn't make sense to expose the interface for listening to intermediate changes. + Check.isTrue(false); + } + + /** + * Get the largest tick value the SeekBar can represent + * + * @return maximum tick value + */ + public int getMaxTick() { + return mTickLabels.length - 1; + } + + /** + * Set listener for observing value changes + * + * @param onChangeListener listener that should receive updates + */ + public void setOnChangeListener(OnChangeListener onChangeListener) { + mOnChangeListener = onChangeListener; + } + + /** + * Set tick value + * + * @param tickValue tick value in range [0, maxTick] + */ + public void setTickValue(int tickValue) { + Check.isTrue(tickValue >= 0); + Check.isTrue(tickValue <= getMaxTick()); + mCurrentTick = tickValue; + setProgress(getProgressForTick(mCurrentTick)); + } + + public void setLabelColor(int color) { + mLabelColor = ColorStateList.valueOf(color); + updateLabelColor(); + } + + public void setLabelColor(ColorStateList colors) { + mLabelColor = colors; + updateLabelColor(); + } + + private void updateLabelColor() { + int color = mLabelColor.getColorForState(getDrawableState(), Color.BLACK); + if (color != mPaint.getColor()) { + mPaint.setColor(color); + invalidate(); + } + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + updateLabelColor(); + } + + @Override + public void onDraw(Canvas canvas) { + super.onDraw(canvas); + + final float sliderWidth = getWidth() - getPaddingRight() - getPaddingLeft(); + final float sliderStepSize = sliderWidth / getMaxTick(); + int closestTick = getClosestTick(getProgress()); + String text = mTickLabels[closestTick].toString(); + final float startOffset = getPaddingLeft(); + final float tickLabelWidth = mPaint.measureText(text); + final float tickPos = sliderStepSize * closestTick; + final float labelOffset; + // First step description text should be anchored with its left edge just + // below the slider start tick. The last step description should be anchored + // to the right just under the end tick. Tick labels in between are centered below + // each tick. + if (closestTick == 0) { + labelOffset = startOffset; + } else if (closestTick == getMaxTick()) { + labelOffset = startOffset + sliderWidth - tickLabelWidth; + } else { + labelOffset = startOffset + tickPos - tickLabelWidth / 2; + } + // Text position is drawn from bottom left, with bottom at the font baseline. We need to + // offset by the descent to cover e.g 'g' that extends below the baseline. + final Paint.FontMetricsInt m = mPaint.getFontMetricsInt(); + final int lowestPosForFullGlyphCoverage = getHeight() - m.descent; + canvas.drawText(text, labelOffset, lowestPosForFullGlyphCoverage, mPaint); + } + + /** + * Listener for observing tick changes + */ + public interface OnChangeListener { + void onValueChanged(int selectedTick); + } +} diff --git a/app/src/main/res/layout/fragment_plot_function_edit.xml b/app/src/main/res/layout/fragment_plot_function_edit.xml index cebfc31a..eecacbf3 100644 --- a/app/src/main/res/layout/fragment_plot_function_edit.xml +++ b/app/src/main/res/layout/fragment_plot_function_edit.xml @@ -59,11 +59,9 @@ @@ -74,11 +72,9 @@ diff --git a/app/src/main/res/layout/preference_number_format.xml b/app/src/main/res/layout/preference_number_format.xml new file mode 100644 index 00000000..fb1478ea --- /dev/null +++ b/app/src/main/res/layout/preference_number_format.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/attrs_dsb.xml b/app/src/main/res/values/attrs_dsb.xml new file mode 100644 index 00000000..1c26d503 --- /dev/null +++ b/app/src/main/res/values/attrs_dsb.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index b908d698..fcca4323 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -319,6 +319,11 @@ gone + + 16sp 14sp \ No newline at end of file diff --git a/app/src/main/res/values/text_non_translatable.xml b/app/src/main/res/values/text_non_translatable.xml index c7026931..85d6359d 100644 --- a/app/src/main/res/values/text_non_translatable.xml +++ b/app/src/main/res/values/text_non_translatable.xml @@ -34,6 +34,5 @@ 13 14 15 - 16 \ No newline at end of file diff --git a/app/src/main/res/values/text_strings.xml b/app/src/main/res/values/text_strings.xml index 1c1c5868..becee1e2 100644 --- a/app/src/main/res/values/text_strings.xml +++ b/app/src/main/res/values/text_strings.xml @@ -124,4 +124,7 @@ Angles Radix Numeral system + Simple + Engineering + Scientific diff --git a/app/src/main/res/xml/preferences_calculations.xml b/app/src/main/res/xml/preferences_calculations.xml index 4aeb0433..bffa19a4 100644 --- a/app/src/main/res/xml/preferences_calculations.xml +++ b/app/src/main/res/xml/preferences_calculations.xml @@ -24,11 +24,9 @@ - +