Unit converter refactor
This commit is contained in:
parent
8f640ecb33
commit
71a75947f3
@ -8,7 +8,7 @@ import javax.annotation.Nonnull;
|
|||||||
import javax.measure.unit.Unit;
|
import javax.measure.unit.Unit;
|
||||||
|
|
||||||
final class Converter {
|
final class Converter {
|
||||||
static int unitName(@Nonnull Unit unit, @Nonnull NamedDimension dimension) {
|
static int unitName(@Nonnull Unit unit, @Nonnull UnitDimension dimension) {
|
||||||
final String id = Strings.nullToEmpty(unit.toString());
|
final String id = Strings.nullToEmpty(unit.toString());
|
||||||
switch (dimension) {
|
switch (dimension) {
|
||||||
case TIME:
|
case TIME:
|
||||||
|
@ -6,7 +6,6 @@ import android.content.DialogInterface;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.annotation.StringRes;
|
|
||||||
import android.support.design.widget.TextInputLayout;
|
import android.support.design.widget.TextInputLayout;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.FragmentActivity;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
@ -20,41 +19,20 @@ import android.view.inputmethod.EditorInfo;
|
|||||||
import android.widget.*;
|
import android.widget.*;
|
||||||
import butterknife.Bind;
|
import butterknife.Bind;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import jscl.JsclMathEngine;
|
|
||||||
import jscl.NumeralBase;
|
|
||||||
import midpcalc.Real;
|
|
||||||
import org.solovyev.android.calculator.*;
|
import org.solovyev.android.calculator.*;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.measure.converter.UnitConverter;
|
import java.util.Comparator;
|
||||||
import javax.measure.unit.NonSI;
|
|
||||||
import javax.measure.unit.SI;
|
|
||||||
import javax.measure.unit.Unit;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class ConverterFragment extends BaseDialogFragment
|
public class ConverterFragment extends BaseDialogFragment
|
||||||
implements AdapterView.OnItemSelectedListener, View.OnFocusChangeListener, TextView.OnEditorActionListener, View.OnClickListener, TextWatcher {
|
implements AdapterView.OnItemSelectedListener, View.OnFocusChangeListener, TextView.OnEditorActionListener, View.OnClickListener, TextWatcher {
|
||||||
|
|
||||||
// todo serso: better to provide a dimension-id pair as units might not be unique in different dimensions
|
|
||||||
@NonNull
|
|
||||||
private static final Set<String> excludedUnits = new HashSet<>(Arrays.asList("year_sidereal", "year_calendar", "day_sidereal", "foot_survey_us", "me", "u"));
|
|
||||||
@NonNull
|
|
||||||
private static final Map<NamedDimension, List<MyUnit>> units = new HashMap<>();
|
|
||||||
private static final String STATE_SELECTION_FROM = "selection.from";
|
private static final String STATE_SELECTION_FROM = "selection.from";
|
||||||
private static final String STATE_SELECTION_TO = "selection.to";
|
private static final String STATE_SELECTION_TO = "selection.to";
|
||||||
private static final String EXTRA_VALUE = "value";
|
private static final String EXTRA_VALUE = "value";
|
||||||
private static final NamedItemComparator COMPARATOR = new NamedItemComparator();
|
private static final NamedItemComparator COMPARATOR = new NamedItemComparator();
|
||||||
|
|
||||||
static {
|
|
||||||
for (Unit<?> unit : SI.getInstance().getUnits()) {
|
|
||||||
addUnit(unit);
|
|
||||||
}
|
|
||||||
for (Unit<?> unit : NonSI.getInstance().getUnits()) {
|
|
||||||
addUnit(unit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Clipboard clipboard;
|
Clipboard clipboard;
|
||||||
@Inject
|
@Inject
|
||||||
@ -75,31 +53,13 @@ public class ConverterFragment extends BaseDialogFragment
|
|||||||
EditText editTextTo;
|
EditText editTextTo;
|
||||||
@Bind(R.id.converter_swap_button)
|
@Bind(R.id.converter_swap_button)
|
||||||
ImageButton swapButton;
|
ImageButton swapButton;
|
||||||
private ArrayAdapter<NamedItem<NamedDimension>> dimensionsAdapter;
|
private ArrayAdapter<Named<ConvertibleDimension>> dimensionsAdapter;
|
||||||
private ArrayAdapter<NamedItem<MyUnit>> adapterFrom;
|
private ArrayAdapter<Named<Convertible>> adapterFrom;
|
||||||
private ArrayAdapter<NamedItem<MyUnit>> adapterTo;
|
private ArrayAdapter<Named<Convertible>> adapterTo;
|
||||||
|
|
||||||
private int pendingFromSelection = View.NO_ID;
|
private int pendingFromSelection = View.NO_ID;
|
||||||
private int pendingToSelection = View.NO_ID;
|
private int pendingToSelection = View.NO_ID;
|
||||||
|
|
||||||
private static void addUnit(@NonNull Unit<?> unit) {
|
|
||||||
if (excludedUnits.contains(unit.toString())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final NamedDimension dimension = NamedDimension.of(unit);
|
|
||||||
if (dimension == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<MyUnit> unitsInDimension = units.get(dimension);
|
|
||||||
if (unitsInDimension == null) {
|
|
||||||
unitsInDimension = new ArrayList<>();
|
|
||||||
units.put(dimension, unitsInDimension);
|
|
||||||
}
|
|
||||||
unitsInDimension.add(MeasureUnit.create(unit));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void show(@Nonnull FragmentActivity activity) {
|
public static void show(@Nonnull FragmentActivity activity) {
|
||||||
show(activity, 1d);
|
show(activity, 1d);
|
||||||
}
|
}
|
||||||
@ -117,11 +77,6 @@ public class ConverterFragment extends BaseDialogFragment
|
|||||||
return new ArrayAdapter<>(context, R.layout.support_simple_spinner_dropdown_item);
|
return new ArrayAdapter<>(context, R.layout.support_simple_spinner_dropdown_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private static <T> NamedItem<T> createNamedItem(@NonNull T item, @StringRes int name, @NonNull Context context) {
|
|
||||||
return new NamedItem<>(item, name == 0 ? item.toString() : context.getString(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPrepareDialog(@NonNull AlertDialog.Builder builder) {
|
protected void onPrepareDialog(@NonNull AlertDialog.Builder builder) {
|
||||||
builder.setPositiveButton(R.string.c_use, null);
|
builder.setPositiveButton(R.string.c_use, null);
|
||||||
@ -144,9 +99,10 @@ public class ConverterFragment extends BaseDialogFragment
|
|||||||
ButterKnife.bind(this, view);
|
ButterKnife.bind(this, view);
|
||||||
|
|
||||||
dimensionsAdapter = makeAdapter(context);
|
dimensionsAdapter = makeAdapter(context);
|
||||||
for (NamedDimension dimension : NamedDimension.values()) {
|
for (ConvertibleDimension dimension : UnitDimension.values()) {
|
||||||
dimensionsAdapter.add(named(dimension));
|
dimensionsAdapter.add(dimension.named(context));
|
||||||
}
|
}
|
||||||
|
dimensionsAdapter.add(NumeralBaseDimension.get().named(context));
|
||||||
adapterFrom = makeAdapter(context);
|
adapterFrom = makeAdapter(context);
|
||||||
adapterTo = makeAdapter(context);
|
adapterTo = makeAdapter(context);
|
||||||
|
|
||||||
@ -176,11 +132,6 @@ public class ConverterFragment extends BaseDialogFragment
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private NamedItem<NamedDimension> named(@Nonnull NamedDimension dimension) {
|
|
||||||
return createNamedItem(dimension, dimension.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
@ -203,22 +154,22 @@ public class ConverterFragment extends BaseDialogFragment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onUnitFromChanged(@NonNull MyUnit unit) {
|
private void onUnitFromChanged(@NonNull Convertible unit) {
|
||||||
final int dimensionPosition = dimensionsSpinner.getSelectedItemPosition();
|
final int dimensionPosition = dimensionsSpinner.getSelectedItemPosition();
|
||||||
updateUnitsTo(dimensionsAdapter.getItem(dimensionPosition).item, unit);
|
updateUnitsTo(dimensionsAdapter.getItem(dimensionPosition).item, unit);
|
||||||
convert();
|
convert();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onDimensionChanged(@NonNull NamedDimension dimension) {
|
private void onDimensionChanged(@NonNull ConvertibleDimension dimension) {
|
||||||
updateUnitsFrom(dimension);
|
updateUnitsFrom(dimension);
|
||||||
updateUnitsTo(dimension, adapterFrom.getItem(spinnerFrom.getSelectedItemPosition()).item);
|
updateUnitsTo(dimension, adapterFrom.getItem(spinnerFrom.getSelectedItemPosition()).item);
|
||||||
convert();
|
convert();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateUnitsFrom(@NonNull NamedDimension dimension) {
|
private void updateUnitsFrom(@NonNull ConvertibleDimension dimension) {
|
||||||
adapterFrom.setNotifyOnChange(false);
|
adapterFrom.setNotifyOnChange(false);
|
||||||
adapterFrom.clear();
|
adapterFrom.clear();
|
||||||
for (MyUnit unit : units.get(dimension)) {
|
for (Convertible unit : dimension.getUnits()) {
|
||||||
adapterFrom.add(unit.named(getActivity()));
|
adapterFrom.add(unit.named(getActivity()));
|
||||||
}
|
}
|
||||||
adapterFrom.sort(COMPARATOR);
|
adapterFrom.sort(COMPARATOR);
|
||||||
@ -228,8 +179,8 @@ public class ConverterFragment extends BaseDialogFragment
|
|||||||
pendingFromSelection = View.NO_ID;
|
pendingFromSelection = View.NO_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateUnitsTo(@NonNull NamedDimension dimension, @NonNull MyUnit except) {
|
private void updateUnitsTo(@NonNull ConvertibleDimension dimension, @NonNull Convertible except) {
|
||||||
final MyUnit selectedUnit;
|
final Convertible selectedUnit;
|
||||||
if (pendingToSelection > View.NO_ID) {
|
if (pendingToSelection > View.NO_ID) {
|
||||||
selectedUnit = null;
|
selectedUnit = null;
|
||||||
} else {
|
} else {
|
||||||
@ -238,7 +189,7 @@ public class ConverterFragment extends BaseDialogFragment
|
|||||||
}
|
}
|
||||||
adapterTo.setNotifyOnChange(false);
|
adapterTo.setNotifyOnChange(false);
|
||||||
adapterTo.clear();
|
adapterTo.clear();
|
||||||
for (MyUnit unit : units.get(dimension)) {
|
for (Convertible unit : dimension.getUnits()) {
|
||||||
if (!except.equals(unit)) {
|
if (!except.equals(unit)) {
|
||||||
adapterTo.add(unit.named(getActivity()));
|
adapterTo.add(unit.named(getActivity()));
|
||||||
}
|
}
|
||||||
@ -248,7 +199,7 @@ public class ConverterFragment extends BaseDialogFragment
|
|||||||
adapterTo.notifyDataSetChanged();
|
adapterTo.notifyDataSetChanged();
|
||||||
if (selectedUnit != null && !except.equals(selectedUnit)) {
|
if (selectedUnit != null && !except.equals(selectedUnit)) {
|
||||||
for (int i = 0; i < adapterTo.getCount(); i++) {
|
for (int i = 0; i < adapterTo.getCount(); i++) {
|
||||||
final MyUnit unit = adapterTo.getItem(i).item;
|
final Convertible unit = adapterTo.getItem(i).item;
|
||||||
if (unit.equals(selectedUnit)) {
|
if (unit.equals(selectedUnit)) {
|
||||||
spinnerTo.setSelection(i);
|
spinnerTo.setSelection(i);
|
||||||
return;
|
return;
|
||||||
@ -290,11 +241,9 @@ public class ConverterFragment extends BaseDialogFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final MyUnit from = adapterFrom.getItem(spinnerFrom.getSelectedItemPosition()).item;
|
final Convertible from = adapterFrom.getItem(spinnerFrom.getSelectedItemPosition()).item;
|
||||||
final Object fromValue = from.parse(value);
|
final Convertible to = adapterTo.getItem(spinnerTo.getSelectedItemPosition()).item;
|
||||||
final MyUnit to = adapterTo.getItem(spinnerTo.getSelectedItemPosition()).item;
|
editTextTo.setText(from.convert(to, value));
|
||||||
final Object toValue = from.getConverterTo(to).convert(fromValue);
|
|
||||||
editTextTo.setText(to.format(toValue));
|
|
||||||
clearError(labelFrom);
|
clearError(labelFrom);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
if (validate) {
|
if (validate) {
|
||||||
@ -354,13 +303,13 @@ public class ConverterFragment extends BaseDialogFragment
|
|||||||
|
|
||||||
private void swap() {
|
private void swap() {
|
||||||
editTextFrom.setText(editTextTo.getText());
|
editTextFrom.setText(editTextTo.getText());
|
||||||
final MyUnit oldFromUnit = adapterFrom.getItem(spinnerFrom.getSelectedItemPosition()).item;
|
final Convertible oldFromUnit = adapterFrom.getItem(spinnerFrom.getSelectedItemPosition()).item;
|
||||||
final MyUnit oldToUnit = adapterTo.getItem(spinnerTo.getSelectedItemPosition()).item;
|
final Convertible oldToUnit = adapterTo.getItem(spinnerTo.getSelectedItemPosition()).item;
|
||||||
|
|
||||||
pendingToSelection = -1;
|
pendingToSelection = -1;
|
||||||
for (int i = 0; i < adapterFrom.getCount(); i++) {
|
for (int i = 0; i < adapterFrom.getCount(); i++) {
|
||||||
pendingToSelection++;
|
pendingToSelection++;
|
||||||
final MyUnit unit = adapterFrom.getItem(i).item;
|
final Convertible unit = adapterFrom.getItem(i).item;
|
||||||
if (unit.equals(oldToUnit)) {
|
if (unit.equals(oldToUnit)) {
|
||||||
pendingToSelection--;
|
pendingToSelection--;
|
||||||
} else if (unit.equals(oldFromUnit)) {
|
} else if (unit.equals(oldFromUnit)) {
|
||||||
@ -369,7 +318,7 @@ public class ConverterFragment extends BaseDialogFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < adapterFrom.getCount(); i++) {
|
for (int i = 0; i < adapterFrom.getCount(); i++) {
|
||||||
final MyUnit unit = adapterFrom.getItem(i).item;
|
final Convertible unit = adapterFrom.getItem(i).item;
|
||||||
if (unit.equals(oldToUnit)) {
|
if (unit.equals(oldToUnit)) {
|
||||||
spinnerFrom.setSelection(i);
|
spinnerFrom.setSelection(i);
|
||||||
break;
|
break;
|
||||||
@ -398,122 +347,10 @@ public class ConverterFragment extends BaseDialogFragment
|
|||||||
super.dismiss();
|
super.dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
private static class NamedItemComparator implements Comparator<Named<Convertible>> {
|
||||||
private <T> NamedItem<T> createNamedItem(@NonNull T item, @StringRes int name) {
|
|
||||||
return createNamedItem(item, name, getActivity());
|
|
||||||
}
|
|
||||||
|
|
||||||
private interface MyUnit {
|
|
||||||
@NonNull
|
|
||||||
Object parse(@NonNull String value);
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
String format(@NonNull Object value);
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
MyConverter getConverterTo(@NonNull MyUnit to);
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
NamedItem<MyUnit> named(@NonNull Context context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private interface MyConverter {
|
|
||||||
Object convert(Object value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class NamedItem<T> {
|
|
||||||
@NonNull
|
|
||||||
public final T item;
|
|
||||||
@NonNull
|
|
||||||
public final CharSequence name;
|
|
||||||
|
|
||||||
private NamedItem(@NonNull T item, @Nonnull String name) {
|
|
||||||
this.item = item;
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public int compare(Named<Convertible> lhs, Named<Convertible> rhs) {
|
||||||
return name.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class NamedItemComparator implements Comparator<NamedItem<MyUnit>> {
|
|
||||||
@Override
|
|
||||||
public int compare(NamedItem<MyUnit> lhs, NamedItem<MyUnit> rhs) {
|
|
||||||
return lhs.toString().compareTo(rhs.toString());
|
return lhs.toString().compareTo(rhs.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class MeasureUnit implements MyUnit {
|
|
||||||
@NonNull
|
|
||||||
final Unit unit;
|
|
||||||
|
|
||||||
private MeasureUnit(@NonNull Unit unit) {
|
|
||||||
this.unit = unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MeasureUnit create(@NonNull Unit unit) {
|
|
||||||
return new MeasureUnit(unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return unit.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public Object parse(@NonNull String value) {
|
|
||||||
final String groupingSeparator = String.valueOf(JsclMathEngine.getInstance().getGroupingSeparator());
|
|
||||||
if (!TextUtils.isEmpty(groupingSeparator)) {
|
|
||||||
value = value.replace(groupingSeparator, "");
|
|
||||||
}
|
|
||||||
final long bits = new Real(value).toDoubleBits();
|
|
||||||
return Double.longBitsToDouble(bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public String format(@NonNull Object value) {
|
|
||||||
return JsclMathEngine.getInstance().format((Double) value, NumeralBase.dec);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public MyConverter getConverterTo(@NonNull final MyUnit to) {
|
|
||||||
return new MyConverter() {
|
|
||||||
@Override
|
|
||||||
public Object convert(Object value) {
|
|
||||||
final UnitConverter converter = unit.getConverterTo(((MeasureUnit) to).unit);
|
|
||||||
return converter.convert((Double) value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public NamedItem<MyUnit> named(@Nonnull Context context) {
|
|
||||||
final NamedDimension dimension = NamedDimension.of(unit);
|
|
||||||
if (dimension == null) {
|
|
||||||
return createNamedItem((MyUnit) MeasureUnit.create(unit), 0, context);
|
|
||||||
}
|
|
||||||
return createNamedItem((MyUnit) MeasureUnit.create(unit), Converter.unitName(unit, dimension), context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
|
|
||||||
final MeasureUnit that = (MeasureUnit) o;
|
|
||||||
return unit.equals(that.unit);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return unit.hashCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package org.solovyev.android.calculator.converter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
interface Convertible {
|
||||||
|
@NonNull
|
||||||
|
String convert(@NonNull Convertible to, @NonNull String value);
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
Named<Convertible> named(@NonNull Context context);
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package org.solovyev.android.calculator.converter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface ConvertibleDimension {
|
||||||
|
@NonNull
|
||||||
|
Named<ConvertibleDimension> named(@NonNull Context context);
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
List<Convertible> getUnits();
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package org.solovyev.android.calculator.converter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.StringRes;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
class Named<T> {
|
||||||
|
@NonNull
|
||||||
|
public final T item;
|
||||||
|
@NonNull
|
||||||
|
public final CharSequence name;
|
||||||
|
|
||||||
|
private Named(@NonNull T item, @Nonnull String name) {
|
||||||
|
this.item = item;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
static <T> Named<T> create(@NonNull T item, @Nonnull String name) {
|
||||||
|
return new Named<T>(item, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
static <T> Named<T> create(@NonNull T item, @StringRes int name, @NonNull Context context) {
|
||||||
|
return create(item, name == 0 ? item.toString() : context.getString(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
final Named<?> that = (Named<?>) o;
|
||||||
|
return item.equals(that.item);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return item.hashCode();
|
||||||
|
}
|
||||||
|
}
|
@ -1,38 +0,0 @@
|
|||||||
package org.solovyev.android.calculator.converter;
|
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.annotation.StringRes;
|
|
||||||
import org.solovyev.android.calculator.R;
|
|
||||||
|
|
||||||
import javax.measure.unit.Dimension;
|
|
||||||
import javax.measure.unit.Unit;
|
|
||||||
|
|
||||||
enum NamedDimension {
|
|
||||||
TIME(Dimension.TIME, R.string.cpp_converter_time),
|
|
||||||
AMOUNT_OF_SUBSTANCE(Dimension.AMOUNT_OF_SUBSTANCE, R.string.cpp_converter_amount_of_substance),
|
|
||||||
ELECTRIC_CURRENT(Dimension.ELECTRIC_CURRENT, R.string.cpp_converter_electric_current),
|
|
||||||
LENGTH(Dimension.LENGTH, R.string.cpp_converter_length),
|
|
||||||
MASS(Dimension.MASS, R.string.cpp_converter_mass),
|
|
||||||
TEMPERATURE(Dimension.TEMPERATURE, R.string.cpp_converter_temperature);
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public final Dimension dimension;
|
|
||||||
@StringRes
|
|
||||||
public final int name;
|
|
||||||
|
|
||||||
NamedDimension(@NonNull Dimension dimension, @StringRes int name) {
|
|
||||||
this.dimension = dimension;
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static NamedDimension of(@NonNull Unit<?> unit) {
|
|
||||||
for (NamedDimension myDimension : values()) {
|
|
||||||
if (myDimension.dimension.equals(unit.getDimension())) {
|
|
||||||
return myDimension;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,32 @@
|
|||||||
|
package org.solovyev.android.calculator.converter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import jscl.NumeralBase;
|
||||||
|
|
||||||
|
public class NumeralBaseConvertible implements Convertible {
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private final NumeralBase base;
|
||||||
|
|
||||||
|
public NumeralBaseConvertible(@NonNull NumeralBase base) {
|
||||||
|
this.base = base;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String convert(@NonNull Convertible to, @NonNull String value) {
|
||||||
|
try {
|
||||||
|
base.toBigInteger(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Named<Convertible> named(@NonNull Context context) {
|
||||||
|
return Named.<Convertible>create(this, base.name());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package org.solovyev.android.calculator.converter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import jscl.NumeralBase;
|
||||||
|
import org.solovyev.android.calculator.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class NumeralBaseDimension implements ConvertibleDimension {
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private static final NumeralBaseDimension INSTANCE = new NumeralBaseDimension();
|
||||||
|
@NonNull
|
||||||
|
private final List<Convertible> units = new ArrayList<>();
|
||||||
|
|
||||||
|
{
|
||||||
|
for (NumeralBase base : NumeralBase.values()) {
|
||||||
|
units.add(new NumeralBaseConvertible(base));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private NumeralBaseDimension() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static ConvertibleDimension get() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Named<ConvertibleDimension> named(@NonNull Context context) {
|
||||||
|
return Named.<ConvertibleDimension>create(this, R.string.cpp_radix, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public List<Convertible> getUnits() {
|
||||||
|
return units;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
package org.solovyev.android.calculator.converter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import jscl.JsclMathEngine;
|
||||||
|
import jscl.NumeralBase;
|
||||||
|
import midpcalc.Real;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.measure.unit.Unit;
|
||||||
|
|
||||||
|
final class UnitConvertible implements Convertible {
|
||||||
|
@NonNull
|
||||||
|
private final Unit unit;
|
||||||
|
|
||||||
|
private UnitConvertible(@NonNull Unit unit) {
|
||||||
|
this.unit = unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
static UnitConvertible create(@NonNull Unit unit) {
|
||||||
|
return new UnitConvertible(unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return unit.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double parse(@NonNull String value) {
|
||||||
|
final String groupingSeparator = String.valueOf(JsclMathEngine.getInstance().getGroupingSeparator());
|
||||||
|
if (!TextUtils.isEmpty(groupingSeparator)) {
|
||||||
|
value = value.replace(groupingSeparator, "");
|
||||||
|
}
|
||||||
|
final long bits = new Real(value).toDoubleBits();
|
||||||
|
return Double.longBitsToDouble(bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public String format(double value) {
|
||||||
|
return JsclMathEngine.getInstance().format(value, NumeralBase.dec);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String convert(@NonNull Convertible to, @NonNull String value) {
|
||||||
|
final double from = parse(value);
|
||||||
|
final double converted = unit.getConverterTo(((UnitConvertible) to).unit).convert(from);
|
||||||
|
return format(converted);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Named<Convertible> named(@Nonnull Context context) {
|
||||||
|
final UnitDimension dimension = UnitDimension.of(unit);
|
||||||
|
if (dimension == null) {
|
||||||
|
return Named.<Convertible>create(this, 0, context);
|
||||||
|
}
|
||||||
|
return Named.<Convertible>create(this, Converter.unitName(unit, dimension), context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
final UnitConvertible that = (UnitConvertible) o;
|
||||||
|
return unit.equals(that.unit);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return unit.hashCode();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package org.solovyev.android.calculator.converter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.annotation.StringRes;
|
||||||
|
import org.solovyev.android.calculator.R;
|
||||||
|
|
||||||
|
import javax.measure.unit.Dimension;
|
||||||
|
import javax.measure.unit.NonSI;
|
||||||
|
import javax.measure.unit.SI;
|
||||||
|
import javax.measure.unit.Unit;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
enum UnitDimension implements ConvertibleDimension {
|
||||||
|
TIME(Dimension.TIME, R.string.cpp_converter_time),
|
||||||
|
AMOUNT_OF_SUBSTANCE(Dimension.AMOUNT_OF_SUBSTANCE, R.string.cpp_converter_amount_of_substance),
|
||||||
|
ELECTRIC_CURRENT(Dimension.ELECTRIC_CURRENT, R.string.cpp_converter_electric_current),
|
||||||
|
LENGTH(Dimension.LENGTH, R.string.cpp_converter_length),
|
||||||
|
MASS(Dimension.MASS, R.string.cpp_converter_mass),
|
||||||
|
TEMPERATURE(Dimension.TEMPERATURE, R.string.cpp_converter_temperature);
|
||||||
|
|
||||||
|
// todo serso: better to provide a dimension-id pair as units might not be unique in different dimensions
|
||||||
|
@NonNull
|
||||||
|
private static final Set<String> excludedUnits = new HashSet<>(Arrays.asList("year_sidereal", "year_calendar", "day_sidereal", "foot_survey_us", "me", "u"));
|
||||||
|
@NonNull
|
||||||
|
private static final Map<Dimension, List<Convertible>> units = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
for (Unit<?> unit : SI.getInstance().getUnits()) {
|
||||||
|
addUnit(unit);
|
||||||
|
}
|
||||||
|
for (Unit<?> unit : NonSI.getInstance().getUnits()) {
|
||||||
|
addUnit(unit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public final Dimension dimension;
|
||||||
|
@StringRes
|
||||||
|
public final int name;
|
||||||
|
UnitDimension(@NonNull Dimension dimension, @StringRes int name) {
|
||||||
|
this.dimension = dimension;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addUnit(@NonNull Unit<?> unit) {
|
||||||
|
if (excludedUnits.contains(unit.toString())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Dimension dimension = unit.getDimension();
|
||||||
|
List<Convertible> unitsInDimension = units.get(dimension);
|
||||||
|
if (unitsInDimension == null) {
|
||||||
|
unitsInDimension = new ArrayList<>();
|
||||||
|
units.put(dimension, unitsInDimension);
|
||||||
|
}
|
||||||
|
unitsInDimension.add(UnitConvertible.create(unit));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static UnitDimension of(@NonNull Unit<?> unit) {
|
||||||
|
for (UnitDimension myDimension : values()) {
|
||||||
|
if (myDimension.dimension.equals(unit.getDimension())) {
|
||||||
|
return myDimension;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Named<ConvertibleDimension> named(@NonNull Context context) {
|
||||||
|
return Named.<ConvertibleDimension>create(this, name, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public List<Convertible> getUnits() {
|
||||||
|
return units.get(dimension);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user