Calculator display changes

This commit is contained in:
Sergey Solovyev 2012-09-21 00:36:52 +04:00
parent 79e85ea255
commit b3cc081f47
12 changed files with 446 additions and 403 deletions

View File

@ -1,5 +1,7 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import jscl.NumeralBase;
import jscl.math.Generic;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.jscl.JsclOperation;
@ -22,4 +24,7 @@ public interface Calculator extends CalculatorEventContainer {
CalculatorEventDataId evaluate(@NotNull JsclOperation operation, CalculatorEventDataId evaluate(@NotNull JsclOperation operation,
@NotNull String expression, @NotNull String expression,
@Nullable MessageRegistry mr); @Nullable MessageRegistry mr);
@NotNull
CalculatorEventDataId convert(@NotNull Generic generic, @NotNull NumeralBase to);
} }

View File

@ -47,8 +47,8 @@ public class CalculatorEvaluationEventDataImpl implements CalculatorEvaluationEv
@Override @Override
@Nullable @Nullable
public Long getCalculationId() { public Long getSequenceId() {
return calculatorEventData.getCalculationId(); return calculatorEventData.getSequenceId();
} }
@Override @Override

View File

@ -13,8 +13,9 @@ public interface CalculatorEventDataId {
// the higher id => the later event // the higher id => the later event
long getEventId(); long getEventId();
// the higher id => the later event
@Nullable @Nullable
Long getCalculationId(); Long getSequenceId();
boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId); boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId);
} }

View File

