Conversion tool

This commit is contained in:
Sergey Solovyev
2012-04-22 00:37:41 +04:00
parent 94d67c1237
commit 8fee55a17e
17 changed files with 703 additions and 20 deletions

View File

@@ -0,0 +1,83 @@
package org.solovyev.android;
import jscl.NumeralBase;
import org.jetbrains.annotations.NotNull;
import java.math.BigInteger;
/**
* User: serso
* Date: 4/21/12
* Time: 8:00 PM
*/
public enum NumeralBaseUnitType implements UnitType<String> {
bin(NumeralBase.bin),
oct(NumeralBase.oct),
dec(NumeralBase.dec),
hex(NumeralBase.hex);
@NotNull
private final NumeralBase numeralBase;
private NumeralBaseUnitType(@NotNull NumeralBase numeralBase) {
this.numeralBase = numeralBase;
}
@NotNull
public Unit<String> createUnit(@NotNull String value) {
return UnitImpl.newInstance(value, this);
}
@NotNull
@Override
public Class<String> getUnitValueClass() {
return String.class;
}
@NotNull
private static final Converter converter = new Converter();
@NotNull
public static Converter getConverter() {
return converter;
}
public static class Converter implements UnitConverter<String> {
private Converter() {
}
@Override
public boolean isSupported(@NotNull UnitType<?> from, @NotNull UnitType<String> to) {
return NumeralBaseUnitType.class.isAssignableFrom(from.getClass()) && NumeralBaseUnitType.class.isAssignableFrom(to.getClass());
}
@NotNull
@Override
public Unit<String> convert(@NotNull Unit<?> from, @NotNull UnitType<String> toType) {
if (!isSupported(from.getUnitType(), toType)) {
throw new IllegalArgumentException("Types are not supported!");
}
final NumeralBaseUnitType fromType = (NumeralBaseUnitType) from.getUnitType();
final NumeralBase fromNumeralBase = fromType.numeralBase;
final NumeralBase toNumeralBase = ((NumeralBaseUnitType) toType).numeralBase;
final String fromValue = (String) from.getValue();
final BigInteger decBigInteger = fromNumeralBase.toBigInteger(fromValue);
return UnitImpl.newInstance(toNumeralBase.toString(decBigInteger), (NumeralBaseUnitType) toType);
}
}
@NotNull
public static NumeralBaseUnitType valueOf(@NotNull NumeralBase nb ) {
for (NumeralBaseUnitType numeralBaseUnitType : values()) {
if ( numeralBaseUnitType.numeralBase == nb ) {
return numeralBaseUnitType;
}
}
throw new IllegalArgumentException(nb + " is not supported numeral base!");
}
}

View File

@@ -0,0 +1,17 @@
package org.solovyev.android;
import org.jetbrains.annotations.NotNull;
/**
* User: serso
* Date: 4/21/12
* Time: 7:54 PM
*/
public interface Unit<V> {
@NotNull
V getValue();
@NotNull
UnitType<V> getUnitType();
}

View File

@@ -0,0 +1,42 @@
package org.solovyev.android;
import org.jetbrains.annotations.NotNull;
/**
* User: serso
* Date: 4/21/12
* Time: 7:53 PM
*/
public interface UnitConverter<T> {
boolean isSupported(@NotNull UnitType<?> from, @NotNull UnitType<T> to);
@NotNull
Unit<T> convert(@NotNull Unit<?> from, @NotNull UnitType<T> toType);
public static class Dummy implements UnitConverter<Object> {
@NotNull
private static final Dummy instance = new Dummy();
@NotNull
public static <T> UnitConverter<T> getInstance() {
return (UnitConverter<T>)instance;
}
private Dummy() {
}
@Override
public boolean isSupported(@NotNull UnitType<?> from, @NotNull UnitType<Object> to) {
return false;
}
@NotNull
@Override
public Unit<Object> convert(@NotNull Unit<?> from, @NotNull UnitType<Object> toType) {
throw new IllegalArgumentException();
}
}
}

View File

@@ -0,0 +1,42 @@
package org.solovyev.android;
import org.jetbrains.annotations.NotNull;
/**
* User: serso
* Date: 4/21/12
* Time: 8:01 PM
*/
public class UnitImpl<V> implements Unit<V> {
@NotNull
private V value;
@NotNull
private UnitType<V> unitType;
private UnitImpl() {
}
@NotNull
public static <V> Unit<V> newInstance(@NotNull V value, @NotNull UnitType<V> unitType) {
final UnitImpl<V> result = new UnitImpl<V>();
result.value = value;
result.unitType = unitType;
return result;
}
@NotNull
@Override
public V getValue() {
return this.value;
}
@NotNull
@Override
public UnitType<V> getUnitType() {
return unitType;
}
}

