parent
b3cc081f47
commit
cca775c2ac
@ -1,30 +1,25 @@
|
|||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import jscl.NumeralBase;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import jscl.math.Generic;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.solovyev.common.msg.MessageRegistry;
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
|
||||||
import org.solovyev.common.msg.MessageRegistry;
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
/**
|
* Date: 20.09.12
|
||||||
* User: Solovyev_S
|
* Time: 16:38
|
||||||
* Date: 20.09.12
|
*/
|
||||||
* Time: 16:38
|
public interface Calculator extends CalculatorEventContainer {
|
||||||
*/
|
|
||||||
public interface Calculator extends CalculatorEventContainer {
|
@NotNull
|
||||||
|
CalculatorEventDataId createFirstEventDataId();
|
||||||
@NotNull
|
|
||||||
CalculatorEventDataId createFirstEventDataId();
|
void evaluate(@NotNull JsclOperation operation,
|
||||||
|
@NotNull String expression);
|
||||||
void evaluate(@NotNull JsclOperation operation,
|
|
||||||
@NotNull String expression);
|
@NotNull
|
||||||
|
CalculatorEventDataId evaluate(@NotNull JsclOperation operation,
|
||||||
@NotNull
|
@NotNull String expression,
|
||||||
CalculatorEventDataId evaluate(@NotNull JsclOperation operation,
|
@Nullable MessageRegistry mr);
|
||||||
@NotNull String expression,
|
}
|
||||||
@Nullable MessageRegistry mr);
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
CalculatorEventDataId convert(@NotNull Generic generic, @NotNull NumeralBase to);
|
|
||||||
}
|
|
||||||
|
@ -1,58 +1,58 @@
|
|||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 9/20/12
|
* Date: 9/20/12
|
||||||
* Time: 10:01 PM
|
* Time: 10:01 PM
|
||||||
*/
|
*/
|
||||||
public class CalculatorEvaluationEventDataImpl implements CalculatorEvaluationEventData {
|
public class CalculatorEvaluationEventDataImpl implements CalculatorEvaluationEventData {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final CalculatorEventData calculatorEventData;
|
private final CalculatorEventData calculatorEventData;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JsclOperation operation;
|
private final JsclOperation operation;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final String expression;
|
private final String expression;
|
||||||
|
|
||||||
public CalculatorEvaluationEventDataImpl(@NotNull CalculatorEventData calculatorEventData,
|
public CalculatorEvaluationEventDataImpl(@NotNull CalculatorEventData calculatorEventData,
|
||||||
@NotNull JsclOperation operation,
|
@NotNull JsclOperation operation,
|
||||||
@NotNull String expression) {
|
@NotNull String expression) {
|
||||||
this.calculatorEventData = calculatorEventData;
|
this.calculatorEventData = calculatorEventData;
|
||||||
this.operation = operation;
|
this.operation = operation;
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public JsclOperation getOperation() {
|
public JsclOperation getOperation() {
|
||||||
return this.operation;
|
return this.operation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public String getExpression() {
|
public String getExpression() {
|
||||||
return this.expression;
|
return this.expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getEventId() {
|
public long getEventId() {
|
||||||
return calculatorEventData.getEventId();
|
return calculatorEventData.getEventId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public Long getSequenceId() {
|
public Long getCalculationId() {
|
||||||
return calculatorEventData.getSequenceId();
|
return calculatorEventData.getCalculationId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) {
|
public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) {
|
||||||
return calculatorEventData.isAfter(calculatorEventDataId);
|
return calculatorEventData.isAfter(calculatorEventDataId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: Solovyev_S
|
* User: Solovyev_S
|
||||||
* Date: 20.09.12
|
* Date: 20.09.12
|
||||||
* Time: 18:18
|
* Time: 18:18
|
||||||
*/
|
*/
|
||||||
public interface CalculatorEventDataId {
|
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);
|
}
|
||||||
}
|
|
||||||
|
@ -1,64 +1,66 @@
|
|||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: Solovyev_S
|
* User: Solovyev_S
|
||||||
* Date: 20.09.12
|
* Date: 20.09.12
|
||||||
* Time: 18:18
|
* Time: 18:18
|
||||||
*/
|
*/
|
||||||
class CalculatorEventDataIdImpl implements CalculatorEventDataId {
|
class CalculatorEventDataIdImpl implements CalculatorEventDataId {
|
||||||
|
|
||||||
private final long eventId;
|
private final long eventId;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private final Long sequenceId;
|
private final Long calculationId;
|
||||||
|
|
||||||
private CalculatorEventDataIdImpl(long id, @Nullable Long sequenceId) {
|
private CalculatorEventDataIdImpl(long id,
|
||||||
this.eventId = id;
|
@Nullable Long calculationId) {
|
||||||
this.sequenceId = sequenceId;
|
this.eventId = id;
|
||||||
}
|
this.calculationId = calculationId;
|
||||||
|
}
|
||||||
@NotNull
|
|
||||||
static CalculatorEventDataId newInstance(long id, @Nullable Long sequenceId) {
|
@NotNull
|
||||||
return new CalculatorEventDataIdImpl(id, sequenceId);
|
static CalculatorEventDataId newInstance(long id,
|
||||||
}
|
@Nullable Long calculationId) {
|
||||||
|
return new CalculatorEventDataIdImpl(id, calculationId);
|
||||||
@Override
|
}
|
||||||
public long getEventId() {
|
|
||||||
return this.eventId;
|
@Override
|
||||||
}
|
public long getEventId() {
|
||||||
|
return this.eventId;
|
||||||
@Nullable
|
}
|
||||||
@Override
|
|
||||||
public Long getSequenceId() {
|
@Nullable
|
||||||
return this.sequenceId;
|
@Override
|
||||||
}
|
public Long getCalculationId() {
|
||||||
|
return this.calculationId;
|
||||||
@Override
|
}
|
||||||
public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) {
|
|
||||||
return this.eventId > calculatorEventDataId.getEventId();
|
@Override
|
||||||
}
|
public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) {
|
||||||
|
return this.eventId > calculatorEventDataId.getEventId();
|
||||||
@Override
|
}
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
@Override
|
||||||
if (!(o instanceof CalculatorEventDataIdImpl)) return false;
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
CalculatorEventDataIdImpl that = (CalculatorEventDataIdImpl) o;
|
if (!(o instanceof CalculatorEventDataIdImpl)) return false;
|
||||||
|
|
||||||
if (eventId != that.eventId) return false;
|
CalculatorEventDataIdImpl that = (CalculatorEventDataIdImpl) o;
|
||||||
if (sequenceId != null ? !sequenceId.equals(that.sequenceId) : that.sequenceId != null)
|
|
||||||
return false;
|
if (eventId != that.eventId) return false;
|
||||||
|
if (calculationId != null ? !calculationId.equals(that.calculationId) : that.calculationId != null)
|
||||||
return true;
|
return false;
|
||||||
}
|
|
||||||
|
return true;
|
||||||
@Override
|
}
|
||||||
public int hashCode() {
|
|
||||||
int result = (int) (eventId ^ (eventId >>> 32));
|
@Override
|
||||||
result = 31 * result + (sequenceId != null ? sequenceId.hashCode() : 0);
|
public int hashCode() {
|
||||||
return result;
|
int result = (int) (eventId ^ (eventId >>> 32));
|
||||||
}
|
result = 31 * result + (calculationId != null ? calculationId.hashCode() : 0);
|
||||||
}
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,57 +1,57 @@
|
|||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: Solovyev_S
|
* User: Solovyev_S
|
||||||
* Date: 20.09.12
|
* Date: 20.09.12
|
||||||
* Time: 16:54
|
* Time: 16:54
|
||||||
*/
|
*/
|
||||||
class CalculatorEventDataImpl implements CalculatorEventData {
|
class CalculatorEventDataImpl implements CalculatorEventData {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private CalculatorEventDataId calculatorEventDataId;
|
private CalculatorEventDataId calculatorEventDataId;
|
||||||
|
|
||||||
private CalculatorEventDataImpl(@NotNull CalculatorEventDataId calculatorEventDataId) {
|
private CalculatorEventDataImpl(@NotNull CalculatorEventDataId calculatorEventDataId) {
|
||||||
this.calculatorEventDataId = calculatorEventDataId;
|
this.calculatorEventDataId = calculatorEventDataId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static CalculatorEventData newInstance(@NotNull CalculatorEventDataId calculatorEventDataId) {
|
public static CalculatorEventData newInstance(@NotNull CalculatorEventDataId calculatorEventDataId) {
|
||||||
return new CalculatorEventDataImpl(calculatorEventDataId);
|
return new CalculatorEventDataImpl(calculatorEventDataId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getEventId() {
|
public long getEventId() {
|
||||||
return calculatorEventDataId.getEventId();
|
return calculatorEventDataId.getEventId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public Long getSequenceId() {
|
public Long getCalculationId() {
|
||||||
return calculatorEventDataId.getSequenceId();
|
return calculatorEventDataId.getCalculationId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) {
|
public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) {
|
||||||
return this.calculatorEventDataId.isAfter(calculatorEventDataId);
|
return this.calculatorEventDataId.isAfter(calculatorEventDataId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (!(o instanceof CalculatorEventDataImpl)) return false;
|
if (!(o instanceof CalculatorEventDataImpl)) return false;
|
||||||
|
|
||||||
CalculatorEventDataImpl that = (CalculatorEventDataImpl) o;
|
CalculatorEventDataImpl that = (CalculatorEventDataImpl) o;
|
||||||
|
|
||||||
if (!calculatorEventDataId.equals(that.calculatorEventDataId)) return false;
|
if (!calculatorEventDataId.equals(that.calculatorEventDataId)) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return calculatorEventDataId.hashCode();
|
return calculatorEventDataId.hashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,55 +1,43 @@
|
|||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: Solovyev_S
|
* User: Solovyev_S
|
||||||
* Date: 20.09.12
|
* Date: 20.09.12
|
||||||
* Time: 16:40
|
* Time: 16:40
|
||||||
*/
|
*/
|
||||||
public enum CalculatorEventType {
|
public enum CalculatorEventType {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
*
|
*
|
||||||
* org.solovyev.android.calculator.CalculatorEvaluationEventData
|
* org.solovyev.android.calculator.CalculatorEvaluationEventData
|
||||||
*
|
*
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @NotNull org.solovyev.android.calculator.CalculatorInput
|
// @NotNull org.solovyev.android.calculator.CalculatorInput
|
||||||
calculation_started,
|
calculation_started,
|
||||||
|
|
||||||
// @NotNull org.solovyev.android.calculator.CalculatorOutput
|
// @NotNull org.solovyev.android.calculator.CalculatorOutput
|
||||||
calculation_result,
|
calculation_result,
|
||||||
|
|
||||||
calculation_cancelled,
|
calculation_cancelled,
|
||||||
|
|
||||||
calculation_finished,
|
calculation_finished,
|
||||||
|
|
||||||
// @NotNull org.solovyev.android.calculator.CalculatorFailure
|
// @NotNull org.solovyev.android.calculator.CalculatorFailure
|
||||||
calculation_failed,
|
calculation_failed;
|
||||||
|
|
||||||
/*
|
public boolean isOfType(@NotNull CalculatorEventType... types) {
|
||||||
**********************************************************************
|
for (CalculatorEventType type : types) {
|
||||||
*
|
if ( this == type ) {
|
||||||
* CONVERSION
|
return true;
|
||||||
*
|
}
|
||||||
**********************************************************************
|
}
|
||||||
*/
|
|
||||||
conversion_started,
|
return false;
|
||||||
|
}
|
||||||
// @NotNull String conversion result
|
|
||||||
conversion_finished;
|
}
|
||||||
|
|
||||||
public boolean isOfType(@NotNull CalculatorEventType... types) {
|
|
||||||
for (CalculatorEventType type : types) {
|
|
||||||
if ( this == type ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -1,291 +1,209 @@
|
|||||||
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;
|
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;
|
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 java.util.List;
|
||||||
import org.solovyev.math.units.UnitConverter;
|
import java.util.concurrent.Executor;
|
||||||
import org.solovyev.math.units.UnitImpl;
|
import java.util.concurrent.Executors;
|
||||||
import org.solovyev.math.units.UnitType;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
import java.util.List;
|
/**
|
||||||
import java.util.concurrent.Executor;
|
* User: Solovyev_S
|
||||||
import java.util.concurrent.Executors;
|
* Date: 20.09.12
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
* Time: 16:42
|
||||||
|
*/
|
||||||
/**
|
public class CalculatorImpl implements Calculator {
|
||||||
* User: Solovyev_S
|
|
||||||
* Date: 20.09.12
|
private static final long FIRST_ID = 0;
|
||||||
* Time: 16:42
|
|
||||||
*/
|
@NotNull
|
||||||
public class CalculatorImpl implements Calculator {
|
private final CalculatorEventContainer calculatorEventContainer = new ListCalculatorEventContainer();
|
||||||
|
|
||||||
private static final long FIRST_ID = 0;
|
@NotNull
|
||||||
|
private final AtomicLong counter = new AtomicLong(FIRST_ID);
|
||||||
@NotNull
|
|
||||||
private final CalculatorEventContainer calculatorEventContainer = new ListCalculatorEventContainer();
|
@NotNull
|
||||||
|
private final Object lock = new Object();
|
||||||
@NotNull
|
|
||||||
private final AtomicLong counter = new AtomicLong(FIRST_ID);
|
@NotNull
|
||||||
|
private final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
|
||||||
@NotNull
|
|
||||||
private final Object lock = new Object();
|
@NotNull
|
||||||
|
private final Executor threadPoolExecutor = Executors.newFixedThreadPool(10);
|
||||||
@NotNull
|
|
||||||
private final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
|
public CalculatorImpl() {
|
||||||
|
}
|
||||||
@NotNull
|
|
||||||
private final Executor threadPoolExecutor = Executors.newFixedThreadPool(10);
|
@NotNull
|
||||||
|
private CalculatorEventDataId nextCalculatorEventDataId() {
|
||||||
public CalculatorImpl() {
|
long eventId = counter.incrementAndGet();
|
||||||
}
|
return CalculatorEventDataIdImpl.newInstance(eventId, eventId);
|
||||||
|
}
|
||||||
@NotNull
|
|
||||||
public static String doConversion(@NotNull UnitConverter<String> converter,
|
@NotNull
|
||||||
@Nullable String from,
|
private CalculatorEventDataId nextEventDataId(@NotNull Long calculationId) {
|
||||||
@NotNull UnitType<String> fromUnitType,
|
long eventId = counter.incrementAndGet();
|
||||||
@NotNull UnitType<String> toUnitType) throws ConversionException{
|
return CalculatorEventDataIdImpl.newInstance(eventId, calculationId);
|
||||||
final String result;
|
}
|
||||||
|
|
||||||
if (StringUtils.isEmpty(from)) {
|
/*
|
||||||
result = "";
|
**********************************************************************
|
||||||
} else {
|
*
|
||||||
|
* CALCULATION
|
||||||
String to = null;
|
*
|
||||||
try {
|
**********************************************************************
|
||||||
if (converter.isSupported(fromUnitType, toUnitType)) {
|
*/
|
||||||
to = converter.convert(UnitImpl.newInstance(from, fromUnitType), toUnitType).getValue();
|
|
||||||
}
|
@NotNull
|
||||||
} catch (RuntimeException e) {
|
@Override
|
||||||
throw new ConversionException(e);
|
public CalculatorEventDataId createFirstEventDataId() {
|
||||||
}
|
return CalculatorEventDataIdImpl.newInstance(FIRST_ID, FIRST_ID);
|
||||||
|
}
|
||||||
result = to;
|
|
||||||
}
|
@Override
|
||||||
|
public void evaluate(@NotNull JsclOperation operation,
|
||||||
return result;
|
@NotNull String expression) {
|
||||||
}
|
evaluate(operation, expression, null);
|
||||||
|
}
|
||||||
@NotNull
|
|
||||||
private CalculatorEventDataId nextCalculatorEventDataId() {
|
@Override
|
||||||
long eventId = counter.incrementAndGet();
|
@NotNull
|
||||||
return CalculatorEventDataIdImpl.newInstance(eventId, eventId);
|
public CalculatorEventDataId evaluate(@NotNull final JsclOperation operation,
|
||||||
}
|
@NotNull final String expression,
|
||||||
|
@Nullable final MessageRegistry mr) {
|
||||||
@NotNull
|
|
||||||
private CalculatorEventDataId nextEventDataId(@NotNull Long sequenceId) {
|
final CalculatorEventDataId eventDataId = nextCalculatorEventDataId();
|
||||||
long eventId = counter.incrementAndGet();
|
|
||||||
return CalculatorEventDataIdImpl.newInstance(eventId, sequenceId);
|
threadPoolExecutor.execute(new Runnable() {
|
||||||
}
|
@Override
|
||||||
|
public void run() {
|
||||||
/*
|
CalculatorImpl.this.evaluate(eventDataId.getCalculationId(), operation, expression, mr);
|
||||||
**********************************************************************
|
}
|
||||||
*
|
});
|
||||||
* CALCULATION
|
|
||||||
*
|
return eventDataId;
|
||||||
**********************************************************************
|
}
|
||||||
*/
|
|
||||||
|
private void evaluate(@NotNull Long calculationId,
|
||||||
@NotNull
|
@NotNull JsclOperation operation,
|
||||||
@Override
|
@NotNull String expression,
|
||||||
public CalculatorEventDataId createFirstEventDataId() {
|
@Nullable MessageRegistry mr) {
|
||||||
return CalculatorEventDataIdImpl.newInstance(FIRST_ID, FIRST_ID);
|
synchronized (lock) {
|
||||||
}
|
|
||||||
|
PreparedExpression preparedExpression = null;
|
||||||
@Override
|
|
||||||
public void evaluate(@NotNull JsclOperation operation,
|
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_started, new CalculatorInputImpl(expression, operation));
|
||||||
@NotNull String expression) {
|
|
||||||
evaluate(operation, expression, null);
|
try {
|
||||||
}
|
preparedExpression = preprocessor.process(expression);
|
||||||
|
|
||||||
@Override
|
final String jsclExpression = preparedExpression.toString();
|
||||||
@NotNull
|
|
||||||
public CalculatorEventDataId evaluate(@NotNull final JsclOperation operation,
|
try {
|
||||||
@NotNull final String expression,
|
|
||||||
@Nullable final MessageRegistry mr) {
|
final Generic result = operation.evaluateGeneric(jsclExpression);
|
||||||
|
|
||||||
final CalculatorEventDataId eventDataId = nextCalculatorEventDataId();
|
// NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!)
|
||||||
|
result.toString();
|
||||||
threadPoolExecutor.execute(new Runnable() {
|
|
||||||
@Override
|
final CalculatorOutputImpl data = new CalculatorOutputImpl(operation.getFromProcessor().process(result), operation, result);
|
||||||
public void run() {
|
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_result, data);
|
||||||
CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, mr);
|
|
||||||
}
|
} catch (AbstractJsclArithmeticException e) {
|
||||||
});
|
handleException(calculationId, operation, expression, mr, new CalculatorEvalException(e, e, jsclExpression));
|
||||||
|
}
|
||||||
return eventDataId;
|
|
||||||
}
|
} catch (ArithmeticException e) {
|
||||||
|
handleException(calculationId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_001, MessageType.error, e.getMessage())));
|
||||||
@NotNull
|
} catch (StackOverflowError e) {
|
||||||
@Override
|
handleException(calculationId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_002, MessageType.error)));
|
||||||
public CalculatorEventDataId convert(@NotNull final Generic generic,
|
} catch (jscl.text.ParseException e) {
|
||||||
@NotNull final NumeralBase to) {
|
handleException(calculationId, operation, expression, mr, preparedExpression, new CalculatorParseException(e));
|
||||||
final CalculatorEventDataId eventDataId = nextCalculatorEventDataId();
|
} catch (ParseInterruptedException e) {
|
||||||
|
|
||||||
threadPoolExecutor.execute(new Runnable() {
|
// do nothing - we ourselves interrupt the calculations
|
||||||
@Override
|
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_cancelled, null);
|
||||||
public void run() {
|
|
||||||
final Long sequenceId = eventDataId.getSequenceId();
|
} catch (CalculatorParseException e) {
|
||||||
assert sequenceId != null;
|
handleException(calculationId, operation, expression, mr, preparedExpression, e);
|
||||||
|
} finally {
|
||||||
fireCalculatorEvent(newConversionEventData(sequenceId), CalculatorEventType.conversion_started, null);
|
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_finished, null);
|
||||||
|
}
|
||||||
final NumeralBase from = CalculatorLocatorImpl.getInstance().getCalculatorEngine().getEngine().getNumeralBase();
|
}
|
||||||
|
}
|
||||||
if (from != to) {
|
|
||||||
String fromString = generic.toString();
|
@NotNull
|
||||||
if (!StringUtils.isEmpty(fromString)) {
|
private CalculatorEventData newCalculationEventData(@NotNull JsclOperation operation,
|
||||||
try {
|
@NotNull String expression,
|
||||||
fromString = ToJsclTextProcessor.getInstance().process(fromString).getExpression();
|
@NotNull Long calculationId) {
|
||||||
} catch (CalculatorParseException e) {
|
return new CalculatorEvaluationEventDataImpl(CalculatorEventDataImpl.newInstance(nextEventDataId(calculationId)), operation, expression);
|
||||||
// ok, problems while processing occurred
|
}
|
||||||
}
|
|
||||||
}
|
private void handleException(@NotNull Long calculationId,
|
||||||
|
@NotNull JsclOperation operation,
|
||||||
// todo serso: continue
|
@NotNull String expression,
|
||||||
//doConversion(AndroidNumeralBase.getConverter(), fromString, AndroidNumeralBase.valueOf(fromString), AndroidNumeralBase.valueOf(to));
|
@Nullable MessageRegistry mr,
|
||||||
} else {
|
@Nullable PreparedExpression preparedExpression,
|
||||||
fireCalculatorEvent(newConversionEventData(sequenceId), CalculatorEventType.conversion_finished, generic.toString());
|
@NotNull CalculatorParseException parseException) {
|
||||||
}
|
|
||||||
}
|
if (operation == JsclOperation.numeric
|
||||||
});
|
&& preparedExpression != null
|
||||||
|
&& preparedExpression.isExistsUndefinedVar()) {
|
||||||
return eventDataId;
|
|
||||||
}
|
evaluate(calculationId, JsclOperation.simplify, expression, mr);
|
||||||
|
|
||||||
@NotNull
|
}
|
||||||
private CalculatorEventData newConversionEventData(@NotNull Long sequenceId) {
|
|
||||||
return CalculatorEventDataImpl.newInstance(nextEventDataId(sequenceId));
|
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(parseException));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void evaluate(@NotNull Long sequenceId,
|
private void handleException(@NotNull Long calculationId,
|
||||||
@NotNull JsclOperation operation,
|
@NotNull JsclOperation operation,
|
||||||
@NotNull String expression,
|
@NotNull String expression,
|
||||||
@Nullable MessageRegistry mr) {
|
@Nullable MessageRegistry mr,
|
||||||
synchronized (lock) {
|
@NotNull CalculatorEvalException evalException) {
|
||||||
|
|
||||||
PreparedExpression preparedExpression = null;
|
if (operation == JsclOperation.numeric && evalException.getCause() instanceof NumeralBaseException) {
|
||||||
|
evaluate(calculationId, JsclOperation.simplify, expression, mr);
|
||||||
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_started, new CalculatorInputImpl(expression, operation));
|
}
|
||||||
|
|
||||||
try {
|
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(evalException));
|
||||||
preparedExpression = preprocessor.process(expression);
|
}
|
||||||
|
|
||||||
final String jsclExpression = preparedExpression.toString();
|
/*
|
||||||
|
**********************************************************************
|
||||||
try {
|
*
|
||||||
|
* EVENTS
|
||||||
final Generic result = operation.evaluateGeneric(jsclExpression);
|
*
|
||||||
|
**********************************************************************
|
||||||
// NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!)
|
*/
|
||||||
result.toString();
|
|
||||||
|
@Override
|
||||||
final CalculatorOutputImpl data = new CalculatorOutputImpl(operation.getFromProcessor().process(result), operation, result);
|
public void addCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) {
|
||||||
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_result, data);
|
calculatorEventContainer.addCalculatorEventListener(calculatorEventListener);
|
||||||
|
}
|
||||||
} catch (AbstractJsclArithmeticException e) {
|
|
||||||
handleException(sequenceId, operation, expression, mr, new CalculatorEvalException(e, e, jsclExpression));
|
@Override
|
||||||
}
|
public void removeCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) {
|
||||||
|
calculatorEventContainer.removeCalculatorEventListener(calculatorEventListener);
|
||||||
} catch (ArithmeticException e) {
|
}
|
||||||
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_001, MessageType.error, e.getMessage())));
|
|
||||||
} catch (StackOverflowError e) {
|
@Override
|
||||||
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_002, MessageType.error)));
|
public void fireCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||||
} catch (jscl.text.ParseException e) {
|
calculatorEventContainer.fireCalculatorEvent(calculatorEventData, calculatorEventType, data);
|
||||||
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(e));
|
}
|
||||||
} catch (ParseInterruptedException e) {
|
|
||||||
|
@Override
|
||||||
// do nothing - we ourselves interrupt the calculations
|
public void fireCalculatorEvents(@NotNull List<CalculatorEvent> calculatorEvents) {
|
||||||
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_cancelled, null);
|
calculatorEventContainer.fireCalculatorEvents(calculatorEvents);
|
||||||
|
}
|
||||||
} catch (CalculatorParseException e) {
|
}
|
||||||
handleException(sequenceId, operation, expression, mr, preparedExpression, e);
|
|
||||||
} finally {
|
|
||||||
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_finished, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private CalculatorEventData newCalculationEventData(@NotNull JsclOperation operation,
|
|
||||||
@NotNull String expression,
|
|
||||||
@NotNull Long calculationId) {
|
|
||||||
return new CalculatorEvaluationEventDataImpl(CalculatorEventDataImpl.newInstance(nextEventDataId(calculationId)), operation, expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleException(@NotNull Long calculationId,
|
|
||||||
@NotNull JsclOperation operation,
|
|
||||||
@NotNull String expression,
|
|
||||||
@Nullable MessageRegistry mr,
|
|
||||||
@Nullable PreparedExpression preparedExpression,
|
|
||||||
@NotNull CalculatorParseException parseException) {
|
|
||||||
|
|
||||||
if (operation == JsclOperation.numeric
|
|
||||||
&& preparedExpression != null
|
|
||||||
&& preparedExpression.isExistsUndefinedVar()) {
|
|
||||||
|
|
||||||
evaluate(calculationId, JsclOperation.simplify, expression, mr);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(parseException));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleException(@NotNull Long calculationId,
|
|
||||||
@NotNull JsclOperation operation,
|
|
||||||
@NotNull String expression,
|
|
||||||
@Nullable MessageRegistry mr,
|
|
||||||
@NotNull CalculatorEvalException evalException) {
|
|
||||||
|
|
||||||
if (operation == JsclOperation.numeric && evalException.getCause() instanceof NumeralBaseException) {
|
|
||||||
evaluate(calculationId, JsclOperation.simplify, expression, mr);
|
|
||||||
}
|
|
||||||
|
|
||||||
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(evalException));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
**********************************************************************
|
|
||||||
*
|
|
||||||
* EVENTS
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) {
|
|
||||||
calculatorEventContainer.addCalculatorEventListener(calculatorEventListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) {
|
|
||||||
calculatorEventContainer.removeCalculatorEventListener(calculatorEventListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void fireCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
|
||||||
calculatorEventContainer.fireCalculatorEvent(calculatorEventData, calculatorEventType, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void fireCalculatorEvents(@NotNull List<CalculatorEvent> calculatorEvents) {
|
|
||||||
calculatorEventContainer.fireCalculatorEvents(calculatorEvents);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class ConversionException extends Exception {
|
|
||||||
private ConversionException() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private ConversionException(Throwable throwable) {
|
|
||||||
super(throwable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
# 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=gen-external-apklibs/org.solovyev.android_android-common-core_1.0.0
|
android.library.reference.1=../calculatorpp-service
|
||||||
android.library.reference.2=gen-external-apklibs/org.solovyev.android_android-common-ads_1.0.0
|
android.library.reference.2=gen-external-apklibs/org.solovyev.android_android-common-core_1.0.0
|
||||||
android.library.reference.3=gen-external-apklibs/org.solovyev.android_android-common-view_1.0.0
|
android.library.reference.3=gen-external-apklibs/org.solovyev.android_android-common-ads_1.0.0
|
||||||
android.library.reference.4=gen-external-apklibs/org.solovyev.android_android-common-preferences_1.0.0
|
android.library.reference.4=gen-external-apklibs/org.solovyev.android_android-common-view_1.0.0
|
||||||
android.library.reference.5=gen-external-apklibs/org.solovyev.android_android-common-other_1.0.0
|
android.library.reference.5=gen-external-apklibs/org.solovyev.android_android-common-preferences_1.0.0
|
||||||
android.library.reference.6=gen-external-apklibs/org.solovyev.android_android-common-menu_1.0.0
|
android.library.reference.6=gen-external-apklibs/org.solovyev.android_android-common-other_1.0.0
|
||||||
|
android.library.reference.7=gen-external-apklibs/org.solovyev.android_android-common-menu_1.0.0
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,235 +1,316 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
* For more information, please, contact se.solovyev@gmail.com
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
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.math.Generic;
|
import jscl.NumeralBase;
|
||||||
import jscl.math.function.Constant;
|
import jscl.math.Generic;
|
||||||
import jscl.math.function.IConstant;
|
import jscl.math.function.Constant;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import jscl.math.function.IConstant;
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.calculator.model.CalculatorEngine;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
import org.solovyev.android.calculator.text.TextProcessor;
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
import org.solovyev.android.calculator.view.TextHighlighter;
|
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
|
||||||
import org.solovyev.android.menu.LabeledMenuItem;
|
import org.solovyev.android.calculator.view.TextHighlighter;
|
||||||
import org.solovyev.android.view.AutoResizeTextView;
|
import org.solovyev.android.calculator.view.UnitConverterViewBuilder;
|
||||||
import org.solovyev.common.collections.CollectionsUtils;
|
import org.solovyev.android.menu.AMenuItem;
|
||||||
|
import org.solovyev.android.menu.LabeledMenuItem;
|
||||||
import java.util.HashSet;
|
import org.solovyev.android.view.AutoResizeTextView;
|
||||||
import java.util.Set;
|
import org.solovyev.common.collections.CollectionsUtils;
|
||||||
|
import org.solovyev.common.text.StringUtils;
|
||||||
/**
|
|
||||||
* User: serso
|
import java.util.HashSet;
|
||||||
* Date: 9/17/11
|
import java.util.Set;
|
||||||
* Time: 10:58 PM
|
|
||||||
*/
|
/**
|
||||||
public class AndroidCalculatorDisplayView extends AutoResizeTextView implements CalculatorDisplayView {
|
* User: serso
|
||||||
|
* Date: 9/17/11
|
||||||
public static enum MenuItem implements LabeledMenuItem<CalculatorDisplayViewState> {
|
* Time: 10:58 PM
|
||||||
|
*/
|
||||||
copy(R.string.c_copy) {
|
public class AndroidCalculatorDisplayView extends AutoResizeTextView implements CalculatorDisplayView {
|
||||||
@Override
|
|
||||||
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
private static enum ConversionMenuItem implements AMenuItem<CalculatorDisplayView> {
|
||||||
CalculatorModel.copyResult(context, data);
|
convert_to_bin(NumeralBase.bin),
|
||||||
}
|
convert_to_dec(NumeralBase.dec),
|
||||||
},
|
convert_to_hex(NumeralBase.hex);
|
||||||
|
|
||||||
convert_to_bin(R.string.convert_to_bin) {
|
@NotNull
|
||||||
@Override
|
private final NumeralBase toNumeralBase;
|
||||||
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
|
||||||
ConversionMenuItem.convert_to_bin.onClick(data, context);
|
private ConversionMenuItem(@NotNull NumeralBase toNumeralBase) {
|
||||||
}
|
this.toNumeralBase = toNumeralBase;
|
||||||
|
}
|
||||||
@Override
|
|
||||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||||
return ConversionMenuItem.convert_to_bin.isItemVisibleFor(generic, operation);
|
boolean result = false;
|
||||||
}
|
|
||||||
},
|
if (operation == JsclOperation.numeric) {
|
||||||
|
if (generic.getConstants().isEmpty()) {
|
||||||
convert_to_dec(R.string.convert_to_dec) {
|
try {
|
||||||
@Override
|
convert(generic);
|
||||||
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
|
||||||
ConversionMenuItem.convert_to_dec.onClick(data, context);
|
// conversion possible => return true
|
||||||
}
|
result = true;
|
||||||
|
|
||||||
@Override
|
} catch (UnitConverterViewBuilder.ConversionException e) {
|
||||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
// conversion is not possible => return false
|
||||||
return ConversionMenuItem.convert_to_dec.isItemVisibleFor(generic, operation);
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
convert_to_hex(R.string.convert_to_hex) {
|
return result;
|
||||||
@Override
|
}
|
||||||
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
|
||||||
ConversionMenuItem.convert_to_hex.onClick(data, context);
|
@Override
|
||||||
}
|
public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) {
|
||||||
|
final NumeralBase fromNumeralBase = CalculatorEngine.instance.getEngine().getNumeralBase();
|
||||||
@Override
|
|
||||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
final Generic lastResult = CalculatorLocatorImpl.getInstance().getCalculatorDisplay().getViewState().getResult();
|
||||||
return ConversionMenuItem.convert_to_hex.isItemVisibleFor(generic, operation);
|
|
||||||
}
|
if (lastResult != null) {
|
||||||
},
|
String to;
|
||||||
|
try {
|
||||||
convert(R.string.c_convert) {
|
to = convert(lastResult);
|
||||||
@Override
|
|
||||||
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
// add prefix
|
||||||
final Generic result = data.getResult();
|
if (fromNumeralBase != toNumeralBase) {
|
||||||
if (result != null) {
|
to = toNumeralBase.getJsclPrefix() + to;
|
||||||
new NumeralBaseConverterDialog(result.toString()).show(context);
|
}
|
||||||
}
|
} catch (UnitConverterViewBuilder.ConversionException e) {
|
||||||
}
|
to = context.getString(R.string.c_error);
|
||||||
|
}
|
||||||
@Override
|
|
||||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
data.setText(to);
|
||||||
return operation == JsclOperation.numeric && generic.getConstants().isEmpty();
|
//data.redraw();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
plot(R.string.c_plot) {
|
@NotNull
|
||||||
@Override
|
private String convert(@NotNull Generic generic) throws UnitConverterViewBuilder.ConversionException {
|
||||||
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
final NumeralBase fromNumeralBase = CalculatorEngine.instance.getEngine().getNumeralBase();
|
||||||
final Generic generic = data.getResult();
|
|
||||||
assert generic != null;
|
if (fromNumeralBase != toNumeralBase) {
|
||||||
|
String from = generic.toString();
|
||||||
final Constant constant = CollectionsUtils.getFirstCollectionElement(getNotSystemConstants(generic));
|
if (!StringUtils.isEmpty(from)) {
|
||||||
assert constant != null;
|
try {
|
||||||
CalculatorActivityLauncher.plotGraph(context, generic, constant);
|
from = ToJsclTextProcessor.getInstance().process(from).getExpression();
|
||||||
}
|
} catch (CalculatorParseException e) {
|
||||||
|
// ok, problems while processing occurred
|
||||||
@Override
|
}
|
||||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
}
|
||||||
boolean result = false;
|
|
||||||
|
return UnitConverterViewBuilder.doConversion(AndroidNumeralBase.getConverter(), from, AndroidNumeralBase.valueOf(fromNumeralBase), AndroidNumeralBase.valueOf(toNumeralBase));
|
||||||
if (operation == JsclOperation.simplify) {
|
} else {
|
||||||
if (getNotSystemConstants(generic).size() == 1) {
|
return generic.toString();
|
||||||
result = true;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
public static enum MenuItem implements LabeledMenuItem<CalculatorDisplayView> {
|
||||||
}
|
|
||||||
|
copy(R.string.c_copy) {
|
||||||
@NotNull
|
@Override
|
||||||
private Set<Constant> getNotSystemConstants(@NotNull Generic generic) {
|
public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) {
|
||||||
final Set<Constant> notSystemConstants = new HashSet<Constant>();
|
CalculatorModel.copyResult(context, data);
|
||||||
|
}
|
||||||
for (Constant constant : generic.getConstants()) {
|
},
|
||||||
IConstant var = CalculatorEngine.instance.getVarsRegistry().get(constant.getName());
|
|
||||||
if (var != null && !var.isSystem() && !var.isDefined()) {
|
convert_to_bin(R.string.convert_to_bin) {
|
||||||
notSystemConstants.add(constant);
|
@Override
|
||||||
}
|
public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) {
|
||||||
}
|
ConversionMenuItem.convert_to_bin.onClick(data, context);
|
||||||
|
}
|
||||||
return notSystemConstants;
|
|
||||||
}
|
@Override
|
||||||
};
|
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||||
|
return ConversionMenuItem.convert_to_bin.isItemVisibleFor(generic, operation);
|
||||||
private final int captionId;
|
}
|
||||||
|
},
|
||||||
MenuItem(int captionId) {
|
|
||||||
this.captionId = captionId;
|
convert_to_dec(R.string.convert_to_dec) {
|
||||||
}
|
@Override
|
||||||
|
public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) {
|
||||||
public final boolean isItemVisible(@NotNull CalculatorDisplayViewState displayViewState) {
|
ConversionMenuItem.convert_to_dec.onClick(data, context);
|
||||||
//noinspection ConstantConditions
|
}
|
||||||
return displayViewState.isValid() && displayViewState.getResult() != null && isItemVisibleFor(displayViewState.getResult(), displayViewState.getOperation());
|
|
||||||
}
|
@Override
|
||||||
|
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
return ConversionMenuItem.convert_to_dec.isItemVisibleFor(generic, operation);
|
||||||
return true;
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
@NotNull
|
convert_to_hex(R.string.convert_to_hex) {
|
||||||
@Override
|
@Override
|
||||||
public String getCaption(@NotNull Context context) {
|
public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) {
|
||||||
return context.getString(captionId);
|
ConversionMenuItem.convert_to_hex.onClick(data, context);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
@NotNull
|
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||||
private CalculatorDisplayViewState state = CalculatorDisplayViewStateImpl.newDefaultInstance();
|
return ConversionMenuItem.convert_to_hex.isItemVisibleFor(generic, operation);
|
||||||
|
}
|
||||||
@NotNull
|
},
|
||||||
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine());
|
|
||||||
|
convert(R.string.c_convert) {
|
||||||
public AndroidCalculatorDisplayView(Context context) {
|
@Override
|
||||||
super(context);
|
public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) {
|
||||||
}
|
final Generic result = data.getState().getResult();
|
||||||
|
if (result != null) {
|
||||||
public AndroidCalculatorDisplayView(Context context, AttributeSet attrs) {
|
new NumeralBaseConverterDialog(result.toString()).show(context);
|
||||||
super(context, attrs);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidCalculatorDisplayView(Context context, AttributeSet attrs, int defStyle) {
|
@Override
|
||||||
super(context, attrs, defStyle);
|
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||||
}
|
return operation == JsclOperation.numeric && generic.getConstants().isEmpty();
|
||||||
|
}
|
||||||
public boolean isValid() {
|
},
|
||||||
return this.state.isValid();
|
|
||||||
}
|
plot(R.string.c_plot) {
|
||||||
|
@Override
|
||||||
|
public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) {
|
||||||
@Override
|
final Generic generic = data.getState().getResult();
|
||||||
public void setState(@NotNull CalculatorDisplayViewState state) {
|
assert generic != null;
|
||||||
this.state = state;
|
|
||||||
if ( state.isValid() ) {
|
final Constant constant = CollectionsUtils.getFirstCollectionElement(getNotSystemConstants(generic));
|
||||||
setTextColor(getResources().getColor(R.color.default_text_color));
|
assert constant != null;
|
||||||
setText(state.getStringResult());
|
CalculatorActivityLauncher.plotGraph(context, generic, constant);
|
||||||
} else {
|
}
|
||||||
setTextColor(getResources().getColor(R.color.display_error_text_color));
|
|
||||||
setText(state.getErrorMessage());
|
@Override
|
||||||
}
|
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||||
}
|
boolean result = false;
|
||||||
|
|
||||||
@NotNull
|
if (operation == JsclOperation.simplify) {
|
||||||
@Override
|
if (getNotSystemConstants(generic).size() == 1) {
|
||||||
public CalculatorDisplayViewState getState() {
|
result = true;
|
||||||
return this.state;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
return result;
|
||||||
public void setText(CharSequence text, BufferType type) {
|
}
|
||||||
super.setText(text, type);
|
|
||||||
}
|
@NotNull
|
||||||
|
private Set<Constant> getNotSystemConstants(@NotNull Generic generic) {
|
||||||
public synchronized void redraw() {
|
final Set<Constant> notSystemConstants = new HashSet<Constant>();
|
||||||
if (isValid()) {
|
|
||||||
String text = getText().toString();
|
for (Constant constant : generic.getConstants()) {
|
||||||
|
IConstant var = CalculatorEngine.instance.getVarsRegistry().get(constant.getName());
|
||||||
Log.d(this.getClass().getName(), text);
|
if (var != null && !var.isSystem() && !var.isDefined()) {
|
||||||
|
notSystemConstants.add(constant);
|
||||||
try {
|
}
|
||||||
TextHighlighter.Result result = textHighlighter.process(text);
|
}
|
||||||
text = result.toString();
|
|
||||||
} catch (CalculatorParseException e) {
|
return notSystemConstants;
|
||||||
Log.e(this.getClass().getName(), e.getMessage(), e);
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Log.d(this.getClass().getName(), text);
|
private final int captionId;
|
||||||
super.setText(Html.fromHtml(text), BufferType.EDITABLE);
|
|
||||||
}
|
MenuItem(int captionId) {
|
||||||
|
this.captionId = captionId;
|
||||||
// todo serso: think where to move it (keep in mind org.solovyev.android.view.AutoResizeTextView.resetTextSize())
|
}
|
||||||
setAddEllipsis(false);
|
|
||||||
setMinTextSize(10);
|
public final boolean isItemVisible(@NotNull CalculatorDisplayViewState displayViewState) {
|
||||||
resizeText();
|
//noinspection ConstantConditions
|
||||||
}
|
return displayViewState.isValid() && displayViewState.getResult() != null && isItemVisibleFor(displayViewState.getResult(), displayViewState.getOperation());
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public int getSelection() {
|
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||||
return this.getSelectionStart();
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@NotNull
|
||||||
public void setSelection(int selection) {
|
@Override
|
||||||
// not supported by TextView
|
public String getCaption(@NotNull Context context) {
|
||||||
}
|
return context.getString(captionId);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private CalculatorDisplayViewState state = CalculatorDisplayViewStateImpl.newDefaultInstance();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine());
|
||||||
|
|
||||||
|
public AndroidCalculatorDisplayView(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AndroidCalculatorDisplayView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AndroidCalculatorDisplayView(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return this.state.isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(@NotNull CalculatorDisplayViewState state) {
|
||||||
|
this.state = state;
|
||||||
|
if ( state.isValid() ) {
|
||||||
|
setTextColor(getResources().getColor(R.color.default_text_color));
|
||||||
|
setText(state.getStringResult());
|
||||||
|
} else {
|
||||||
|
setTextColor(getResources().getColor(R.color.display_error_text_color));
|
||||||
|
setText(state.getErrorMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public CalculatorDisplayViewState getState() {
|
||||||
|
return this.state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setText(CharSequence text, BufferType type) {
|
||||||
|
super.setText(text, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void redraw() {
|
||||||
|
if (isValid()) {
|
||||||
|
String text = getText().toString();
|
||||||
|
|
||||||
|
Log.d(this.getClass().getName(), text);
|
||||||
|
|
||||||
|
try {
|
||||||
|
TextHighlighter.Result result = textHighlighter.process(text);
|
||||||
|
text = result.toString();
|
||||||
|
} catch (CalculatorParseException e) {
|
||||||
|
Log.e(this.getClass().getName(), e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(this.getClass().getName(), text);
|
||||||
|
super.setText(Html.fromHtml(text), BufferType.EDITABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo serso: think where to move it (keep in mind org.solovyev.android.view.AutoResizeTextView.resetTextSize())
|
||||||
|
setAddEllipsis(false);
|
||||||
|
setMinTextSize(10);
|
||||||
|
resizeText();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSelection() {
|
||||||
|
return this.getSelectionStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSelection(int selection) {
|
||||||
|
// not supported by TextView
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,411 +1,412 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
* For more information, please, contact se.solovyev@gmail.com
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.text.ClipboardManager;
|
import android.text.ClipboardManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.CursorControl;
|
import org.solovyev.android.CursorControl;
|
||||||
import org.solovyev.android.calculator.history.AndroidCalculatorHistoryImpl;
|
import org.solovyev.android.calculator.history.AndroidCalculatorHistoryImpl;
|
||||||
import org.solovyev.android.calculator.history.CalculatorHistoryState;
|
import org.solovyev.android.calculator.history.CalculatorHistoryState;
|
||||||
import org.solovyev.android.calculator.history.TextViewEditorAdapter;
|
import org.solovyev.android.calculator.history.TextViewEditorAdapter;
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
import org.solovyev.android.calculator.math.MathType;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
import org.solovyev.android.calculator.model.CalculatorEngine;
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
import org.solovyev.android.history.HistoryControl;
|
import org.solovyev.android.history.HistoryControl;
|
||||||
import org.solovyev.android.menu.AMenuBuilder;
|
import org.solovyev.android.menu.AMenuBuilder;
|
||||||
import org.solovyev.android.menu.MenuImpl;
|
import org.solovyev.android.menu.MenuImpl;
|
||||||
import org.solovyev.common.MutableObject;
|
import org.solovyev.common.MutableObject;
|
||||||
import org.solovyev.common.history.HistoryAction;
|
import org.solovyev.common.history.HistoryAction;
|
||||||
import org.solovyev.common.msg.Message;
|
import org.solovyev.common.msg.Message;
|
||||||
import org.solovyev.common.text.StringUtils;
|
import org.solovyev.common.text.StringUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 9/12/11
|
* Date: 9/12/11
|
||||||
* Time: 11:15 PM
|
* Time: 11:15 PM
|
||||||
*/
|
*/
|
||||||
public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorHistoryState>, CalculatorEngineControl {
|
public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorHistoryState>, CalculatorEngineControl {
|
||||||
|
|
||||||
instance;
|
instance;
|
||||||
|
|
||||||
// millis to wait before evaluation after user edit action
|
// millis to wait before evaluation after user edit action
|
||||||
public static final int EVAL_DELAY_MILLIS = 0;
|
public static final int EVAL_DELAY_MILLIS = 0;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private CalculatorEditor editor;
|
private CalculatorEditor editor;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private AndroidCalculatorDisplayView display;
|
private AndroidCalculatorDisplayView display;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private CalculatorEngine calculatorEngine;
|
private CalculatorEngine calculatorEngine;
|
||||||
|
|
||||||
public CalculatorModel init(@NotNull final Activity activity, @NotNull SharedPreferences preferences, @NotNull CalculatorEngine calculator) {
|
public CalculatorModel init(@NotNull final Activity activity, @NotNull SharedPreferences preferences, @NotNull CalculatorEngine calculator) {
|
||||||
Log.d(this.getClass().getName(), "CalculatorModel initialization with activity: " + activity);
|
Log.d(this.getClass().getName(), "CalculatorModel initialization with activity: " + activity);
|
||||||
this.calculatorEngine = calculator;
|
this.calculatorEngine = calculator;
|
||||||
|
|
||||||
this.editor = (CalculatorEditor) activity.findViewById(R.id.calculatorEditor);
|
this.editor = (CalculatorEditor) activity.findViewById(R.id.calculatorEditor);
|
||||||
this.editor.init(preferences);
|
this.editor.init(preferences);
|
||||||
preferences.registerOnSharedPreferenceChangeListener(editor);
|
preferences.registerOnSharedPreferenceChangeListener(editor);
|
||||||
|
|
||||||
this.display = (AndroidCalculatorDisplayView) activity.findViewById(R.id.calculatorDisplay);
|
this.display = (AndroidCalculatorDisplayView) activity.findViewById(R.id.calculatorDisplay);
|
||||||
this.display.setOnClickListener(new CalculatorDisplayOnClickListener(activity));
|
this.display.setOnClickListener(new CalculatorDisplayOnClickListener(activity));
|
||||||
|
|
||||||
final CalculatorHistoryState lastState = AndroidCalculatorHistoryImpl.instance.getLastHistoryState();
|
final CalculatorHistoryState lastState = AndroidCalculatorHistoryImpl.instance.getLastHistoryState();
|
||||||
if (lastState == null) {
|
if (lastState == null) {
|
||||||
saveHistoryState();
|
saveHistoryState();
|
||||||
} else {
|
} else {
|
||||||
setCurrentHistoryState(lastState);
|
setCurrentHistoryState(lastState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void showEvaluationError(@NotNull Activity activity, @NotNull final String errorMessage) {
|
private static void showEvaluationError(@NotNull Activity activity, @NotNull final String errorMessage) {
|
||||||
final LayoutInflater layoutInflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
|
final LayoutInflater layoutInflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
|
||||||
|
|
||||||
final View errorMessageView = layoutInflater.inflate(R.layout.display_error_message, null);
|
final View errorMessageView = layoutInflater.inflate(R.layout.display_error_message, null);
|
||||||
((TextView) errorMessageView.findViewById(R.id.error_message_text_view)).setText(errorMessage);
|
((TextView) errorMessageView.findViewById(R.id.error_message_text_view)).setText(errorMessage);
|
||||||
|
|
||||||
final AlertDialog.Builder builder = new AlertDialog.Builder(activity)
|
final AlertDialog.Builder builder = new AlertDialog.Builder(activity)
|
||||||
.setPositiveButton(R.string.c_cancel, null)
|
.setPositiveButton(R.string.c_cancel, null)
|
||||||
.setView(errorMessageView);
|
.setView(errorMessageView);
|
||||||
|
|
||||||
builder.create().show();
|
builder.create().show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void copyResult(@NotNull Context context) {
|
public void copyResult(@NotNull Context context) {
|
||||||
copyResult(context, display);
|
copyResult(context, display);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void copyResult(@NotNull Context context, @NotNull final CalculatorDisplayViewState viewState) {
|
public static void copyResult(@NotNull Context context, @NotNull final CalculatorDisplayView display) {
|
||||||
if (viewState.isValid()) {
|
final CalculatorDisplayViewState displayViewState = display.getState();
|
||||||
final CharSequence text = viewState.getText();
|
if (displayViewState.isValid()) {
|
||||||
if (!StringUtils.isEmpty(text)) {
|
final CharSequence text = display.getText();
|
||||||
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
|
if (!StringUtils.isEmpty(text)) {
|
||||||
clipboard.setText(text.toString());
|
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
|
||||||
Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show();
|
clipboard.setText(text.toString());
|
||||||
}
|
Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private void saveHistoryState() {
|
|
||||||
AndroidCalculatorHistoryImpl.instance.addState(getCurrentHistoryState());
|
private void saveHistoryState() {
|
||||||
}
|
AndroidCalculatorHistoryImpl.instance.addState(getCurrentHistoryState());
|
||||||
|
}
|
||||||
public void setCursorOnStart() {
|
|
||||||
editor.setSelection(0);
|
public void setCursorOnStart() {
|
||||||
}
|
editor.setSelection(0);
|
||||||
|
}
|
||||||
public void setCursorOnEnd() {
|
|
||||||
editor.setSelection(editor.getText().length());
|
public void setCursorOnEnd() {
|
||||||
}
|
editor.setSelection(editor.getText().length());
|
||||||
|
}
|
||||||
public void moveCursorLeft() {
|
|
||||||
if (editor.getSelectionStart() > 0) {
|
public void moveCursorLeft() {
|
||||||
editor.setSelection(editor.getSelectionStart() - 1);
|
if (editor.getSelectionStart() > 0) {
|
||||||
}
|
editor.setSelection(editor.getSelectionStart() - 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public void moveCursorRight() {
|
|
||||||
if (editor.getSelectionStart() < editor.getText().length()) {
|
public void moveCursorRight() {
|
||||||
editor.setSelection(editor.getSelectionStart() + 1);
|
if (editor.getSelectionStart() < editor.getText().length()) {
|
||||||
}
|
editor.setSelection(editor.getSelectionStart() + 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public void doTextOperation(@NotNull TextOperation operation) {
|
|
||||||
doTextOperation(operation, true);
|
public void doTextOperation(@NotNull TextOperation operation) {
|
||||||
}
|
doTextOperation(operation, true);
|
||||||
|
}
|
||||||
public void doTextOperation(@NotNull TextOperation operation, boolean delayEvaluate) {
|
|
||||||
doTextOperation(operation, delayEvaluate, JsclOperation.numeric, false);
|
public void doTextOperation(@NotNull TextOperation operation, boolean delayEvaluate) {
|
||||||
}
|
doTextOperation(operation, delayEvaluate, JsclOperation.numeric, false);
|
||||||
|
}
|
||||||
public void doTextOperation(@NotNull TextOperation operation, boolean delayEvaluate, @NotNull JsclOperation jsclOperation, boolean forceEval) {
|
|
||||||
final String editorStateBefore = this.editor.getText().toString();
|
public void doTextOperation(@NotNull TextOperation operation, boolean delayEvaluate, @NotNull JsclOperation jsclOperation, boolean forceEval) {
|
||||||
|
final String editorStateBefore = this.editor.getText().toString();
|
||||||
Log.d(CalculatorModel.class.getName(), "Editor state changed before '" + editorStateBefore + "'");
|
|
||||||
operation.doOperation(this.editor);
|
Log.d(CalculatorModel.class.getName(), "Editor state changed before '" + editorStateBefore + "'");
|
||||||
//Log.d(CalculatorModel.class.getName(), "Doing text operation" + StringUtils.fromStackTrace(Thread.currentThread().getStackTrace()));
|
operation.doOperation(this.editor);
|
||||||
|
//Log.d(CalculatorModel.class.getName(), "Doing text operation" + StringUtils.fromStackTrace(Thread.currentThread().getStackTrace()));
|
||||||
final String editorStateAfter = this.editor.getText().toString();
|
|
||||||
if (forceEval ||!editorStateBefore.equals(editorStateAfter)) {
|
final String editorStateAfter = this.editor.getText().toString();
|
||||||
|
if (forceEval ||!editorStateBefore.equals(editorStateAfter)) {
|
||||||
editor.redraw();
|
|
||||||
|
editor.redraw();
|
||||||
evaluate(delayEvaluate, editorStateAfter, jsclOperation, null);
|
|
||||||
}
|
evaluate(delayEvaluate, editorStateAfter, jsclOperation, null);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@NotNull
|
|
||||||
private final static MutableObject<Runnable> pendingOperation = new MutableObject<Runnable>();
|
@NotNull
|
||||||
|
private final static MutableObject<Runnable> pendingOperation = new MutableObject<Runnable>();
|
||||||
private void evaluate(boolean delayEvaluate,
|
|
||||||
@NotNull final String expression,
|
private void evaluate(boolean delayEvaluate,
|
||||||
@NotNull final JsclOperation operation,
|
@NotNull final String expression,
|
||||||
@Nullable CalculatorHistoryState historyState) {
|
@NotNull final JsclOperation operation,
|
||||||
|
@Nullable CalculatorHistoryState historyState) {
|
||||||
final CalculatorHistoryState localHistoryState;
|
|
||||||
if (historyState == null) {
|
final CalculatorHistoryState localHistoryState;
|
||||||
//this.display.setText("");
|
if (historyState == null) {
|
||||||
localHistoryState = getCurrentHistoryState();
|
//this.display.setText("");
|
||||||
} else {
|
localHistoryState = getCurrentHistoryState();
|
||||||
this.display.setText(historyState.getDisplayState().getEditorState().getText());
|
} else {
|
||||||
localHistoryState = historyState;
|
this.display.setText(historyState.getDisplayState().getEditorState().getText());
|
||||||
}
|
localHistoryState = historyState;
|
||||||
|
}
|
||||||
pendingOperation.setObject(new Runnable() {
|
|
||||||
@Override
|
pendingOperation.setObject(new Runnable() {
|
||||||
public void run() {
|
@Override
|
||||||
// allow only one runner at one time
|
public void run() {
|
||||||
synchronized (pendingOperation) {
|
// allow only one runner at one time
|
||||||
//lock all operations with history
|
synchronized (pendingOperation) {
|
||||||
if (pendingOperation.getObject() == this) {
|
//lock all operations with history
|
||||||
// actually nothing shall be logged while text operations are done
|
if (pendingOperation.getObject() == this) {
|
||||||
evaluate(expression, operation, this);
|
// actually nothing shall be logged while text operations are done
|
||||||
|
evaluate(expression, operation, this);
|
||||||
if (pendingOperation.getObject() == this) {
|
|
||||||
// todo serso: of course there is small probability that someone will set pendingOperation after if statement but before .setObject(null)
|
if (pendingOperation.getObject() == this) {
|
||||||
pendingOperation.setObject(null);
|
// todo serso: of course there is small probability that someone will set pendingOperation after if statement but before .setObject(null)
|
||||||
localHistoryState.setDisplayState(getCurrentHistoryState().getDisplayState());
|
pendingOperation.setObject(null);
|
||||||
}
|
localHistoryState.setDisplayState(getCurrentHistoryState().getDisplayState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
});
|
||||||
if (delayEvaluate) {
|
|
||||||
if (historyState == null) {
|
if (delayEvaluate) {
|
||||||
AndroidCalculatorHistoryImpl.instance.addState(localHistoryState);
|
if (historyState == null) {
|
||||||
}
|
AndroidCalculatorHistoryImpl.instance.addState(localHistoryState);
|
||||||
// todo serso: this is not correct - operation is processing still in the same thread
|
}
|
||||||
new Handler().postDelayed(pendingOperation.getObject(), EVAL_DELAY_MILLIS);
|
// todo serso: this is not correct - operation is processing still in the same thread
|
||||||
} else {
|
new Handler().postDelayed(pendingOperation.getObject(), EVAL_DELAY_MILLIS);
|
||||||
pendingOperation.getObject().run();
|
} else {
|
||||||
if (historyState == null) {
|
pendingOperation.getObject().run();
|
||||||
AndroidCalculatorHistoryImpl.instance.addState(localHistoryState);
|
if (historyState == null) {
|
||||||
}
|
AndroidCalculatorHistoryImpl.instance.addState(localHistoryState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void evaluate() {
|
@Override
|
||||||
evaluate(false, this.editor.getText().toString(), JsclOperation.numeric, null);
|
public void evaluate() {
|
||||||
}
|
evaluate(false, this.editor.getText().toString(), JsclOperation.numeric, null);
|
||||||
|
}
|
||||||
public void evaluate(@NotNull JsclOperation operation) {
|
|
||||||
evaluate(false, this.editor.getText().toString(), operation, null);
|
public void evaluate(@NotNull JsclOperation operation) {
|
||||||
}
|
evaluate(false, this.editor.getText().toString(), operation, null);
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void simplify() {
|
@Override
|
||||||
evaluate(false, this.editor.getText().toString(), JsclOperation.simplify, null);
|
public void simplify() {
|
||||||
}
|
evaluate(false, this.editor.getText().toString(), JsclOperation.simplify, null);
|
||||||
|
}
|
||||||
private void evaluate(@Nullable final String expression,
|
|
||||||
@NotNull JsclOperation operation,
|
private void evaluate(@Nullable final String expression,
|
||||||
@NotNull Runnable currentRunner) {
|
@NotNull JsclOperation operation,
|
||||||
|
@NotNull Runnable currentRunner) {
|
||||||
if (!StringUtils.isEmpty(expression)) {
|
|
||||||
try {
|
if (!StringUtils.isEmpty(expression)) {
|
||||||
Log.d(CalculatorModel.class.getName(), "Trying to evaluate '" + operation + "': " + expression /*+ StringUtils.fromStackTrace(Thread.currentThread().getStackTrace())*/);
|
try {
|
||||||
final CalculatorOutput result = calculatorEngine.evaluate(operation, expression);
|
Log.d(CalculatorModel.class.getName(), "Trying to evaluate '" + operation + "': " + expression /*+ StringUtils.fromStackTrace(Thread.currentThread().getStackTrace())*/);
|
||||||
|
final CalculatorOutput result = calculatorEngine.evaluate(operation, expression);
|
||||||
// todo serso: second condition might replaced with expression.equals(this.editor.getText().toString()) ONLY if expression will be formatted with text highlighter
|
|
||||||
if (currentRunner == pendingOperation.getObject() && this.editor.getText().length() > 0) {
|
// todo serso: second condition might replaced with expression.equals(this.editor.getText().toString()) ONLY if expression will be formatted with text highlighter
|
||||||
display.setText(result.getStringResult());
|
if (currentRunner == pendingOperation.getObject() && this.editor.getText().length() > 0) {
|
||||||
} else {
|
display.setText(result.getStringResult());
|
||||||
display.setText("");
|
} else {
|
||||||
}
|
display.setText("");
|
||||||
display.setJsclOperation(result.getOperation());
|
}
|
||||||
display.setGenericResult(result.getResult());
|
display.setJsclOperation(result.getOperation());
|
||||||
} catch (CalculatorParseException e) {
|
display.setGenericResult(result.getResult());
|
||||||
handleEvaluationException(expression, display, operation, e);
|
} catch (CalculatorParseException e) {
|
||||||
} catch (CalculatorEvalException e) {
|
handleEvaluationException(expression, display, operation, e);
|
||||||
handleEvaluationException(expression, display, operation, e);
|
} catch (CalculatorEvalException e) {
|
||||||
}
|
handleEvaluationException(expression, display, operation, e);
|
||||||
} else {
|
}
|
||||||
this.display.setText("");
|
} else {
|
||||||
this.display.setJsclOperation(operation);
|
this.display.setText("");
|
||||||
this.display.setGenericResult(null);
|
this.display.setJsclOperation(operation);
|
||||||
}
|
this.display.setGenericResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
this.display.redraw();
|
|
||||||
}
|
this.display.redraw();
|
||||||
|
}
|
||||||
private void handleEvaluationException(@NotNull String expression,
|
|
||||||
@NotNull AndroidCalculatorDisplayView localDisplay,
|
private void handleEvaluationException(@NotNull String expression,
|
||||||
@NotNull JsclOperation operation,
|
@NotNull AndroidCalculatorDisplayView localDisplay,
|
||||||
@NotNull Message e) {
|
@NotNull JsclOperation operation,
|
||||||
Log.d(CalculatorModel.class.getName(), "Evaluation failed for : " + expression + ". Error message: " + e);
|
@NotNull Message e) {
|
||||||
if ( StringUtils.isEmpty(localDisplay.getText()) ) {
|
Log.d(CalculatorModel.class.getName(), "Evaluation failed for : " + expression + ". Error message: " + e);
|
||||||
// if previous display state was empty -> show error
|
if ( StringUtils.isEmpty(localDisplay.getText()) ) {
|
||||||
localDisplay.setText(R.string.c_syntax_error);
|
// if previous display state was empty -> show error
|
||||||
} else {
|
localDisplay.setText(R.string.c_syntax_error);
|
||||||
// show previous result instead of error caption (actually previous result will be greyed)
|
} else {
|
||||||
}
|
// show previous result instead of error caption (actually previous result will be greyed)
|
||||||
localDisplay.setJsclOperation(operation);
|
}
|
||||||
localDisplay.setGenericResult(null);
|
localDisplay.setJsclOperation(operation);
|
||||||
localDisplay.setValid(false);
|
localDisplay.setGenericResult(null);
|
||||||
localDisplay.setErrorMessage(e.getLocalizedMessage());
|
localDisplay.setValid(false);
|
||||||
}
|
localDisplay.setErrorMessage(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
public void clear() {
|
|
||||||
if (!StringUtils.isEmpty(editor.getText()) || !StringUtils.isEmpty(display.getText())) {
|
public void clear() {
|
||||||
editor.getText().clear();
|
if (!StringUtils.isEmpty(editor.getText()) || !StringUtils.isEmpty(display.getText())) {
|
||||||
display.setText("");
|
editor.getText().clear();
|
||||||
saveHistoryState();
|
display.setText("");
|
||||||
}
|
saveHistoryState();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public void processDigitButtonAction(@Nullable final String text) {
|
|
||||||
processDigitButtonAction(text, true);
|
public void processDigitButtonAction(@Nullable final String text) {
|
||||||
}
|
processDigitButtonAction(text, true);
|
||||||
|
}
|
||||||
public void processDigitButtonAction(@Nullable final String text, boolean delayEvaluate) {
|
|
||||||
|
public void processDigitButtonAction(@Nullable final String text, boolean delayEvaluate) {
|
||||||
if (!StringUtils.isEmpty(text)) {
|
|
||||||
doTextOperation(new CalculatorModel.TextOperation() {
|
if (!StringUtils.isEmpty(text)) {
|
||||||
|
doTextOperation(new CalculatorModel.TextOperation() {
|
||||||
@Override
|
|
||||||
public void doOperation(@NotNull EditText editor) {
|
@Override
|
||||||
int cursorPositionOffset = 0;
|
public void doOperation(@NotNull EditText editor) {
|
||||||
final StringBuilder textToBeInserted = new StringBuilder(text);
|
int cursorPositionOffset = 0;
|
||||||
|
final StringBuilder textToBeInserted = new StringBuilder(text);
|
||||||
final MathType.Result mathType = MathType.getType(text, 0, false);
|
|
||||||
switch (mathType.getMathType()) {
|
final MathType.Result mathType = MathType.getType(text, 0, false);
|
||||||
case function:
|
switch (mathType.getMathType()) {
|
||||||
textToBeInserted.append("()");
|
case function:
|
||||||
cursorPositionOffset = -1;
|
textToBeInserted.append("()");
|
||||||
break;
|
cursorPositionOffset = -1;
|
||||||
case operator:
|
break;
|
||||||
textToBeInserted.append("()");
|
case operator:
|
||||||
cursorPositionOffset = -1;
|
textToBeInserted.append("()");
|
||||||
break;
|
cursorPositionOffset = -1;
|
||||||
case comma:
|
break;
|
||||||
textToBeInserted.append(" ");
|
case comma:
|
||||||
break;
|
textToBeInserted.append(" ");
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
if (cursorPositionOffset == 0) {
|
|
||||||
if (MathType.openGroupSymbols.contains(text)) {
|
if (cursorPositionOffset == 0) {
|
||||||
cursorPositionOffset = -1;
|
if (MathType.openGroupSymbols.contains(text)) {
|
||||||
}
|
cursorPositionOffset = -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
editor.getText().insert(editor.getSelectionStart(), textToBeInserted.toString());
|
|
||||||
editor.setSelection(editor.getSelectionStart() + cursorPositionOffset, editor.getSelectionEnd() + cursorPositionOffset);
|
editor.getText().insert(editor.getSelectionStart(), textToBeInserted.toString());
|
||||||
}
|
editor.setSelection(editor.getSelectionStart() + cursorPositionOffset, editor.getSelectionEnd() + cursorPositionOffset);
|
||||||
}, delayEvaluate);
|
}
|
||||||
}
|
}, delayEvaluate);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public static interface TextOperation {
|
|
||||||
|
public static interface TextOperation {
|
||||||
void doOperation(@NotNull EditText editor);
|
|
||||||
|
void doOperation(@NotNull EditText editor);
|
||||||
}
|
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void doHistoryAction(@NotNull HistoryAction historyAction) {
|
@Override
|
||||||
synchronized (AndroidCalculatorHistoryImpl.instance) {
|
public void doHistoryAction(@NotNull HistoryAction historyAction) {
|
||||||
if (AndroidCalculatorHistoryImpl.instance.isActionAvailable(historyAction)) {
|
synchronized (AndroidCalculatorHistoryImpl.instance) {
|
||||||
final CalculatorHistoryState newState = AndroidCalculatorHistoryImpl.instance.doAction(historyAction, getCurrentHistoryState());
|
if (AndroidCalculatorHistoryImpl.instance.isActionAvailable(historyAction)) {
|
||||||
if (newState != null) {
|
final CalculatorHistoryState newState = AndroidCalculatorHistoryImpl.instance.doAction(historyAction, getCurrentHistoryState());
|
||||||
setCurrentHistoryState(newState);
|
if (newState != null) {
|
||||||
}
|
setCurrentHistoryState(newState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) {
|
@Override
|
||||||
synchronized (AndroidCalculatorHistoryImpl.instance) {
|
public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) {
|
||||||
Log.d(this.getClass().getName(), "Saved history found: " + editorHistoryState);
|
synchronized (AndroidCalculatorHistoryImpl.instance) {
|
||||||
|
Log.d(this.getClass().getName(), "Saved history found: " + editorHistoryState);
|
||||||
editorHistoryState.setValuesFromHistory(new TextViewEditorAdapter(this.editor), this.display);
|
|
||||||
|
editorHistoryState.setValuesFromHistory(new TextViewEditorAdapter(this.editor), this.display);
|
||||||
final String expression = this.editor.getText().toString();
|
|
||||||
if ( !StringUtils.isEmpty(expression) ) {
|
final String expression = this.editor.getText().toString();
|
||||||
if ( StringUtils.isEmpty(this.display.getText().toString()) ) {
|
if ( !StringUtils.isEmpty(expression) ) {
|
||||||
evaluate(false, expression, this.display.getJsclOperation(), editorHistoryState);
|
if ( StringUtils.isEmpty(this.display.getText().toString()) ) {
|
||||||
}
|
evaluate(false, expression, this.display.getJsclOperation(), editorHistoryState);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
editor.redraw();
|
|
||||||
display.redraw();
|
editor.redraw();
|
||||||
}
|
display.redraw();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@Override
|
|
||||||
@NotNull
|
@Override
|
||||||
public CalculatorHistoryState getCurrentHistoryState() {
|
@NotNull
|
||||||
synchronized (AndroidCalculatorHistoryImpl.instance) {
|
public CalculatorHistoryState getCurrentHistoryState() {
|
||||||
return CalculatorHistoryState.newInstance(new TextViewEditorAdapter(this.editor), this.display);
|
synchronized (AndroidCalculatorHistoryImpl.instance) {
|
||||||
}
|
return CalculatorHistoryState.newInstance(new TextViewEditorAdapter(this.editor), this.display);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@NotNull
|
|
||||||
public AndroidCalculatorDisplayView getDisplay() {
|
@NotNull
|
||||||
return display;
|
public AndroidCalculatorDisplayView getDisplay() {
|
||||||
}
|
return display;
|
||||||
|
}
|
||||||
private static class CalculatorDisplayOnClickListener implements View.OnClickListener {
|
|
||||||
|
private static class CalculatorDisplayOnClickListener implements View.OnClickListener {
|
||||||
@NotNull
|
|
||||||
private final Activity activity;
|
@NotNull
|
||||||
|
private final Activity activity;
|
||||||
public CalculatorDisplayOnClickListener(@NotNull Activity activity) {
|
|
||||||
this.activity = activity;
|
public CalculatorDisplayOnClickListener(@NotNull Activity activity) {
|
||||||
}
|
this.activity = activity;
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
@Override
|
||||||
if (v instanceof CalculatorDisplayView) {
|
public void onClick(View v) {
|
||||||
final CalculatorDisplay cd = CalculatorLocatorImpl.getInstance().getCalculatorDisplay();
|
if (v instanceof CalculatorDisplayView) {
|
||||||
|
final CalculatorDisplay cd = CalculatorLocatorImpl.getInstance().getCalculatorDisplay();
|
||||||
final CalculatorDisplayViewState displayViewState = cd.getViewState();
|
|
||||||
|
final CalculatorDisplayViewState displayViewState = cd.getViewState();
|
||||||
if (displayViewState.isValid()) {
|
|
||||||
final List<AndroidCalculatorDisplayView.MenuItem> filteredMenuItems = new ArrayList<AndroidCalculatorDisplayView.MenuItem>(AndroidCalculatorDisplayView.MenuItem.values().length);
|
if (displayViewState.isValid()) {
|
||||||
for (AndroidCalculatorDisplayView.MenuItem menuItem : AndroidCalculatorDisplayView.MenuItem.values()) {
|
final List<AndroidCalculatorDisplayView.MenuItem> filteredMenuItems = new ArrayList<AndroidCalculatorDisplayView.MenuItem>(AndroidCalculatorDisplayView.MenuItem.values().length);
|
||||||
if (menuItem.isItemVisible(displayViewState)) {
|
for (AndroidCalculatorDisplayView.MenuItem menuItem : AndroidCalculatorDisplayView.MenuItem.values()) {
|
||||||
filteredMenuItems.add(menuItem);
|
if (menuItem.isItemVisible(displayViewState)) {
|
||||||
}
|
filteredMenuItems.add(menuItem);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!filteredMenuItems.isEmpty()) {
|
|
||||||
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 = displayViewState.getErrorMessage();
|
} else {
|
||||||
if (errorMessage != null) {
|
final String errorMessage = displayViewState.getErrorMessage();
|
||||||
showEvaluationError(activity, errorMessage);
|
if (errorMessage != null) {
|
||||||
}
|
showEvaluationError(activity, errorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,224 +1,259 @@
|
|||||||
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.android.calculator.CalculatorImpl;
|
import org.solovyev.math.units.Unit;
|
||||||
import org.solovyev.math.units.Unit;
|
import org.solovyev.math.units.UnitConverter;
|
||||||
import org.solovyev.math.units.UnitConverter;
|
import org.solovyev.math.units.UnitImpl;
|
||||||
import org.solovyev.math.units.UnitImpl;
|
import org.solovyev.math.units.UnitType;
|
||||||
import org.solovyev.math.units.UnitType;
|
import org.solovyev.android.calculator.R;
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.view.ViewBuilder;
|
||||||
import org.solovyev.android.view.ViewBuilder;
|
import org.solovyev.android.view.ViewFromLayoutBuilder;
|
||||||
import org.solovyev.android.view.ViewFromLayoutBuilder;
|
import org.solovyev.common.text.StringUtils;
|
||||||
|
|
||||||
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(CalculatorImpl.doConversion(converter, from, getFromUnitType(main), getToUnitType(main)));
|
toEditText.setText(doConversion(converter, from, getFromUnitType(main), getToUnitType(main)));
|
||||||
} catch (CalculatorImpl.ConversionException e) {
|
} catch (ConversionException e) {
|
||||||
toEditText.setText(context.getString(R.string.c_error));
|
toEditText.setText(context.getString(R.string.c_error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
public static final class ConversionException extends Exception {
|
||||||
private static Unit<String> getToUnit(@NotNull View main) {
|
private ConversionException() {
|
||||||
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);
|
|
||||||
return (UnitType<String>) toSpinner.getSelectedItem();
|
@NotNull
|
||||||
}
|
public static String doConversion(@NotNull UnitConverter<String> converter,
|
||||||
|
@Nullable String from,
|
||||||
@NotNull
|
@NotNull UnitType<String> fromUnitType,
|
||||||
private static Unit<String> getFromUnit(@NotNull View main) {
|
@NotNull UnitType<String> toUnitType) throws ConversionException{
|
||||||
final EditText fromUnits = (EditText) main.findViewById(R.id.units_from);
|
final String result;
|
||||||
return UnitImpl.newInstance(fromUnits.getText().toString(), getFromUnitType(main));
|
|
||||||
}
|
if (StringUtils.isEmpty(from)) {
|
||||||
|
result = "";
|
||||||
@NotNull
|
} else {
|
||||||
private static UnitType<String> getFromUnitType(@NotNull View main) {
|
|
||||||
final Spinner fromSpinner = (Spinner) main.findViewById(R.id.unit_types_from);
|
String to = null;
|
||||||
return (UnitType<String>) fromSpinner.getSelectedItem();
|
try {
|
||||||
}
|
if (converter.isSupported(fromUnitType, toUnitType)) {
|
||||||
|
to = converter.convert(UnitImpl.newInstance(from, fromUnitType), toUnitType).getValue();
|
||||||
public static class CustomButtonData {
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
@NotNull
|
throw new ConversionException(e);
|
||||||
private String text;
|
}
|
||||||
|
|
||||||
@NotNull
|
result = to;
|
||||||
private CustomButtonOnClickListener clickListener;
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
public CustomButtonData(@NotNull String text, @NotNull CustomButtonOnClickListener clickListener) {
|
}
|
||||||
this.text = text;
|
|
||||||
this.clickListener = clickListener;
|
@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));
|
||||||
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user