@ -13,18 +13,16 @@ class CalculatorEventDataIdImpl implements CalculatorEventDataId {
private final long eventId; private final long eventId;
@Nullable @Nullable
private final Long calculationId; private final Long sequenceId;
private CalculatorEventDataIdImpl(long id, private CalculatorEventDataIdImpl(long id, @Nullable Long sequenceId) {
@Nullable Long calculationId) {
this.eventId = id; this.eventId = id;
this.calculationId = calculationId; this.sequenceId = sequenceId;
} }
@NotNull @NotNull
static CalculatorEventDataId newInstance(long id, static CalculatorEventDataId newInstance(long id, @Nullable Long sequenceId) {
@Nullable Long calculationId) { return new CalculatorEventDataIdImpl(id, sequenceId);
return new CalculatorEventDataIdImpl(id, calculationId);
} }
@Override @Override
@ -34,8 +32,8 @@ class CalculatorEventDataIdImpl implements CalculatorEventDataId {
@Nullable @Nullable
@Override @Override
public Long getCalculationId() { public Long getSequenceId() {
return this.calculationId; return this.sequenceId;
} }
@Override @Override
@ -51,7 +49,7 @@ class CalculatorEventDataIdImpl implements CalculatorEventDataId {
CalculatorEventDataIdImpl that = (CalculatorEventDataIdImpl) o; CalculatorEventDataIdImpl that = (CalculatorEventDataIdImpl) o;
if (eventId != that.eventId) return false; if (eventId != that.eventId) return false;
if (calculationId != null ? !calculationId.equals(that.calculationId) : that.calculationId != null) if (sequenceId != null ? !sequenceId.equals(that.sequenceId) : that.sequenceId != null)
return false; return false;
return true; return true;
@ -60,7 +58,7 @@ class CalculatorEventDataIdImpl implements CalculatorEventDataId {
@Override @Override
public int hashCode() { public int hashCode() {
int result = (int) (eventId ^ (eventId >>> 32)); int result = (int) (eventId ^ (eventId >>> 32));
result = 31 * result + (calculationId != null ? calculationId.hashCode() : 0); result = 31 * result + (sequenceId != null ? sequenceId.hashCode() : 0);
return result; return result;
} }
} }

View File

@ -29,8 +29,8 @@ class CalculatorEventDataImpl implements CalculatorEventData {
@Override @Override
@Nullable @Nullable
public Long getCalculationId() { public Long getSequenceId() {
return calculatorEventDataId.getCalculationId(); return calculatorEventDataId.getSequenceId();
} }
@Override @Override

View File

@ -28,7 +28,19 @@ public enum CalculatorEventType {
calculation_finished, calculation_finished,
// @NotNull org.solovyev.android.calculator.CalculatorFailure // @NotNull org.solovyev.android.calculator.CalculatorFailure
calculation_failed; calculation_failed,
/*
**********************************************************************
*
* CONVERSION
*
**********************************************************************
*/
conversion_started,
// @NotNull String conversion result
conversion_finished;
public boolean isOfType(@NotNull CalculatorEventType... types) { public boolean isOfType(@NotNull CalculatorEventType... types) {
for (CalculatorEventType type : types) { for (CalculatorEventType type : types) {

View File

@ -1,6 +1,7 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import jscl.AbstractJsclArithmeticException; import jscl.AbstractJsclArithmeticException;
import jscl.NumeralBase;
import jscl.NumeralBaseException; import jscl.NumeralBaseException;
import jscl.math.Generic; import jscl.math.Generic;
import jscl.text.ParseInterruptedException; import jscl.text.ParseInterruptedException;
@ -10,6 +11,10 @@ import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.text.TextProcessor; import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.common.msg.MessageRegistry; import org.solovyev.common.msg.MessageRegistry;
import org.solovyev.common.msg.MessageType; import org.solovyev.common.msg.MessageType;
import org.solovyev.common.text.StringUtils;
import org.solovyev.math.units.UnitConverter;
import org.solovyev.math.units.UnitImpl;
import org.solovyev.math.units.UnitType;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@ -43,6 +48,32 @@ public class CalculatorImpl implements Calculator {
public CalculatorImpl() { public CalculatorImpl() {
} }
@NotNull
public static String doConversion(@NotNull UnitConverter<String> converter,
@Nullable String from,
@NotNull UnitType<String> fromUnitType,
@NotNull UnitType<String> toUnitType) throws ConversionException{
final String result;
if (StringUtils.isEmpty(from)) {
result = "";
} else {
String to = null;
try {
if (converter.isSupported(fromUnitType, toUnitType)) {
to = converter.convert(UnitImpl.newInstance(from, fromUnitType), toUnitType).getValue();
}
} catch (RuntimeException e) {
throw new ConversionException(e);
}
result = to;
}
return result;
}
@NotNull @NotNull
private CalculatorEventDataId nextCalculatorEventDataId() { private CalculatorEventDataId nextCalculatorEventDataId() {
long eventId = counter.incrementAndGet(); long eventId = counter.incrementAndGet();
@ -50,9 +81,9 @@ public class CalculatorImpl implements Calculator {
} }
@NotNull @NotNull
private CalculatorEventDataId nextEventDataId(@NotNull Long calculationId) { private CalculatorEventDataId nextEventDataId(@NotNull Long sequenceId) {
long eventId = counter.incrementAndGet(); long eventId = counter.incrementAndGet();
return CalculatorEventDataIdImpl.newInstance(eventId, calculationId); return CalculatorEventDataIdImpl.newInstance(eventId, sequenceId);
} }
/* /*
@ -86,14 +117,56 @@ public class CalculatorImpl implements Calculator {
threadPoolExecutor.execute(new Runnable() { threadPoolExecutor.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
CalculatorImpl.this.evaluate(eventDataId.getCalculationId(), operation, expression, mr); CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, mr);
} }
}); });
return eventDataId; return eventDataId;
} }
private void evaluate(@NotNull Long calculationId, @NotNull
@Override
public CalculatorEventDataId convert(@NotNull final Generic generic,
@NotNull final NumeralBase to) {
final CalculatorEventDataId eventDataId = nextCalculatorEventDataId();
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
final Long sequenceId = eventDataId.getSequenceId();
assert sequenceId != null;
fireCalculatorEvent(newConversionEventData(sequenceId), CalculatorEventType.conversion_started, null);
final NumeralBase from = CalculatorLocatorImpl.getInstance().getCalculatorEngine().getEngine().getNumeralBase();
if (from != to) {
String fromString = generic.toString();
if (!StringUtils.isEmpty(fromString)) {
try {
fromString = ToJsclTextProcessor.getInstance().process(fromString).getExpression();
} catch (CalculatorParseException e) {
// ok, problems while processing occurred
}
}
// todo serso: continue
//doConversion(AndroidNumeralBase.getConverter(), fromString, AndroidNumeralBase.valueOf(fromString), AndroidNumeralBase.valueOf(to));
} else {
fireCalculatorEvent(newConversionEventData(sequenceId), CalculatorEventType.conversion_finished, generic.toString());
}
}
});
return eventDataId;
}
@NotNull
private CalculatorEventData newConversionEventData(@NotNull Long sequenceId) {
return CalculatorEventDataImpl.newInstance(nextEventDataId(sequenceId));
}
private void evaluate(@NotNull Long sequenceId,
@NotNull JsclOperation operation, @NotNull JsclOperation operation,
@NotNull String expression, @NotNull String expression,
@Nullable MessageRegistry mr) { @Nullable MessageRegistry mr) {
@ -101,7 +174,7 @@ public class CalculatorImpl implements Calculator {
PreparedExpression preparedExpression = null; PreparedExpression preparedExpression = null;
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_started, new CalculatorInputImpl(expression, operation)); fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_started, new CalculatorInputImpl(expression, operation));
try { try {
preparedExpression = preprocessor.process(expression); preparedExpression = preprocessor.process(expression);
@ -116,27 +189,27 @@ public class CalculatorImpl implements Calculator {
result.toString(); result.toString();
final CalculatorOutputImpl data = new CalculatorOutputImpl(operation.getFromProcessor().process(result), operation, result); final CalculatorOutputImpl data = new CalculatorOutputImpl(operation.getFromProcessor().process(result), operation, result);
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_result, data); fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_result, data);
} catch (AbstractJsclArithmeticException e) { } catch (AbstractJsclArithmeticException e) {
handleException(calculationId, operation, expression, mr, new CalculatorEvalException(e, e, jsclExpression)); handleException(sequenceId, operation, expression, mr, new CalculatorEvalException(e, e, jsclExpression));
} }
} catch (ArithmeticException e) { } catch (ArithmeticException e) {
handleException(calculationId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_001, MessageType.error, e.getMessage()))); handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_001, MessageType.error, e.getMessage())));
} catch (StackOverflowError e) { } catch (StackOverflowError e) {
handleException(calculationId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_002, MessageType.error))); handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_002, MessageType.error)));
} catch (jscl.text.ParseException e) { } catch (jscl.text.ParseException e) {
handleException(calculationId, operation, expression, mr, preparedExpression, new CalculatorParseException(e)); handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(e));
} catch (ParseInterruptedException e) { } catch (ParseInterruptedException e) {
// do nothing - we ourselves interrupt the calculations // do nothing - we ourselves interrupt the calculations
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_cancelled, null); fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_cancelled, null);
} catch (CalculatorParseException e) { } catch (CalculatorParseException e) {
handleException(calculationId, operation, expression, mr, preparedExpression, e); handleException(sequenceId, operation, expression, mr, preparedExpression, e);
} finally { } finally {
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_finished, null); fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_finished, null);
} }
} }
} }
@ -206,4 +279,13 @@ public class CalculatorImpl implements Calculator {
public void fireCalculatorEvents(@NotNull List<CalculatorEvent> calculatorEvents) { public void fireCalculatorEvents(@NotNull List<CalculatorEvent> calculatorEvents) {
calculatorEventContainer.fireCalculatorEvents(calculatorEvents); calculatorEventContainer.fireCalculatorEvents(calculatorEvents);
} }
public static final class ConversionException extends Exception {
private ConversionException() {
}
private ConversionException(Throwable throwable) {
super(throwable);
}
}
} }

View File

@ -1,20 +1,19 @@
# This file is automatically generated by Android Tools. # This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED! # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
# #
# This file must be checked in Version Control Systems. # This file must be checked in Version Control Systems.
# #
# To customize properties used by the Ant build system use, # To customize properties used by the Ant build system use,
# "ant.properties", and override values to adapt the script to your # "ant.properties", and override values to adapt the script to your
# project structure. # project structure.
# Project target. # Project target.
target=android-15 target=android-15
android.library.reference.1=../calculatorpp-service android.library.reference.1=gen-external-apklibs/org.solovyev.android_android-common-core_1.0.0
android.library.reference.2=gen-external-apklibs/org.solovyev.android_android-common-core_1.0.0 android.library.reference.2=gen-external-apklibs/org.solovyev.android_android-common-ads_1.0.0
android.library.reference.3=gen-external-apklibs/org.solovyev.android_android-common-ads_1.0.0 android.library.reference.3=gen-external-apklibs/org.solovyev.android_android-common-view_1.0.0
android.library.reference.4=gen-external-apklibs/org.solovyev.android_android-common-view_1.0.0 android.library.reference.4=gen-external-apklibs/org.solovyev.android_android-common-preferences_1.0.0
android.library.reference.5=gen-external-apklibs/org.solovyev.android_android-common-preferences_1.0.0 android.library.reference.5=gen-external-apklibs/org.solovyev.android_android-common-other_1.0.0
android.library.reference.6=gen-external-apklibs/org.solovyev.android_android-common-other_1.0.0 android.library.reference.6=gen-external-apklibs/org.solovyev.android_android-common-menu_1.0.0
android.library.reference.7=gen-external-apklibs/org.solovyev.android_android-common-menu_1.0.0

View File

@ -10,7 +10,6 @@ import android.graphics.Color;
import android.text.Html; import android.text.Html;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
import jscl.NumeralBase;
import jscl.math.Generic; import jscl.math.Generic;
import jscl.math.function.Constant; import jscl.math.function.Constant;
import jscl.math.function.IConstant; import jscl.math.function.IConstant;
@ -20,12 +19,9 @@ import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.calculator.text.TextProcessor; import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog; import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
import org.solovyev.android.calculator.view.TextHighlighter; import org.solovyev.android.calculator.view.TextHighlighter;
import org.solovyev.android.calculator.view.UnitConverterViewBuilder;
import org.solovyev.android.menu.AMenuItem;
import org.solovyev.android.menu.LabeledMenuItem; import org.solovyev.android.menu.LabeledMenuItem;
import org.solovyev.android.view.AutoResizeTextView; import org.solovyev.android.view.AutoResizeTextView;
import org.solovyev.common.collections.CollectionsUtils; import org.solovyev.common.collections.CollectionsUtils;
import org.solovyev.common.text.StringUtils;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -37,95 +33,18 @@ import java.util.Set;
*/ */
public class AndroidCalculatorDisplayView extends AutoResizeTextView implements CalculatorDisplayView { public class AndroidCalculatorDisplayView extends AutoResizeTextView implements CalculatorDisplayView {
private static enum ConversionMenuItem implements AMenuItem<CalculatorDisplayView> { public static enum MenuItem implements LabeledMenuItem<CalculatorDisplayViewState> {
convert_to_bin(NumeralBase.bin),
convert_to_dec(NumeralBase.dec),
convert_to_hex(NumeralBase.hex);
@NotNull
private final NumeralBase toNumeralBase;
private ConversionMenuItem(@NotNull NumeralBase toNumeralBase) {
this.toNumeralBase = toNumeralBase;
}
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
boolean result = false;
if (operation == JsclOperation.numeric) {
if (generic.getConstants().isEmpty()) {
try {
convert(generic);
// conversion possible => return true
result = true;
} catch (UnitConverterViewBuilder.ConversionException e) {
// conversion is not possible => return false
}
}
}
return result;
}
@Override
public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) {
final NumeralBase fromNumeralBase = CalculatorEngine.instance.getEngine().getNumeralBase();
final Generic lastResult = CalculatorLocatorImpl.getInstance().getCalculatorDisplay().getViewState().getResult();
if (lastResult != null) {
String to;
try {
to = convert(lastResult);
// add prefix
if (fromNumeralBase != toNumeralBase) {
to = toNumeralBase.getJsclPrefix() + to;
}
} catch (UnitConverterViewBuilder.ConversionException e) {
to = context.getString(R.string.c_error);
}
data.setText(to);
//data.redraw();
}
}
@NotNull
private String convert(@NotNull Generic generic) throws UnitConverterViewBuilder.ConversionException {
final NumeralBase fromNumeralBase = CalculatorEngine.instance.getEngine().getNumeralBase();
if (fromNumeralBase != toNumeralBase) {
String from = generic.toString();
if (!StringUtils.isEmpty(from)) {
try {
from = ToJsclTextProcessor.getInstance().process(from).getExpression();
} catch (CalculatorParseException e) {
// ok, problems while processing occurred
}
}
return UnitConverterViewBuilder.doConversion(AndroidNumeralBase.getConverter(), from, AndroidNumeralBase.valueOf(fromNumeralBase), AndroidNumeralBase.valueOf(toNumeralBase));
} else {
return generic.toString();
}
}
}
public static enum MenuItem implements LabeledMenuItem<CalculatorDisplayView> {
copy(R.string.c_copy) { copy(R.string.c_copy) {
@Override @Override
public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
CalculatorModel.copyResult(context, data); CalculatorModel.copyResult(context, data);
} }
}, },
convert_to_bin(R.string.convert_to_bin) { convert_to_bin(R.string.convert_to_bin) {
@Override @Override
public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
ConversionMenuItem.convert_to_bin.onClick(data, context); ConversionMenuItem.convert_to_bin.onClick(data, context);
} }
@ -137,7 +56,7 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements
convert_to_dec(R.string.convert_to_dec) { convert_to_dec(R.string.convert_to_dec) {
@Override @Override
public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
ConversionMenuItem.convert_to_dec.onClick(data, context); ConversionMenuItem.convert_to_dec.onClick(data, context);
} }
@ -149,7 +68,7 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements
convert_to_hex(R.string.convert_to_hex) { convert_to_hex(R.string.convert_to_hex) {
@Override @Override
public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
ConversionMenuItem.convert_to_hex.onClick(data, context); ConversionMenuItem.convert_to_hex.onClick(data, context);
} }
@ -161,8 +80,8 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements
convert(R.string.c_convert) { convert(R.string.c_convert) {
@Override @Override
public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
final Generic result = data.getState().getResult(); final Generic result = data.getResult();
if (result != null) { if (result != null) {
new NumeralBaseConverterDialog(result.toString()).show(context); new NumeralBaseConverterDialog(result.toString()).show(context);
} }
@ -176,8 +95,8 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements
plot(R.string.c_plot) { plot(R.string.c_plot) {
@Override @Override
public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
final Generic generic = data.getState().getResult(); final Generic generic = data.getResult();
assert generic != null; assert generic != null;
final Constant constant = CollectionsUtils.getFirstCollectionElement(getNotSystemConstants(generic)); final Constant constant = CollectionsUtils.getFirstCollectionElement(getNotSystemConstants(generic));

View File

@ -97,10 +97,9 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
copyResult(context, display); copyResult(context, display);
} }
public static void copyResult(@NotNull Context context, @NotNull final CalculatorDisplayView display) { public static void copyResult(@NotNull Context context, @NotNull final CalculatorDisplayViewState viewState) {
final CalculatorDisplayViewState displayViewState = display.getState(); if (viewState.isValid()) {
if (displayViewState.isValid()) { final CharSequence text = viewState.getText();
final CharSequence text = display.getText();
if (!StringUtils.isEmpty(text)) { if (!StringUtils.isEmpty(text)) {
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE); final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
clipboard.setText(text.toString()); clipboard.setText(text.toString());

View File

@ -0,0 +1,63 @@
package org.solovyev.android.calculator;
import android.content.Context;
import jscl.NumeralBase;
import jscl.math.Generic;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.menu.AMenuItem;
/**
* User: serso
* Date: 9/21/12
* Time: 12:11 AM
*/
enum ConversionMenuItem implements AMenuItem<CalculatorDisplayViewState> {
convert_to_bin(NumeralBase.bin),
convert_to_dec(NumeralBase.dec),
convert_to_hex(NumeralBase.hex);
@NotNull
private final NumeralBase toNumeralBase;
ConversionMenuItem(@NotNull NumeralBase toNumeralBase) {
this.toNumeralBase = toNumeralBase;
}
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
boolean result = false;
if (operation == JsclOperation.numeric) {
if (generic.getConstants().isEmpty()) {
try {
convert(generic);
// conversion possible => return true
result = true;
} catch (CalculatorImpl.ConversionException e) {
// conversion is not possible => return false
}
}
}
return result;
}
@Override
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
final NumeralBase fromNumeralBase = CalculatorEngine.instance.getEngine().getNumeralBase();
final Generic lastResult = data.getResult();
if (lastResult != null) {
convert(lastResult);
}
}
private void convert(@NotNull Generic generic) {
CalculatorLocatorImpl.getInstance().getCalculator().convert(generic, this.toNumeralBase);
}
}

View File

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