View File

@@ -0,0 +1,16 @@
package org.solovyev.android;
import org.jetbrains.annotations.NotNull;
/**
* User: serso
* Date: 4/21/12
* Time: 7:55 PM
*/
public interface UnitType<V> {
@NotNull
Class<V> getUnitValueClass();
boolean equals(@NotNull Object o);
}

View File

@@ -36,10 +36,7 @@ import org.solovyev.android.calculator.about.CalculatorReleaseNotesActivity;
import org.solovyev.android.calculator.history.CalculatorHistory;
import org.solovyev.android.calculator.history.CalculatorHistoryState;
import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.calculator.view.AngleUnitsButton;
import org.solovyev.android.calculator.view.CalculatorAdditionalTitle;
import org.solovyev.android.calculator.view.NumeralBasesButton;
import org.solovyev.android.calculator.view.OnDragListenerVibrator;
import org.solovyev.android.calculator.view.*;
import org.solovyev.android.history.HistoryDragProcessor;
import org.solovyev.android.view.ColorButton;
import org.solovyev.android.view.drag.*;
@@ -615,6 +612,10 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
CalculatorActivityLauncher.showHelp(this);
result = true;
break;
case R.id.main_menu_conversion_tool:
new NumeralBaseConverterDialog(null).show(this);
result = true;
break;
case R.id.main_menu_item_exit:
this.finish();
result = true;

View File

@@ -13,15 +13,14 @@ import android.util.Log;
import jscl.math.Generic;
import jscl.math.function.Constant;
import jscl.math.function.IConstant;
import jscl.math.numeric.Numeric;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.calculator.model.CalculatorParseException;
import org.solovyev.android.calculator.model.TextProcessor;
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
import org.solovyev.android.calculator.view.TextHighlighter;
import org.solovyev.android.calculator.view.UnitsConverter;
import org.solovyev.android.menu.AMenuItem;
import org.solovyev.android.view.AutoResizeTextView;
import org.solovyev.common.utils.CollectionsUtils;
@@ -48,8 +47,7 @@ public class CalculatorDisplay extends AutoResizeTextView implements ICalculator
convert(R.string.c_convert) {
@Override
public void doAction(@NotNull CalculatorDisplay data, @NotNull Context context) {
// todo serso: continue
new UnitsConverter();
new NumeralBaseConverterDialog(data.getGenericResult().toString()).show(context);
}
@Override

View File

@@ -394,7 +394,11 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
filteredMenuItems.add(menuItem);
}
}
AMenuBuilder.newInstance(activity, MenuImpl.newInstance(filteredMenuItems)).create(cd).show();
if (!filteredMenuItems.isEmpty()) {
AMenuBuilder.newInstance(activity, MenuImpl.newInstance(filteredMenuItems)).create(cd).show();
}
} else {
final String errorMessage = cd.getErrorMessage();
if (errorMessage != null) {

View File

@@ -0,0 +1,105 @@
package org.solovyev.android.calculator.view;
import android.app.AlertDialog;
import android.content.Context;
import android.view.View;
import android.view.WindowManager;
import jscl.NumeralBase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.NumeralBaseUnitType;
import org.solovyev.android.Unit;
import org.solovyev.android.UnitImpl;
import org.solovyev.android.calculator.CalculatorModel;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.calculator.model.CalculatorParseException;
import org.solovyev.android.calculator.model.ToJsclTextProcessor;
import org.solovyev.common.utils.MutableObject;
import org.solovyev.common.utils.StringUtils;
import java.util.Arrays;
/**
* User: serso
* Date: 4/22/12
* Time: 12:20 AM
*/
public class NumeralBaseConverterDialog {
@Nullable
private String initialFromValue;
public NumeralBaseConverterDialog(String initialFromValue) {
this.initialFromValue = initialFromValue;
}
public void show(@NotNull Context context) {
final UnitConverterViewBuilder b = new UnitConverterViewBuilder();
b.setFromUnitTypes(Arrays.asList(NumeralBaseUnitType.values()));
b.setToUnitTypes(Arrays.asList(NumeralBaseUnitType.values()));
if (!StringUtils.isEmpty(initialFromValue)) {
String value = initialFromValue;
try {
value = ToJsclTextProcessor.getInstance().process(value).getExpression();
b.setFromValue(UnitImpl.newInstance(value, NumeralBaseUnitType.valueOf(CalculatorEngine.instance.getEngine().getNumeralBase())));
} catch (CalculatorParseException e) {
b.setFromValue(UnitImpl.newInstance(value, NumeralBaseUnitType.valueOf(CalculatorEngine.instance.getEngine().getNumeralBase())));
}
} else {
b.setFromValue(UnitImpl.newInstance("", NumeralBaseUnitType.valueOf(CalculatorEngine.instance.getEngine().getNumeralBase())));
}
b.setConverter(NumeralBaseUnitType.getConverter());
final MutableObject<AlertDialog> alertDialogHolder = new MutableObject<AlertDialog>();
b.setOkButtonOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final AlertDialog alertDialog = alertDialogHolder.getObject();
if (alertDialog != null) {
alertDialog.dismiss();
}
}
});
b.setCustomButtonData(new UnitConverterViewBuilder.CustomButtonData(context.getString(R.string.c_use), new UnitConverterViewBuilder.CustomButtonOnClickListener() {
@Override
public void onClick(@NotNull Unit<String> fromUnits, @NotNull Unit<String> toUnits) {
String toUnitsValue = toUnits.getValue();
if (!toUnits.getUnitType().equals(NumeralBaseUnitType.valueOf(CalculatorEngine.instance.getEngine().getNumeralBase()))) {
for (NumeralBase nb : NumeralBase.values()) {
if (NumeralBaseUnitType.valueOf(nb).equals(toUnits.getUnitType())) {
toUnitsValue = nb.getJsclPrefix() + toUnitsValue;
break;
}
}
}
CalculatorModel.instance.processDigitButtonAction(toUnitsValue, false);
final AlertDialog alertDialog = alertDialogHolder.getObject();
if (alertDialog != null) {
alertDialog.dismiss();
}
}
}));
final AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
alertBuilder.setView(b.build(context));
alertBuilder.setTitle(R.string.c_conversion_tool);
final AlertDialog alertDialog = alertBuilder.create();
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(alertDialog.getWindow().getAttributes());
lp.width = WindowManager.LayoutParams.FILL_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
alertDialogHolder.setObject(alertDialog);
alertDialog.show();
alertDialog.getWindow().setAttributes(lp);
}
}

View File

@@ -0,0 +1,236 @@
package org.solovyev.android.calculator.view;
import android.app.Activity;
import android.content.Context;
import android.text.ClipboardManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.Unit;
import org.solovyev.android.UnitConverter;
import org.solovyev.android.UnitImpl;
import org.solovyev.android.UnitType;
import org.solovyev.android.calculator.R;
import org.solovyev.android.view.ViewBuilder;
import org.solovyev.android.view.ViewFromLayoutBuilder;
import org.solovyev.common.utils.StringUtils;
import java.util.Collections;
import java.util.List;
/**
* User: serso
* Date: 4/20/12
* Time: 4:50 PM
*/
public class UnitConverterViewBuilder implements ViewBuilder<View> {
@NotNull
private List<? extends UnitType<String>> fromUnitTypes = Collections.emptyList();
@NotNull
private List<? extends UnitType<String>> toUnitTypes = Collections.emptyList();
@Nullable
private Unit<String> fromValue;
@NotNull
private UnitConverter<String> converter = UnitConverter.Dummy.getInstance();
@Nullable
private View.OnClickListener okButtonOnClickListener;
@Nullable
private CustomButtonData customButtonData;
public void setFromUnitTypes(@NotNull List<? extends UnitType<String>> fromUnitTypes) {
this.fromUnitTypes = fromUnitTypes;
}
public void setToUnitTypes(@NotNull List<? extends UnitType<String>> toUnitTypes) {
this.toUnitTypes = toUnitTypes;
}
public void setFromValue(@Nullable Unit<String> fromValue) {
this.fromValue = fromValue;
}
public void setConverter(@NotNull UnitConverter<String> converter) {
this.converter = converter;
}
public void setOkButtonOnClickListener(@Nullable View.OnClickListener okButtonOnClickListener) {
this.okButtonOnClickListener = okButtonOnClickListener;
}
public void setCustomButtonData(@Nullable CustomButtonData customButtonData) {
this.customButtonData = customButtonData;
}
@NotNull
@Override
public View build(@NotNull final Context context) {
final View main = ViewFromLayoutBuilder.newInstance(R.layout.unit_converter).build(context);
final Spinner fromSpinner = (Spinner) main.findViewById(R.id.unit_types_from);
final EditText fromEditText = (EditText) main.findViewById(R.id.units_from);
fromEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
doConversion(main, context, UnitConverterViewBuilder.this.converter);
}
});
fillSpinner(main, context, R.id.unit_types_from, fromUnitTypes);
fillSpinner(main, context, R.id.unit_types_to, toUnitTypes);
if (fromValue != null) {
fromEditText.setText(fromValue.getValue());
int i = fromUnitTypes.indexOf(fromValue.getUnitType());
if ( i >= 0 ) {
fromSpinner.setSelection(i);
}
}
final Button copyButton = (Button) main.findViewById(R.id.unit_converter_copy_button);
copyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final EditText toEditText = (EditText) main.findViewById(R.id.units_to);
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
clipboard.setText(toEditText.getText().toString());
Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show();
}
});
final Button okButton = (Button) main.findViewById(R.id.unit_converter_ok_button);
if ( okButtonOnClickListener == null ) {
((ViewGroup) okButton.getParent()).removeView(okButton);
} else {
okButton.setOnClickListener(this.okButtonOnClickListener);
}
final Button customButton = (Button) main.findViewById(R.id.unit_converter_custom_button);
if ( customButtonData == null ) {
((ViewGroup) customButton.getParent()).removeView(customButton);
} else {
customButton.setText(customButtonData.text);
customButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
customButtonData.clickListener.onClick(getFromUnit(main), getToUnit(main));
}
});
}
return main;
}
private void fillSpinner(@NotNull final View main,
@NotNull final Context context,
final int spinnerId,
@NotNull List<? extends UnitType<String>> unitTypes) {
final Spinner spinner = (Spinner) main.findViewById(spinnerId);
final ArrayAdapter<UnitType<String>> adapter = new ArrayAdapter<UnitType<String>>(context, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
for (UnitType<String> fromUnitType : unitTypes) {
adapter.add(fromUnitType);
}
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
doConversion(main, context, UnitConverterViewBuilder.this.converter);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
spinner.setAdapter(adapter);
}
private static void doConversion(@NotNull View main, @NotNull Context context, @NotNull UnitConverter<String> converter) {
final EditText fromEditText = (EditText) main.findViewById(R.id.units_from);
final EditText toEditText = (EditText) main.findViewById(R.id.units_to);
final String from = fromEditText.getText().toString();
if (StringUtils.isEmpty(from)) {
toEditText.setText("");
} else {
final UnitType<String> fromUnitType = getFromUnitType(main);
final UnitType<String> toUnitType = getToUnitType(main);
String to = null;
try {
if (converter.isSupported(fromUnitType, toUnitType)) {
to = converter.convert(UnitImpl.newInstance(from, fromUnitType), toUnitType).getValue();
}
} catch (RuntimeException e) {
to = context.getString(R.string.c_error);
}
toEditText.setText(to);
}
}
@NotNull
private static Unit<String> getToUnit(@NotNull View main) {
final EditText toUnits = (EditText) main.findViewById(R.id.units_to);
return UnitImpl.newInstance(toUnits.getText().toString(), getToUnitType(main));
}
@NotNull
private static UnitType<String> getToUnitType(@NotNull View main) {
final Spinner toSpinner = (Spinner) main.findViewById(R.id.unit_types_to);
return (UnitType<String>) toSpinner.getSelectedItem();
}
@NotNull
private static Unit<String> getFromUnit(@NotNull View main) {
final EditText fromUnits = (EditText) main.findViewById(R.id.units_from);
return UnitImpl.newInstance(fromUnits.getText().toString(), getFromUnitType(main));
}
@NotNull
private static UnitType<String> getFromUnitType(@NotNull View main) {
final Spinner fromSpinner = (Spinner) main.findViewById(R.id.unit_types_from);
return (UnitType<String>) fromSpinner.getSelectedItem();
}
public static class CustomButtonData {
@NotNull
private String text;
@NotNull
private CustomButtonOnClickListener clickListener;
public CustomButtonData(@NotNull String text, @NotNull CustomButtonOnClickListener clickListener) {
this.text = text;
this.clickListener = clickListener;
}
}
public static interface CustomButtonOnClickListener {
void onClick(@NotNull Unit<String> fromUnits, @NotNull Unit<String> toUnits);
}
}

View File

@@ -1,9 +0,0 @@
package org.solovyev.android.calculator.view;
/**
* User: serso
* Date: 4/20/12
* Time: 4:50 PM
*/
public class UnitsConverter {
}