New core implementation
This commit is contained in:
parent
eb37fe495b
commit
1d2aaa9d47
@ -1,85 +1,85 @@
|
|||||||
/*
|
/*
|
||||||
* 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
|
||||||
* or visit http://se.solovyev.org
|
* or visit http://se.solovyev.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import jscl.MathEngine;
|
import jscl.MathEngine;
|
||||||
import jscl.NumeralBase;
|
import jscl.NumeralBase;
|
||||||
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.math.MathType;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
import org.solovyev.common.text.StringUtils;
|
import org.solovyev.common.text.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 12/15/11
|
* Date: 12/15/11
|
||||||
* Time: 9:01 PM
|
* Time: 9:01 PM
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractNumberBuilder {
|
public abstract class AbstractNumberBuilder {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected final MathEngine engine;
|
protected final MathEngine engine;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
protected StringBuilder numberBuilder = null;
|
protected StringBuilder numberBuilder = null;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
protected NumeralBase nb;
|
protected NumeralBase nb;
|
||||||
|
|
||||||
protected AbstractNumberBuilder(@NotNull MathEngine engine) {
|
protected AbstractNumberBuilder(@NotNull MathEngine engine) {
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
this.nb = engine.getNumeralBase();
|
this.nb = engine.getNumeralBase();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method determines if we can continue to process current number
|
* Method determines if we can continue to process current number
|
||||||
*
|
*
|
||||||
* @param mathTypeResult current math type result
|
* @param mathTypeResult current math type result
|
||||||
* @return true if we can continue of processing of current number, if false - new number should be constructed
|
* @return true if we can continue of processing of current number, if false - new number should be constructed
|
||||||
*/
|
*/
|
||||||
protected boolean canContinue(@NotNull MathType.Result mathTypeResult) {
|
protected boolean canContinue(@NotNull MathType.Result mathTypeResult) {
|
||||||
boolean result = mathTypeResult.getMathType().getGroupType() == MathType.MathGroupType.number &&
|
boolean result = mathTypeResult.getMathType().getGroupType() == MathType.MathGroupType.number &&
|
||||||
!spaceBefore(mathTypeResult) &&
|
!spaceBefore(mathTypeResult) &&
|
||||||
numeralBaseCheck(mathTypeResult) &&
|
numeralBaseCheck(mathTypeResult) &&
|
||||||
numeralBaseInTheStart(mathTypeResult.getMathType()) || isSignAfterE(mathTypeResult);
|
numeralBaseInTheStart(mathTypeResult.getMathType()) || isSignAfterE(mathTypeResult);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean spaceBefore(@NotNull MathType.Result mathTypeResult) {
|
private boolean spaceBefore(@NotNull MathType.Result mathTypeResult) {
|
||||||
return numberBuilder == null && StringUtils.isEmpty(mathTypeResult.getMatch().trim());
|
return numberBuilder == null && StringUtils.isEmpty(mathTypeResult.getMatch().trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean numeralBaseInTheStart(@NotNull MathType mathType) {
|
private boolean numeralBaseInTheStart(@NotNull MathType mathType) {
|
||||||
return mathType != MathType.numeral_base || numberBuilder == null;
|
return mathType != MathType.numeral_base || numberBuilder == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean numeralBaseCheck(@NotNull MathType.Result mathType) {
|
private boolean numeralBaseCheck(@NotNull MathType.Result mathType) {
|
||||||
return mathType.getMathType() != MathType.digit || getNumeralBase().getAcceptableCharacters().contains(mathType.getMatch().charAt(0));
|
return mathType.getMathType() != MathType.digit || getNumeralBase().getAcceptableCharacters().contains(mathType.getMatch().charAt(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSignAfterE(@NotNull MathType.Result mathTypeResult) {
|
private boolean isSignAfterE(@NotNull MathType.Result mathTypeResult) {
|
||||||
if (!isHexMode()) {
|
if (!isHexMode()) {
|
||||||
if ("-".equals(mathTypeResult.getMatch()) || "+".equals(mathTypeResult.getMatch())) {
|
if ("-".equals(mathTypeResult.getMatch()) || "+".equals(mathTypeResult.getMatch())) {
|
||||||
final StringBuilder localNb = numberBuilder;
|
final StringBuilder localNb = numberBuilder;
|
||||||
if (localNb != null && localNb.length() > 0) {
|
if (localNb != null && localNb.length() > 0) {
|
||||||
if (localNb.charAt(localNb.length() - 1) == MathType.POWER_10) {
|
if (localNb.charAt(localNb.length() - 1) == MathType.POWER_10) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isHexMode() {
|
public boolean isHexMode() {
|
||||||
return nb == NumeralBase.hex || (nb == null && engine.getNumeralBase() == NumeralBase.hex);
|
return nb == NumeralBase.hex || (nb == null && engine.getNumeralBase() == NumeralBase.hex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected NumeralBase getNumeralBase() {
|
protected NumeralBase getNumeralBase() {
|
||||||
return nb == null ? engine.getNumeralBase() : nb;
|
return nb == null ? engine.getNumeralBase() : nb;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 16:38
|
||||||
|
*/
|
||||||
|
public interface Calculator extends CalculatorEventContainer {
|
||||||
|
}
|
@ -1,73 +1,72 @@
|
|||||||
/*
|
/*
|
||||||
* 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
|
||||||
* or visit http://se.solovyev.org
|
* or visit http://se.solovyev.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import jscl.AbstractJsclArithmeticException;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.solovyev.common.exceptions.SersoException;
|
||||||
import org.solovyev.common.exceptions.SersoException;
|
import org.solovyev.common.msg.Message;
|
||||||
import org.solovyev.common.msg.Message;
|
import org.solovyev.common.msg.MessageType;
|
||||||
import org.solovyev.common.msg.MessageType;
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.List;
|
import java.util.Locale;
|
||||||
import java.util.Locale;
|
|
||||||
|
/**
|
||||||
/**
|
* User: serso
|
||||||
* User: serso
|
* Date: 12/8/11
|
||||||
* Date: 12/8/11
|
* Time: 1:27 AM
|
||||||
* Time: 1:27 AM
|
*/
|
||||||
*/
|
public class CalculatorEvalException extends SersoException implements Message {
|
||||||
public class CalculatorEvalException extends SersoException implements Message {
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
private final Message message;
|
||||||
private final Message message;
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
private final String expression;
|
||||||
private final String expression;
|
|
||||||
|
public CalculatorEvalException(@NotNull Message message, @NotNull Throwable cause, String expression) {
|
||||||
public CalculatorEvalException(@NotNull Message message, @NotNull Throwable cause, String expression) {
|
super(cause);
|
||||||
super(cause);
|
this.message = message;
|
||||||
this.message = message;
|
this.expression = expression;
|
||||||
this.expression = expression;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
public String getExpression() {
|
||||||
public String getExpression() {
|
return expression;
|
||||||
return expression;
|
}
|
||||||
}
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
@Override
|
||||||
@Override
|
public String getMessageCode() {
|
||||||
public String getMessageCode() {
|
return this.message.getMessageCode();
|
||||||
return this.message.getMessageCode();
|
}
|
||||||
}
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
@Override
|
||||||
@Override
|
public List<Object> getParameters() {
|
||||||
public List<Object> getParameters() {
|
return this.message.getParameters();
|
||||||
return this.message.getParameters();
|
}
|
||||||
}
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
@Override
|
||||||
@Override
|
public MessageType getMessageType() {
|
||||||
public MessageType getMessageType() {
|
return this.message.getMessageType();
|
||||||
return this.message.getMessageType();
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
@Override
|
@NotNull
|
||||||
@NotNull
|
public String getLocalizedMessage() {
|
||||||
public String getLocalizedMessage() {
|
return this.message.getLocalizedMessage(Locale.getDefault());
|
||||||
return this.message.getLocalizedMessage(Locale.getDefault());
|
}
|
||||||
}
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
@Override
|
||||||
@Override
|
public String getLocalizedMessage(@NotNull Locale locale) {
|
||||||
public String getLocalizedMessage(@NotNull Locale locale) {
|
return this.message.getLocalizedMessage(locale);
|
||||||
return this.message.getLocalizedMessage(locale);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 16:39
|
||||||
|
*/
|
||||||
|
public interface CalculatorEventContainer {
|
||||||
|
|
||||||
|
void addCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener);
|
||||||
|
|
||||||
|
void removeCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener);
|
||||||
|
|
||||||
|
void fireCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data);
|
||||||
|
|
||||||
|
void fireCalculatorEvents(@NotNull List<CalculatorEvent> calculatorEvents);
|
||||||
|
|
||||||
|
public static class CalculatorEvent {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private CalculatorEventData calculatorEventData;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private CalculatorEventType calculatorEventType;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Object data;
|
||||||
|
|
||||||
|
public CalculatorEvent(@NotNull CalculatorEventData calculatorEventData,
|
||||||
|
@NotNull CalculatorEventType calculatorEventType,
|
||||||
|
@Nullable Object data) {
|
||||||
|
this.calculatorEventData = calculatorEventData;
|
||||||
|
this.calculatorEventType = calculatorEventType;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public CalculatorEventData getCalculatorEventData() {
|
||||||
|
return calculatorEventData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public CalculatorEventType getCalculatorEventType() {
|
||||||
|
return calculatorEventType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Object getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 16:51
|
||||||
|
*/
|
||||||
|
public interface CalculatorEventData extends CalculatorEventDataId {
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 18:18
|
||||||
|
*/
|
||||||
|
public interface CalculatorEventDataId {
|
||||||
|
|
||||||
|
// the higher id => the later event
|
||||||
|
long getEventId();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
Long getCalculationId();
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 18:18
|
||||||
|
*/
|
||||||
|
public class CalculatorEventDataIdImpl implements CalculatorEventDataId {
|
||||||
|
|
||||||
|
private final long eventId;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final Long calculationId;
|
||||||
|
|
||||||
|
private CalculatorEventDataIdImpl(long id,
|
||||||
|
@Nullable Long calculationId) {
|
||||||
|
this.eventId = id;
|
||||||
|
this.calculationId = calculationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static CalculatorEventDataId newInstance(long id,
|
||||||
|
@Nullable Long calculationId) {
|
||||||
|
return new CalculatorEventDataIdImpl(id, calculationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getEventId() {
|
||||||
|
return this.eventId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Long getCalculationId() {
|
||||||
|
return this.calculationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof CalculatorEventDataIdImpl)) return false;
|
||||||
|
|
||||||
|
CalculatorEventDataIdImpl that = (CalculatorEventDataIdImpl) o;
|
||||||
|
|
||||||
|
if (eventId != that.eventId) return false;
|
||||||
|
if (calculationId != null ? !calculationId.equals(that.calculationId) : that.calculationId != null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = (int) (eventId ^ (eventId >>> 32));
|
||||||
|
result = 31 * result + (calculationId != null ? calculationId.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 16:54
|
||||||
|
*/
|
||||||
|
class CalculatorEventDataImpl implements CalculatorEventData {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private CalculatorEventDataId calculatorEventDataId;
|
||||||
|
|
||||||
|
CalculatorEventDataImpl(@NotNull CalculatorEventDataId calculatorEventDataId) {
|
||||||
|
this.calculatorEventDataId = calculatorEventDataId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getEventId() {
|
||||||
|
return calculatorEventDataId.getEventId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Long getCalculationId() {
|
||||||
|
return calculatorEventDataId.getCalculationId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof CalculatorEventDataImpl)) return false;
|
||||||
|
|
||||||
|
CalculatorEventDataImpl that = (CalculatorEventDataImpl) o;
|
||||||
|
|
||||||
|
if (!calculatorEventDataId.equals(that.calculatorEventDataId)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return calculatorEventDataId.hashCode();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.EventListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 16:39
|
||||||
|
*/
|
||||||
|
public interface CalculatorEventListener extends EventListener {
|
||||||
|
|
||||||
|
void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 16:40
|
||||||
|
*/
|
||||||
|
public enum CalculatorEventType {
|
||||||
|
}
|
@ -0,0 +1,168 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import jscl.AbstractJsclArithmeticException;
|
||||||
|
import jscl.NumeralBaseException;
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import jscl.text.ParseInterruptedException;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
|
import org.solovyev.common.msg.MessageRegistry;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 16:42
|
||||||
|
*/
|
||||||
|
public class CalculatorImpl implements Calculator {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final CalculatorEventContainer calculatorEventContainer = new ListCalculatorEventContainer();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static final Calculator instance = new CalculatorImpl();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final AtomicLong counter = new AtomicLong(0);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Object lock = new Object();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Executor threadPoolExecutor = Executors.newFixedThreadPool(10);
|
||||||
|
|
||||||
|
private CalculatorImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static Calculator getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private CalculatorEventDataId nextCalculatorEventDataId() {
|
||||||
|
long eventId = counter.incrementAndGet();
|
||||||
|
return CalculatorEventDataIdImpl.newInstance(eventId, eventId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* CALCULATION
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void evaluate(@NotNull JsclOperation operation,
|
||||||
|
@NotNull String expression) {
|
||||||
|
evaluate(operation, expression, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void evaluate(@NotNull final JsclOperation operation,
|
||||||
|
@NotNull final String expression,
|
||||||
|
@Nullable final MessageRegistry mr) {
|
||||||
|
|
||||||
|
final CalculatorEventDataId eventDataId = nextCalculatorEventDataId();
|
||||||
|
|
||||||
|
threadPoolExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
CalculatorImpl.this.evaluate(eventDataId, operation, expression, mr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void evaluate(@NotNull CalculatorEventDataId eventDataId,
|
||||||
|
@NotNull JsclOperation operation,
|
||||||
|
@NotNull String expression,
|
||||||
|
@Nullable MessageRegistry mr) {
|
||||||
|
synchronized (lock) {
|
||||||
|
PreparedExpression preparedExpression = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
preparedExpression = preprocessor.process(expression);
|
||||||
|
|
||||||
|
final String jsclExpression = preparedExpression.toString();
|
||||||
|
try {
|
||||||
|
|
||||||
|
final Generic genericResult = operation.evaluateGeneric(jsclExpression);
|
||||||
|
|
||||||
|
// NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!)
|
||||||
|
genericResult.toString();
|
||||||
|
|
||||||
|
//return new Result(operation.getFromProcessor().process(genericResult), operation, genericResult);
|
||||||
|
} catch (AbstractJsclArithmeticException e) {
|
||||||
|
handleException(eventDataId, operation, expression, mr, preparedExpression, null, new CalculatorEvalException(e, e, jsclExpression));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
//final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_1, MessageType.error, CalculatorApplication.getInstance(), e.getMessage());
|
||||||
|
handleException(operation, expression, mr, preparedExpression, new CalculatorParseException(jsclExpression, androidMessage));
|
||||||
|
} catch (StackOverflowError e) {
|
||||||
|
//final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_2, MessageType.error, CalculatorApplication.getInstance());
|
||||||
|
handleException(eventDataId, operation, expression, mr, preparedExpression, new CalculatorParseException(e), null);
|
||||||
|
} catch (jscl.text.ParseException e) {
|
||||||
|
//System.out.println(e.getMessage());
|
||||||
|
handleException(eventDataId, operation, expression, mr, preparedExpression, new CalculatorParseException(e), null);
|
||||||
|
} catch (ParseInterruptedException e) {
|
||||||
|
// do nothing - we ourselves interrupt the calculations
|
||||||
|
} catch (CalculatorParseException e) {
|
||||||
|
handleException(eventDataId, operation, expression, mr, preparedExpression, e, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleException(@NotNull CalculatorEventDataId eventDataId,
|
||||||
|
@NotNull JsclOperation operation,
|
||||||
|
@NotNull String expression,
|
||||||
|
@Nullable MessageRegistry mr,
|
||||||
|
@Nullable PreparedExpression preparedExpression,
|
||||||
|
@Nullable CalculatorParseException parseException,
|
||||||
|
@Nullable CalculatorEvalException evalException) {
|
||||||
|
if (operation == JsclOperation.numeric && (preparedExpression != null && preparedExpression.isExistsUndefinedVar() || (evalException != null && evalException.getCause() instanceof NumeralBaseException))) {
|
||||||
|
evaluate(eventDataId, JsclOperation.simplify, expression, mr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parseException != null) {
|
||||||
|
throw parseException;
|
||||||
|
} else {
|
||||||
|
throw 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);
|
||||||
|
}
|
||||||
|
}
|
@ -17,7 +17,7 @@ import org.solovyev.android.calculator.jscl.JsclOperation;
|
|||||||
* Date: 12/17/11
|
* Date: 12/17/11
|
||||||
* Time: 9:45 PM
|
* Time: 9:45 PM
|
||||||
*/
|
*/
|
||||||
public interface ICalculatorDisplay extends Editor{
|
public interface JCalculatorDisplay extends Editor{
|
||||||
|
|
||||||
boolean isValid();
|
boolean isValid();
|
||||||
|
|
@ -0,0 +1,50 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.common.utils.ListListenersContainer;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 16:42
|
||||||
|
*/
|
||||||
|
public class ListCalculatorEventContainer implements CalculatorEventContainer {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static final String TAG = "CalculatorEventData";
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final ListListenersContainer<CalculatorEventListener> listeners = new ListListenersContainer<CalculatorEventListener>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) {
|
||||||
|
listeners.addListener(calculatorEventListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) {
|
||||||
|
listeners.removeListener(calculatorEventListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||||
|
fireCalculatorEvents(Arrays.asList(new CalculatorEvent(calculatorEventData, calculatorEventType, data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireCalculatorEvents(@NotNull List<CalculatorEvent> calculatorEvents) {
|
||||||
|
final List<CalculatorEventListener> listeners = this.listeners.getListeners();
|
||||||
|
|
||||||
|
for (CalculatorEvent e : calculatorEvents) {
|
||||||
|
Log.d(TAG, "Event: " + e.getCalculatorEventType() + " with data: " + e.getData());
|
||||||
|
for (CalculatorEventListener listener : listeners) {
|
||||||
|
listener.onCalculatorEvent(e.getCalculatorEventData(), e.getCalculatorEventType(), e.getData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,55 +1,55 @@
|
|||||||
/*
|
/*
|
||||||
* 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
|
||||||
* or visit http://se.solovyev.org
|
* or visit http://se.solovyev.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import jscl.MathEngine;
|
import jscl.MathEngine;
|
||||||
import jscl.NumeralBase;
|
import jscl.NumeralBase;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.calculator.math.MathType;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 12/15/11
|
* Date: 12/15/11
|
||||||
* Time: 8:33 PM
|
* Time: 8:33 PM
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class LiteNumberBuilder extends AbstractNumberBuilder {
|
public class LiteNumberBuilder extends AbstractNumberBuilder {
|
||||||
|
|
||||||
public LiteNumberBuilder(@NotNull MathEngine engine) {
|
public LiteNumberBuilder(@NotNull MathEngine engine) {
|
||||||
super(engine);
|
super(engine);
|
||||||
this.nb = engine.getNumeralBase();
|
this.nb = engine.getNumeralBase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(@NotNull MathType.Result mathTypeResult) {
|
public void process(@NotNull MathType.Result mathTypeResult) {
|
||||||
if (canContinue(mathTypeResult)) {
|
if (canContinue(mathTypeResult)) {
|
||||||
// let's continue building number
|
// let's continue building number
|
||||||
if (numberBuilder == null) {
|
if (numberBuilder == null) {
|
||||||
// if new number => create new builder
|
// if new number => create new builder
|
||||||
numberBuilder = new StringBuilder();
|
numberBuilder = new StringBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mathTypeResult.getMathType() != MathType.numeral_base) {
|
if (mathTypeResult.getMathType() != MathType.numeral_base) {
|
||||||
// just add matching string
|
// just add matching string
|
||||||
numberBuilder.append(mathTypeResult.getMatch());
|
numberBuilder.append(mathTypeResult.getMatch());
|
||||||
} else {
|
} else {
|
||||||
// set explicitly numeral base (do not include it into number)
|
// set explicitly numeral base (do not include it into number)
|
||||||
nb = NumeralBase.getByPrefix(mathTypeResult.getMatch());
|
nb = NumeralBase.getByPrefix(mathTypeResult.getMatch());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// process current number (and go to the next one)
|
// process current number (and go to the next one)
|
||||||
if (numberBuilder != null) {
|
if (numberBuilder != null) {
|
||||||
numberBuilder = null;
|
numberBuilder = null;
|
||||||
|
|
||||||
// must set default numeral base (exit numeral base mode)
|
// must set default numeral base (exit numeral base mode)
|
||||||
nb = engine.getNumeralBase();
|
nb = engine.getNumeralBase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,202 +1,203 @@
|
|||||||
/*
|
/*
|
||||||
* 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
|
||||||
* or visit http://se.solovyev.org
|
* or visit http://se.solovyev.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import jscl.MathContext;
|
import jscl.MathContext;
|
||||||
import jscl.MathEngine;
|
import jscl.MathEngine;
|
||||||
import jscl.NumeralBase;
|
import jscl.NumeralBase;
|
||||||
import jscl.math.numeric.Real;
|
import jscl.math.numeric.Real;
|
||||||
import jscl.text.*;
|
import jscl.text.*;
|
||||||
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.math.MathType;
|
import org.solovyev.android.calculator.AbstractNumberBuilder;
|
||||||
import org.solovyev.common.MutableObject;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
|
import org.solovyev.common.MutableObject;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
/**
|
|
||||||
* User: serso
|
/**
|
||||||
* Date: 10/23/11
|
* User: serso
|
||||||
* Time: 2:57 PM
|
* Date: 10/23/11
|
||||||
*/
|
* Time: 2:57 PM
|
||||||
public class NumberBuilder extends AbstractNumberBuilder {
|
*/
|
||||||
|
public class NumberBuilder extends AbstractNumberBuilder {
|
||||||
public NumberBuilder(@NotNull MathEngine engine) {
|
|
||||||
super(engine);
|
public NumberBuilder(@NotNull MathEngine engine) {
|
||||||
}
|
super(engine);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Method replaces number in text according to some rules (e.g. formatting)
|
/**
|
||||||
*
|
* Method replaces number in text according to some rules (e.g. formatting)
|
||||||
* @param text text where number can be replaced
|
*
|
||||||
* @param mathTypeResult math type result of current token
|
* @param text text where number can be replaced
|
||||||
* @param offset offset between new number length and old number length (newNumberLength - oldNumberLength)
|
* @param mathTypeResult math type result of current token
|
||||||
*
|
* @param offset offset between new number length and old number length (newNumberLength - oldNumberLength)
|
||||||
*
|
*
|
||||||
* @return new math type result (as one can be changed due to substituting of number with constant)
|
*
|
||||||
*/
|
* @return new math type result (as one can be changed due to substituting of number with constant)
|
||||||
@NotNull
|
*/
|
||||||
public MathType.Result process(@NotNull StringBuilder text, @NotNull MathType.Result mathTypeResult, @Nullable MutableObject<Integer> offset) {
|
@NotNull
|
||||||
final MathType.Result possibleResult;
|
public MathType.Result process(@NotNull StringBuilder text, @NotNull MathType.Result mathTypeResult, @Nullable MutableObject<Integer> offset) {
|
||||||
if (canContinue(mathTypeResult)) {
|
final MathType.Result possibleResult;
|
||||||
// let's continue building number
|
if (canContinue(mathTypeResult)) {
|
||||||
if (numberBuilder == null) {
|
// let's continue building number
|
||||||
// if new number => create new builder
|
if (numberBuilder == null) {
|
||||||
numberBuilder = new StringBuilder();
|
// if new number => create new builder
|
||||||
}
|
numberBuilder = new StringBuilder();
|
||||||
|
}
|
||||||
if (mathTypeResult.getMathType() != MathType.numeral_base) {
|
|
||||||
// just add matching string
|
if (mathTypeResult.getMathType() != MathType.numeral_base) {
|
||||||
numberBuilder.append(mathTypeResult.getMatch());
|
// just add matching string
|
||||||
} else {
|
numberBuilder.append(mathTypeResult.getMatch());
|
||||||
// set explicitly numeral base (do not include it into number)
|
} else {
|
||||||
nb = NumeralBase.getByPrefix(mathTypeResult.getMatch());
|
// set explicitly numeral base (do not include it into number)
|
||||||
}
|
nb = NumeralBase.getByPrefix(mathTypeResult.getMatch());
|
||||||
|
}
|
||||||
possibleResult = null;
|
|
||||||
} else {
|
possibleResult = null;
|
||||||
// process current number (and go to the next one)
|
} else {
|
||||||
possibleResult = processNumber(text, offset);
|
// process current number (and go to the next one)
|
||||||
}
|
possibleResult = processNumber(text, offset);
|
||||||
|
}
|
||||||
return possibleResult == null ? mathTypeResult : possibleResult;
|
|
||||||
}
|
return possibleResult == null ? mathTypeResult : possibleResult;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Method replaces number in text according to some rules (e.g. formatting)
|
/**
|
||||||
*
|
* Method replaces number in text according to some rules (e.g. formatting)
|
||||||
* @param text text where number can be replaced
|
*
|
||||||
* @param offset offset between new number length and old number length (newNumberLength - oldNumberLength)
|
* @param text text where number can be replaced
|
||||||
*
|
* @param offset offset between new number length and old number length (newNumberLength - oldNumberLength)
|
||||||
* @return new math type result (as one can be changed due to substituting of number with constant)
|
*
|
||||||
*/
|
* @return new math type result (as one can be changed due to substituting of number with constant)
|
||||||
@Nullable
|
*/
|
||||||
public MathType.Result processNumber(@NotNull StringBuilder text, @Nullable MutableObject<Integer> offset) {
|
@Nullable
|
||||||
// total number of trimmed chars
|
public MathType.Result processNumber(@NotNull StringBuilder text, @Nullable MutableObject<Integer> offset) {
|
||||||
int trimmedChars = 0;
|
// total number of trimmed chars
|
||||||
|
int trimmedChars = 0;
|
||||||
String number = null;
|
|
||||||
|
String number = null;
|
||||||
// save numeral base (as later it might be replaced)
|
|
||||||
final NumeralBase localNb = getNumeralBase();
|
// toXml numeral base (as later it might be replaced)
|
||||||
|
final NumeralBase localNb = getNumeralBase();
|
||||||
if (numberBuilder != null) {
|
|
||||||
try {
|
if (numberBuilder != null) {
|
||||||
number = numberBuilder.toString();
|
try {
|
||||||
|
number = numberBuilder.toString();
|
||||||
// let's get rid of unnecessary characters (grouping separators, + after E)
|
|
||||||
final List<String> tokens = new ArrayList<String>();
|
// let's get rid of unnecessary characters (grouping separators, + after E)
|
||||||
tokens.addAll(MathType.grouping_separator.getTokens());
|
final List<String> tokens = new ArrayList<String>();
|
||||||
// + after E can be omitted: 10+E = 10E (NOTE: - cannot be omitted )
|
tokens.addAll(MathType.grouping_separator.getTokens());
|
||||||
tokens.add("+");
|
// + after E can be omitted: 10+E = 10E (NOTE: - cannot be omitted )
|
||||||
for (String groupingSeparator : tokens) {
|
tokens.add("+");
|
||||||
final String trimmedNumber = number.replace(groupingSeparator, "");
|
for (String groupingSeparator : tokens) {
|
||||||
trimmedChars += number.length() - trimmedNumber.length();
|
final String trimmedNumber = number.replace(groupingSeparator, "");
|
||||||
number = trimmedNumber;
|
trimmedChars += number.length() - trimmedNumber.length();
|
||||||
}
|
number = trimmedNumber;
|
||||||
|
}
|
||||||
// check if number still valid
|
|
||||||
toDouble(number, getNumeralBase(), engine);
|
// check if number still valid
|
||||||
|
toDouble(number, getNumeralBase(), engine);
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
// number is not valid => stop
|
} catch (NumberFormatException e) {
|
||||||
number = null;
|
// number is not valid => stop
|
||||||
}
|
number = null;
|
||||||
|
}
|
||||||
numberBuilder = null;
|
|
||||||
|
numberBuilder = null;
|
||||||
// must set default numeral base (exit numeral base mode)
|
|
||||||
nb = engine.getNumeralBase();
|
// must set default numeral base (exit numeral base mode)
|
||||||
}
|
nb = engine.getNumeralBase();
|
||||||
|
}
|
||||||
return replaceNumberInText(text, number, trimmedChars, offset, localNb, engine);
|
|
||||||
}
|
return replaceNumberInText(text, number, trimmedChars, offset, localNb, engine);
|
||||||
|
}
|
||||||
@Nullable
|
|
||||||
private static MathType.Result replaceNumberInText(@NotNull StringBuilder text,
|
@Nullable
|
||||||
@Nullable String number,
|
private static MathType.Result replaceNumberInText(@NotNull StringBuilder text,
|
||||||
int trimmedChars,
|
@Nullable String number,
|
||||||
@Nullable MutableObject<Integer> offset,
|
int trimmedChars,
|
||||||
@NotNull NumeralBase nb,
|
@Nullable MutableObject<Integer> offset,
|
||||||
@NotNull final MathEngine engine) {
|
@NotNull NumeralBase nb,
|
||||||
MathType.Result result = null;
|
@NotNull final MathEngine engine) {
|
||||||
|
MathType.Result result = null;
|
||||||
if (number != null) {
|
|
||||||
// in any case remove old number from text
|
if (number != null) {
|
||||||
final int oldNumberLength = number.length() + trimmedChars;
|
// in any case remove old number from text
|
||||||
text.delete(text.length() - oldNumberLength, text.length());
|
final int oldNumberLength = number.length() + trimmedChars;
|
||||||
|
text.delete(text.length() - oldNumberLength, text.length());
|
||||||
final String newNumber = formatNumber(number, nb, engine);
|
|
||||||
if (offset != null) {
|
final String newNumber = formatNumber(number, nb, engine);
|
||||||
// register offset between old number and new number
|
if (offset != null) {
|
||||||
offset.setObject(newNumber.length() - oldNumberLength);
|
// register offset between old number and new number
|
||||||
}
|
offset.setObject(newNumber.length() - oldNumberLength);
|
||||||
text.append(newNumber);
|
}
|
||||||
}
|
text.append(newNumber);
|
||||||
|
}
|
||||||
return result;
|
|
||||||
}
|
return result;
|
||||||
|
}
|
||||||
@NotNull
|
|
||||||
private static String formatNumber(@NotNull String number, @NotNull NumeralBase nb, @NotNull MathEngine engine) {
|
@NotNull
|
||||||
String result;
|
private static String formatNumber(@NotNull String number, @NotNull NumeralBase nb, @NotNull MathEngine engine) {
|
||||||
|
String result;
|
||||||
int indexOfDot = number.indexOf('.');
|
|
||||||
|
int indexOfDot = number.indexOf('.');
|
||||||
if (indexOfDot < 0) {
|
|
||||||
int indexOfE;
|
if (indexOfDot < 0) {
|
||||||
if (nb == NumeralBase.hex) {
|
int indexOfE;
|
||||||
indexOfE = -1;
|
if (nb == NumeralBase.hex) {
|
||||||
} else {
|
indexOfE = -1;
|
||||||
indexOfE = number.indexOf(MathType.POWER_10);
|
} else {
|
||||||
}
|
indexOfE = number.indexOf(MathType.POWER_10);
|
||||||
if (indexOfE < 0) {
|
}
|
||||||
result = engine.addGroupingSeparators(nb, number);
|
if (indexOfE < 0) {
|
||||||
} else {
|
result = engine.addGroupingSeparators(nb, number);
|
||||||
final String partBeforeE;
|
} else {
|
||||||
if (indexOfE != 0) {
|
final String partBeforeE;
|
||||||
partBeforeE = engine.addGroupingSeparators(nb, number.substring(0, indexOfE));
|
if (indexOfE != 0) {
|
||||||
} else {
|
partBeforeE = engine.addGroupingSeparators(nb, number.substring(0, indexOfE));
|
||||||
partBeforeE = "";
|
} else {
|
||||||
}
|
partBeforeE = "";
|
||||||
result = partBeforeE + number.substring(indexOfE);
|
}
|
||||||
}
|
result = partBeforeE + number.substring(indexOfE);
|
||||||
} else {
|
}
|
||||||
final String integerPart;
|
} else {
|
||||||
if (indexOfDot != 0) {
|
final String integerPart;
|
||||||
integerPart = engine.addGroupingSeparators(nb, number.substring(0, indexOfDot));
|
if (indexOfDot != 0) {
|
||||||
} else {
|
integerPart = engine.addGroupingSeparators(nb, number.substring(0, indexOfDot));
|
||||||
integerPart = "";
|
} else {
|
||||||
}
|
integerPart = "";
|
||||||
result = integerPart + number.substring(indexOfDot);
|
}
|
||||||
}
|
result = integerPart + number.substring(indexOfDot);
|
||||||
|
}
|
||||||
return result;
|
|
||||||
}
|
return result;
|
||||||
|
}
|
||||||
@NotNull
|
|
||||||
private static Double toDouble(@NotNull String s, @NotNull NumeralBase nb, @NotNull final MathContext mc) throws NumberFormatException {
|
@NotNull
|
||||||
final NumeralBase defaultNb = mc.getNumeralBase();
|
private static Double toDouble(@NotNull String s, @NotNull NumeralBase nb, @NotNull final MathContext mc) throws NumberFormatException {
|
||||||
try {
|
final NumeralBase defaultNb = mc.getNumeralBase();
|
||||||
mc.setNumeralBase(nb);
|
try {
|
||||||
|
mc.setNumeralBase(nb);
|
||||||
try {
|
|
||||||
return JsclIntegerParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), mc), null).content().doubleValue();
|
try {
|
||||||
} catch (ParseException e) {
|
return JsclIntegerParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), mc), null).content().doubleValue();
|
||||||
try {
|
} catch (ParseException e) {
|
||||||
return ((Real) DoubleParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), mc), null).content()).doubleValue();
|
try {
|
||||||
} catch (ParseException e1) {
|
return ((Real) DoubleParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), mc), null).content()).doubleValue();
|
||||||
throw new NumberFormatException();
|
} catch (ParseException e1) {
|
||||||
}
|
throw new NumberFormatException();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} finally {
|
|
||||||
mc.setNumeralBase(defaultNb);
|
} finally {
|
||||||
}
|
mc.setNumeralBase(defaultNb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
@ -1,65 +1,65 @@
|
|||||||
/*
|
/*
|
||||||
* 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
|
||||||
* or visit http://se.solovyev.org
|
* or visit http://se.solovyev.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import jscl.math.function.IConstant;
|
import jscl.math.function.IConstant;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 10/18/11
|
* Date: 10/18/11
|
||||||
* Time: 10:07 PM
|
* Time: 10:07 PM
|
||||||
*/
|
*/
|
||||||
public class PreparedExpression implements CharSequence{
|
public class PreparedExpression implements CharSequence{
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private String expression;
|
private String expression;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private List<IConstant> undefinedVars;
|
private List<IConstant> undefinedVars;
|
||||||
|
|
||||||
public PreparedExpression(@NotNull String expression, @NotNull List<IConstant> undefinedVars) {
|
public PreparedExpression(@NotNull String expression, @NotNull List<IConstant> undefinedVars) {
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
this.undefinedVars = undefinedVars;
|
this.undefinedVars = undefinedVars;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public String getExpression() {
|
public String getExpression() {
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isExistsUndefinedVar() {
|
public boolean isExistsUndefinedVar() {
|
||||||
return !this.undefinedVars.isEmpty();
|
return !this.undefinedVars.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<IConstant> getUndefinedVars() {
|
public List<IConstant> getUndefinedVars() {
|
||||||
return undefinedVars;
|
return undefinedVars;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int length() {
|
public int length() {
|
||||||
return expression.length();
|
return expression.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char charAt(int i) {
|
public char charAt(int i) {
|
||||||
return expression.charAt(i);
|
return expression.charAt(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharSequence subSequence(int i, int i1) {
|
public CharSequence subSequence(int i, int i1) {
|
||||||
return expression.subSequence(i, i1);
|
return expression.subSequence(i, i1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return this.expression;
|
return this.expression;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,12 +4,13 @@
|
|||||||
* or visit http://se.solovyev.org
|
* or visit http://se.solovyev.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import jscl.math.function.IConstant;
|
import jscl.math.function.IConstant;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.calculator.CalculatorApplication;
|
import org.solovyev.android.calculator.CalculatorApplication;
|
||||||
import org.solovyev.android.calculator.CalculatorParseException;
|
import org.solovyev.android.calculator.CalculatorParseException;
|
||||||
|
import org.solovyev.android.calculator.PreparedExpression;
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
import org.solovyev.android.calculator.text.TextProcessor;
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
import org.solovyev.android.msg.AndroidMessage;
|
import org.solovyev.android.msg.AndroidMessage;
|
@ -11,7 +11,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.simpleframework.xml.Element;
|
import org.simpleframework.xml.Element;
|
||||||
import org.simpleframework.xml.Root;
|
import org.simpleframework.xml.Root;
|
||||||
import org.simpleframework.xml.Transient;
|
import org.simpleframework.xml.Transient;
|
||||||
import org.solovyev.android.calculator.ICalculatorDisplay;
|
import org.solovyev.android.calculator.JCalculatorDisplay;
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,7 +47,7 @@ public class CalculatorDisplayHistoryState implements Cloneable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static CalculatorDisplayHistoryState newInstance(@NotNull ICalculatorDisplay display) {
|
public static CalculatorDisplayHistoryState newInstance(@NotNull JCalculatorDisplay display) {
|
||||||
final CalculatorDisplayHistoryState result = new CalculatorDisplayHistoryState();
|
final CalculatorDisplayHistoryState result = new CalculatorDisplayHistoryState();
|
||||||
|
|
||||||
result.editorState = EditorHistoryState.newInstance(display);
|
result.editorState = EditorHistoryState.newInstance(display);
|
||||||
@ -59,7 +59,7 @@ public class CalculatorDisplayHistoryState implements Cloneable {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setValuesFromHistory(@NotNull ICalculatorDisplay display) {
|
public void setValuesFromHistory(@NotNull JCalculatorDisplay display) {
|
||||||
this.getEditorState().setValuesFromHistory(display);
|
this.getEditorState().setValuesFromHistory(display);
|
||||||
display.setValid(this.isValid());
|
display.setValid(this.isValid());
|
||||||
display.setErrorMessage(this.getErrorMessage());
|
display.setErrorMessage(this.getErrorMessage());
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package org.solovyev.android.calculator.history;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.common.history.HistoryHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 16:11
|
||||||
|
*/
|
||||||
|
public interface CalculatorHistory extends HistoryHelper<CalculatorHistoryState> {
|
||||||
|
|
||||||
|
void fromXml(@NotNull String xml);
|
||||||
|
|
||||||
|
String toXml();
|
||||||
|
|
||||||
|
void clearSavedHistory();
|
||||||
|
|
||||||
|
void removeSavedHistory(@NotNull CalculatorHistoryState historyState);
|
||||||
|
}
|
@ -0,0 +1,131 @@
|
|||||||
|
package org.solovyev.android.calculator.history;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.common.history.HistoryAction;
|
||||||
|
import org.solovyev.common.history.HistoryHelper;
|
||||||
|
import org.solovyev.common.history.SimpleHistoryHelper;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 16:12
|
||||||
|
*/
|
||||||
|
public class CalculatorHistoryImpl implements CalculatorHistory {
|
||||||
|
|
||||||
|
private final AtomicInteger counter = new AtomicInteger(0);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final HistoryHelper<CalculatorHistoryState> history = new SimpleHistoryHelper<CalculatorHistoryState>();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final List<CalculatorHistoryState> savedHistory = new ArrayList<CalculatorHistoryState>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return this.history.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CalculatorHistoryState getLastHistoryState() {
|
||||||
|
return this.history.getLastHistoryState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUndoAvailable() {
|
||||||
|
return history.isUndoAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) {
|
||||||
|
return history.undo(currentState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRedoAvailable() {
|
||||||
|
return history.isRedoAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) {
|
||||||
|
return history.redo(currentState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActionAvailable(@NotNull HistoryAction historyAction) {
|
||||||
|
return history.isActionAvailable(historyAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CalculatorHistoryState doAction(@NotNull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) {
|
||||||
|
return history.doAction(historyAction, currentState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addState(@Nullable CalculatorHistoryState currentState) {
|
||||||
|
history.addState(currentState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<CalculatorHistoryState> getStates() {
|
||||||
|
return history.getStates();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
this.history.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public List<CalculatorHistoryState> getSavedHistory() {
|
||||||
|
return Collections.unmodifiableList(savedHistory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState) {
|
||||||
|
if (historyState.isSaved()) {
|
||||||
|
return historyState;
|
||||||
|
} else {
|
||||||
|
final CalculatorHistoryState savedState = historyState.clone();
|
||||||
|
|
||||||
|
savedState.setId(counter.incrementAndGet());
|
||||||
|
savedState.setSaved(true);
|
||||||
|
|
||||||
|
savedHistory.add(savedState);
|
||||||
|
|
||||||
|
return savedState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromXml(@NotNull String xml) {
|
||||||
|
clearSavedHistory();
|
||||||
|
|
||||||
|
HistoryUtils.fromXml(xml, this.savedHistory);
|
||||||
|
for (CalculatorHistoryState historyState : savedHistory) {
|
||||||
|
historyState.setSaved(true);
|
||||||
|
historyState.setId(counter.incrementAndGet());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toXml() {
|
||||||
|
return HistoryUtils.toXml(this.savedHistory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearSavedHistory() {
|
||||||
|
this.savedHistory.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) {
|
||||||
|
this.savedHistory.remove(historyState);
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.simpleframework.xml.Element;
|
import org.simpleframework.xml.Element;
|
||||||
import org.simpleframework.xml.Root;
|
import org.simpleframework.xml.Root;
|
||||||
import org.solovyev.android.calculator.Editor;
|
import org.solovyev.android.calculator.Editor;
|
||||||
import org.solovyev.android.calculator.ICalculatorDisplay;
|
import org.solovyev.android.calculator.JCalculatorDisplay;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
@ -38,7 +38,7 @@ public class CalculatorHistoryState extends AbstractHistoryState {
|
|||||||
this.displayState = displayState;
|
this.displayState = displayState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CalculatorHistoryState newInstance(@NotNull Editor editor, @NotNull ICalculatorDisplay display) {
|
public static CalculatorHistoryState newInstance(@NotNull Editor editor, @NotNull JCalculatorDisplay display) {
|
||||||
final EditorHistoryState editorHistoryState = EditorHistoryState.newInstance(editor);
|
final EditorHistoryState editorHistoryState = EditorHistoryState.newInstance(editor);
|
||||||
final CalculatorDisplayHistoryState displayHistoryState = CalculatorDisplayHistoryState.newInstance(display);
|
final CalculatorDisplayHistoryState displayHistoryState = CalculatorDisplayHistoryState.newInstance(display);
|
||||||
return new CalculatorHistoryState(editorHistoryState, displayHistoryState);
|
return new CalculatorHistoryState(editorHistoryState, displayHistoryState);
|
||||||
@ -94,7 +94,7 @@ public class CalculatorHistoryState extends AbstractHistoryState {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setValuesFromHistory(@NotNull Editor editor, @NotNull ICalculatorDisplay display) {
|
public void setValuesFromHistory(@NotNull Editor editor, @NotNull JCalculatorDisplay display) {
|
||||||
this.getEditorState().setValuesFromHistory(editor);
|
this.getEditorState().setValuesFromHistory(editor);
|
||||||
this.getDisplayState().setValuesFromHistory(display);
|
this.getDisplayState().setValuesFromHistory(display);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
package org.solovyev.common.utils;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 16:43
|
||||||
|
*/
|
||||||
|
// todo serso: move to common
|
||||||
|
public class ListListenersContainer<T> {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final List<WeakReference<T>> listeners = new ArrayList<WeakReference<T>>();
|
||||||
|
|
||||||
|
public void addListener(@NotNull final T listener) {
|
||||||
|
synchronized (listeners) {
|
||||||
|
boolean contains = Iterables.any(listeners, new WeakReferencePredicate<T>(listener));
|
||||||
|
|
||||||
|
if (!contains) {
|
||||||
|
listeners.add(new WeakReference<T>(listener));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeListener(@NotNull T listener) {
|
||||||
|
synchronized (listeners) {
|
||||||
|
Iterables.removeIf(listeners, new WeakReferencePredicate<T>(listener));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public List<T> getListeners() {
|
||||||
|
final List<T> localListeners;
|
||||||
|
|
||||||
|
synchronized (listeners) {
|
||||||
|
localListeners = new ArrayList<T>(listeners.size());
|
||||||
|
|
||||||
|
// copy listeners and remove garbage collected references
|
||||||
|
for ( Iterator<WeakReference<T>> it = listeners.iterator(); it.hasNext(); ) {
|
||||||
|
final WeakReference<T> r = it.next();
|
||||||
|
final T t = r.get();
|
||||||
|
if ( t == null ) {
|
||||||
|
it.remove();
|
||||||
|
} else {
|
||||||
|
localListeners.add(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return localListeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class WeakReferencePredicate<T> implements Predicate<WeakReference<T>> {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final T t;
|
||||||
|
|
||||||
|
public WeakReferencePredicate(T t) {
|
||||||
|
this.t = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(@Nullable WeakReference<T> r) {
|
||||||
|
final T t = r != null ? r.get() : null;
|
||||||
|
return this.t.equals(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -32,7 +32,7 @@ import org.solovyev.android.AndroidUtils;
|
|||||||
import org.solovyev.android.FontSizeAdjuster;
|
import org.solovyev.android.FontSizeAdjuster;
|
||||||
import org.solovyev.android.LocalBinder;
|
import org.solovyev.android.LocalBinder;
|
||||||
import org.solovyev.android.calculator.about.CalculatorReleaseNotesActivity;
|
import org.solovyev.android.calculator.about.CalculatorReleaseNotesActivity;
|
||||||
import org.solovyev.android.calculator.history.CalculatorHistory;
|
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.model.CalculatorEngine;
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
import org.solovyev.android.calculator.view.AngleUnitsButton;
|
import org.solovyev.android.calculator.view.AngleUnitsButton;
|
||||||
@ -136,7 +136,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
|||||||
|
|
||||||
vibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE);
|
vibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE);
|
||||||
|
|
||||||
CalculatorHistory.instance.load(this, preferences);
|
AndroidCalculatorHistoryImpl.instance.load(this, preferences);
|
||||||
calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance);
|
calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance);
|
||||||
|
|
||||||
dpclRegister.clear();
|
dpclRegister.clear();
|
||||||
|
@ -19,7 +19,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
import org.solovyev.android.calculator.model.CalculatorEngine;
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
import org.solovyev.android.calculator.text.TextProcessor;
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
import org.solovyev.android.calculator.model.ToJsclTextProcessor;
|
import org.solovyev.android.calculator.ToJsclTextProcessor;
|
||||||
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
|
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
|
||||||
import org.solovyev.android.calculator.view.TextHighlighter;
|
import org.solovyev.android.calculator.view.TextHighlighter;
|
||||||
import org.solovyev.android.calculator.view.UnitConverterViewBuilder;
|
import org.solovyev.android.calculator.view.UnitConverterViewBuilder;
|
||||||
@ -37,7 +37,7 @@ import java.util.Set;
|
|||||||
* Date: 9/17/11
|
* Date: 9/17/11
|
||||||
* Time: 10:58 PM
|
* Time: 10:58 PM
|
||||||
*/
|
*/
|
||||||
public class CalculatorDisplay extends AutoResizeTextView implements ICalculatorDisplay{
|
public class CalculatorDisplay extends AutoResizeTextView implements JCalculatorDisplay {
|
||||||
|
|
||||||
private static enum ConversionMenuItem implements AMenuItem<CalculatorDisplay> {
|
private static enum ConversionMenuItem implements AMenuItem<CalculatorDisplay> {
|
||||||
convert_to_bin(NumeralBase.bin),
|
convert_to_bin(NumeralBase.bin),
|
||||||
|
@ -20,13 +20,12 @@ 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.CalculatorHistory;
|
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.calculator.model.CalculatorEvalException;
|
|
||||||
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;
|
||||||
@ -70,7 +69,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
this.display = (CalculatorDisplay) activity.findViewById(R.id.calculatorDisplay);
|
this.display = (CalculatorDisplay) activity.findViewById(R.id.calculatorDisplay);
|
||||||
this.display.setOnClickListener(new CalculatorDisplayOnClickListener(activity));
|
this.display.setOnClickListener(new CalculatorDisplayOnClickListener(activity));
|
||||||
|
|
||||||
final CalculatorHistoryState lastState = CalculatorHistory.instance.getLastHistoryState();
|
final CalculatorHistoryState lastState = AndroidCalculatorHistoryImpl.instance.getLastHistoryState();
|
||||||
if (lastState == null) {
|
if (lastState == null) {
|
||||||
saveHistoryState();
|
saveHistoryState();
|
||||||
} else {
|
} else {
|
||||||
@ -110,7 +109,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void saveHistoryState() {
|
private void saveHistoryState() {
|
||||||
CalculatorHistory.instance.addState(getCurrentHistoryState());
|
AndroidCalculatorHistoryImpl.instance.addState(getCurrentHistoryState());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCursorOnStart() {
|
public void setCursorOnStart() {
|
||||||
@ -196,14 +195,14 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
|
|
||||||
if (delayEvaluate) {
|
if (delayEvaluate) {
|
||||||
if (historyState == null) {
|
if (historyState == null) {
|
||||||
CalculatorHistory.instance.addState(localHistoryState);
|
AndroidCalculatorHistoryImpl.instance.addState(localHistoryState);
|
||||||
}
|
}
|
||||||
// todo serso: this is not correct - operation is processing still in the same thread
|
// todo serso: this is not correct - operation is processing still in the same thread
|
||||||
new Handler().postDelayed(pendingOperation.getObject(), EVAL_DELAY_MILLIS);
|
new Handler().postDelayed(pendingOperation.getObject(), EVAL_DELAY_MILLIS);
|
||||||
} else {
|
} else {
|
||||||
pendingOperation.getObject().run();
|
pendingOperation.getObject().run();
|
||||||
if (historyState == null) {
|
if (historyState == null) {
|
||||||
CalculatorHistory.instance.addState(localHistoryState);
|
AndroidCalculatorHistoryImpl.instance.addState(localHistoryState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,9 +329,9 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doHistoryAction(@NotNull HistoryAction historyAction) {
|
public void doHistoryAction(@NotNull HistoryAction historyAction) {
|
||||||
synchronized (CalculatorHistory.instance) {
|
synchronized (AndroidCalculatorHistoryImpl.instance) {
|
||||||
if (CalculatorHistory.instance.isActionAvailable(historyAction)) {
|
if (AndroidCalculatorHistoryImpl.instance.isActionAvailable(historyAction)) {
|
||||||
final CalculatorHistoryState newState = CalculatorHistory.instance.doAction(historyAction, getCurrentHistoryState());
|
final CalculatorHistoryState newState = AndroidCalculatorHistoryImpl.instance.doAction(historyAction, getCurrentHistoryState());
|
||||||
if (newState != null) {
|
if (newState != null) {
|
||||||
setCurrentHistoryState(newState);
|
setCurrentHistoryState(newState);
|
||||||
}
|
}
|
||||||
@ -342,7 +341,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) {
|
public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) {
|
||||||
synchronized (CalculatorHistory.instance) {
|
synchronized (AndroidCalculatorHistoryImpl.instance) {
|
||||||
Log.d(this.getClass().getName(), "Saved history found: " + editorHistoryState);
|
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);
|
||||||
@ -362,7 +361,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public CalculatorHistoryState getCurrentHistoryState() {
|
public CalculatorHistoryState getCurrentHistoryState() {
|
||||||
synchronized (CalculatorHistory.instance) {
|
synchronized (AndroidCalculatorHistoryImpl.instance) {
|
||||||
return CalculatorHistoryState.newInstance(new TextViewEditorAdapter(this.editor), this.display);
|
return CalculatorHistoryState.newInstance(new TextViewEditorAdapter(this.editor), this.display);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,263 +1,263 @@
|
|||||||
/*
|
/*
|
||||||
* 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
|
||||||
* or visit http://se.solovyev.org
|
* or visit http://se.solovyev.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator.history;
|
package org.solovyev.android.calculator.history;
|
||||||
|
|
||||||
import android.app.ListActivity;
|
import android.app.ListActivity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import com.google.ads.AdView;
|
import com.google.ads.AdView;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.ads.AdsController;
|
import org.solovyev.android.ads.AdsController;
|
||||||
import org.solovyev.android.calculator.CalculatorModel;
|
import org.solovyev.android.calculator.CalculatorModel;
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
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.collections.CollectionsUtils;
|
import org.solovyev.common.collections.CollectionsUtils;
|
||||||
import org.solovyev.common.equals.Equalizer;
|
import org.solovyev.common.equals.Equalizer;
|
||||||
import org.solovyev.common.filter.Filter;
|
import org.solovyev.common.filter.Filter;
|
||||||
import org.solovyev.common.filter.FilterRule;
|
import org.solovyev.common.filter.FilterRule;
|
||||||
import org.solovyev.common.filter.FilterRulesChain;
|
import org.solovyev.common.filter.FilterRulesChain;
|
||||||
import org.solovyev.common.text.StringUtils;
|
import org.solovyev.common.text.StringUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 10/15/11
|
* Date: 10/15/11
|
||||||
* Time: 1:13 PM
|
* Time: 1:13 PM
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractHistoryActivity extends ListActivity {
|
public abstract class AbstractHistoryActivity extends ListActivity {
|
||||||
|
|
||||||
public static final Comparator<CalculatorHistoryState> COMPARATOR = new Comparator<CalculatorHistoryState>() {
|
public static final Comparator<CalculatorHistoryState> COMPARATOR = new Comparator<CalculatorHistoryState>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(CalculatorHistoryState state1, CalculatorHistoryState state2) {
|
public int compare(CalculatorHistoryState state1, CalculatorHistoryState state2) {
|
||||||
if (state1.isSaved() == state2.isSaved()) {
|
if (state1.isSaved() == state2.isSaved()) {
|
||||||
long l = state2.getTime() - state1.getTime();
|
long l = state2.getTime() - state1.getTime();
|
||||||
return l > 0l ? 1 : (l < 0l ? -1 : 0);
|
return l > 0l ? 1 : (l < 0l ? -1 : 0);
|
||||||
} else if (state1.isSaved()) {
|
} else if (state1.isSaved()) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (state2.isSaved()) {
|
} else if (state2.isSaved()) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private ArrayAdapter<CalculatorHistoryState> adapter;
|
private ArrayAdapter<CalculatorHistoryState> adapter;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private AdView adView;
|
private AdView adView;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
setContentView(R.layout.history_activity);
|
setContentView(R.layout.history_activity);
|
||||||
|
|
||||||
adView = AdsController.getInstance().inflateAd(this);
|
adView = AdsController.getInstance().inflateAd(this);
|
||||||
|
|
||||||
adapter = new HistoryArrayAdapter(this, getLayoutId(), R.id.history_item, new ArrayList<CalculatorHistoryState>());
|
adapter = new HistoryArrayAdapter(this, getLayoutId(), R.id.history_item, new ArrayList<CalculatorHistoryState>());
|
||||||
setListAdapter(adapter);
|
setListAdapter(adapter);
|
||||||
|
|
||||||
final ListView lv = getListView();
|
final ListView lv = getListView();
|
||||||
lv.setTextFilterEnabled(true);
|
lv.setTextFilterEnabled(true);
|
||||||
|
|
||||||
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||||
public void onItemClick(final AdapterView<?> parent,
|
public void onItemClick(final AdapterView<?> parent,
|
||||||
final View view,
|
final View view,
|
||||||
final int position,
|
final int position,
|
||||||
final long id) {
|
final long id) {
|
||||||
|
|
||||||
useHistoryItem((CalculatorHistoryState) parent.getItemAtPosition(position), AbstractHistoryActivity.this);
|
useHistoryItem((CalculatorHistoryState) parent.getItemAtPosition(position), AbstractHistoryActivity.this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
|
lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
|
public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
|
||||||
final CalculatorHistoryState historyState = (CalculatorHistoryState) parent.getItemAtPosition(position);
|
final CalculatorHistoryState historyState = (CalculatorHistoryState) parent.getItemAtPosition(position);
|
||||||
|
|
||||||
final Context context = AbstractHistoryActivity.this;
|
final Context context = AbstractHistoryActivity.this;
|
||||||
|
|
||||||
final HistoryItemMenuData data = new HistoryItemMenuData(historyState, adapter);
|
final HistoryItemMenuData data = new HistoryItemMenuData(historyState, adapter);
|
||||||
|
|
||||||
final List<HistoryItemMenuItem> menuItems = CollectionsUtils.asList(HistoryItemMenuItem.values());
|
final List<HistoryItemMenuItem> menuItems = CollectionsUtils.asList(HistoryItemMenuItem.values());
|
||||||
|
|
||||||
if (historyState.isSaved()) {
|
if (historyState.isSaved()) {
|
||||||
menuItems.remove(HistoryItemMenuItem.save);
|
menuItems.remove(HistoryItemMenuItem.save);
|
||||||
} else {
|
} else {
|
||||||
if (isAlreadySaved(historyState)) {
|
if (isAlreadySaved(historyState)) {
|
||||||
menuItems.remove(HistoryItemMenuItem.save);
|
menuItems.remove(HistoryItemMenuItem.save);
|
||||||
}
|
}
|
||||||
menuItems.remove(HistoryItemMenuItem.remove);
|
menuItems.remove(HistoryItemMenuItem.remove);
|
||||||
menuItems.remove(HistoryItemMenuItem.edit);
|
menuItems.remove(HistoryItemMenuItem.edit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (historyState.getDisplayState().isValid() && StringUtils.isEmpty(historyState.getDisplayState().getEditorState().getText())) {
|
if (historyState.getDisplayState().isValid() && StringUtils.isEmpty(historyState.getDisplayState().getEditorState().getText())) {
|
||||||
menuItems.remove(HistoryItemMenuItem.copy_result);
|
menuItems.remove(HistoryItemMenuItem.copy_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
final AMenuBuilder<HistoryItemMenuItem, HistoryItemMenuData> menuBuilder = AMenuBuilder.newInstance(context, MenuImpl.newInstance(menuItems));
|
final AMenuBuilder<HistoryItemMenuItem, HistoryItemMenuData> menuBuilder = AMenuBuilder.newInstance(context, MenuImpl.newInstance(menuItems));
|
||||||
menuBuilder.create(data).show();
|
menuBuilder.create(data).show();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
if ( this.adView != null ) {
|
if ( this.adView != null ) {
|
||||||
this.adView.destroy();
|
this.adView.destroy();
|
||||||
}
|
}
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract int getLayoutId();
|
protected abstract int getLayoutId();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
final List<CalculatorHistoryState> historyList = getHistoryList();
|
final List<CalculatorHistoryState> historyList = getHistoryList();
|
||||||
try {
|
try {
|
||||||
this.adapter.setNotifyOnChange(false);
|
this.adapter.setNotifyOnChange(false);
|
||||||
this.adapter.clear();
|
this.adapter.clear();
|
||||||
for (CalculatorHistoryState historyState : historyList) {
|
for (CalculatorHistoryState historyState : historyList) {
|
||||||
this.adapter.add(historyState);
|
this.adapter.add(historyState);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
this.adapter.setNotifyOnChange(true);
|
this.adapter.setNotifyOnChange(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.adapter.notifyDataSetChanged();
|
this.adapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isAlreadySaved(@NotNull CalculatorHistoryState historyState) {
|
public static boolean isAlreadySaved(@NotNull CalculatorHistoryState historyState) {
|
||||||
assert !historyState.isSaved();
|
assert !historyState.isSaved();
|
||||||
|
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
try {
|
try {
|
||||||
historyState.setSaved(true);
|
historyState.setSaved(true);
|
||||||
if ( CollectionsUtils.contains(historyState, CalculatorHistory.instance.getSavedHistory(), new Equalizer<CalculatorHistoryState>() {
|
if ( CollectionsUtils.contains(historyState, AndroidCalculatorHistoryImpl.instance.getSavedHistory(), new Equalizer<CalculatorHistoryState>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable CalculatorHistoryState first, @Nullable CalculatorHistoryState second) {
|
public boolean equals(@Nullable CalculatorHistoryState first, @Nullable CalculatorHistoryState second) {
|
||||||
return first != null && second != null &&
|
return first != null && second != null &&
|
||||||
first.getTime() == second.getTime() &&
|
first.getTime() == second.getTime() &&
|
||||||
first.getDisplayState().equals(second.getDisplayState()) &&
|
first.getDisplayState().equals(second.getDisplayState()) &&
|
||||||
first.getEditorState().equals(second.getEditorState());
|
first.getEditorState().equals(second.getEditorState());
|
||||||
}
|
}
|
||||||
}) ) {
|
}) ) {
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
historyState.setSaved(false);
|
historyState.setSaved(false);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void useHistoryItem(@NotNull final CalculatorHistoryState historyState, @NotNull AbstractHistoryActivity activity) {
|
public static void useHistoryItem(@NotNull final CalculatorHistoryState historyState, @NotNull AbstractHistoryActivity activity) {
|
||||||
|
|
||||||
// before evaluating history item - clear display (in order to get Error message in display if evaluation fail)
|
// before evaluating history item - clear display (in order to get Error message in display if evaluation fail)
|
||||||
CalculatorModel.instance.getDisplay().setText("");
|
CalculatorModel.instance.getDisplay().setText("");
|
||||||
CalculatorModel.instance.doTextOperation(new CalculatorModel.TextOperation() {
|
CalculatorModel.instance.doTextOperation(new CalculatorModel.TextOperation() {
|
||||||
@Override
|
@Override
|
||||||
public void doOperation(@NotNull EditText editor) {
|
public void doOperation(@NotNull EditText editor) {
|
||||||
final EditorHistoryState editorState = historyState.getEditorState();
|
final EditorHistoryState editorState = historyState.getEditorState();
|
||||||
editor.setText(editorState.getText());
|
editor.setText(editorState.getText());
|
||||||
editor.setSelection(editorState.getCursorPosition());
|
editor.setSelection(editorState.getCursorPosition());
|
||||||
}
|
}
|
||||||
}, false, historyState.getDisplayState().getJsclOperation(), true);
|
}, false, historyState.getDisplayState().getJsclOperation(), true);
|
||||||
|
|
||||||
CalculatorModel.instance.setCursorOnEnd();
|
CalculatorModel.instance.setCursorOnEnd();
|
||||||
|
|
||||||
activity.finish();
|
activity.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private List<CalculatorHistoryState> getHistoryList() {
|
private List<CalculatorHistoryState> getHistoryList() {
|
||||||
final List<CalculatorHistoryState> calculatorHistoryStates = getHistoryItems();
|
final List<CalculatorHistoryState> calculatorHistoryStates = getHistoryItems();
|
||||||
|
|
||||||
Collections.sort(calculatorHistoryStates, COMPARATOR);
|
Collections.sort(calculatorHistoryStates, COMPARATOR);
|
||||||
|
|
||||||
final FilterRulesChain<CalculatorHistoryState> filterRulesChain = new FilterRulesChain<CalculatorHistoryState>();
|
final FilterRulesChain<CalculatorHistoryState> filterRulesChain = new FilterRulesChain<CalculatorHistoryState>();
|
||||||
filterRulesChain.addFilterRule(new FilterRule<CalculatorHistoryState>() {
|
filterRulesChain.addFilterRule(new FilterRule<CalculatorHistoryState>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean isFiltered(CalculatorHistoryState object) {
|
public boolean isFiltered(CalculatorHistoryState object) {
|
||||||
return object == null || StringUtils.isEmpty(object.getEditorState().getText());
|
return object == null || StringUtils.isEmpty(object.getEditorState().getText());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
new Filter<CalculatorHistoryState>(filterRulesChain).filter(calculatorHistoryStates.iterator());
|
new Filter<CalculatorHistoryState>(filterRulesChain).filter(calculatorHistoryStates.iterator());
|
||||||
|
|
||||||
return calculatorHistoryStates;
|
return calculatorHistoryStates;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected abstract List<CalculatorHistoryState> getHistoryItems();
|
protected abstract List<CalculatorHistoryState> getHistoryItems();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static String getHistoryText(@NotNull CalculatorHistoryState state) {
|
public static String getHistoryText(@NotNull CalculatorHistoryState state) {
|
||||||
final StringBuilder result = new StringBuilder();
|
final StringBuilder result = new StringBuilder();
|
||||||
result.append(state.getEditorState().getText());
|
result.append(state.getEditorState().getText());
|
||||||
result.append(getIdentitySign(state.getDisplayState().getJsclOperation()));
|
result.append(getIdentitySign(state.getDisplayState().getJsclOperation()));
|
||||||
final String expressionResult = state.getDisplayState().getEditorState().getText();
|
final String expressionResult = state.getDisplayState().getEditorState().getText();
|
||||||
if (expressionResult != null) {
|
if (expressionResult != null) {
|
||||||
result.append(expressionResult);
|
result.append(expressionResult);
|
||||||
}
|
}
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static String getIdentitySign(@NotNull JsclOperation jsclOperation) {
|
private static String getIdentitySign(@NotNull JsclOperation jsclOperation) {
|
||||||
return jsclOperation == JsclOperation.simplify ? "≡" : "=";
|
return jsclOperation == JsclOperation.simplify ? "≡" : "=";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(android.view.Menu menu) {
|
public boolean onCreateOptionsMenu(android.view.Menu menu) {
|
||||||
final MenuInflater menuInflater = getMenuInflater();
|
final MenuInflater menuInflater = getMenuInflater();
|
||||||
menuInflater.inflate(R.menu.history_menu, menu);
|
menuInflater.inflate(R.menu.history_menu, menu);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
boolean result;
|
boolean result;
|
||||||
|
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.history_menu_clear_history:
|
case R.id.history_menu_clear_history:
|
||||||
clearHistory();
|
clearHistory();
|
||||||
result = true;
|
result = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = super.onOptionsItemSelected(item);
|
result = super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void clearHistory();
|
protected abstract void clearHistory();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected ArrayAdapter<CalculatorHistoryState> getAdapter() {
|
protected ArrayAdapter<CalculatorHistoryState> getAdapter() {
|
||||||
return adapter;
|
return adapter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package org.solovyev.android.calculator.history;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 16:07
|
||||||
|
*/
|
||||||
|
public interface AndroidCalculatorHistory extends CalculatorHistory {
|
||||||
|
|
||||||
|
void load(@Nullable Context context, @Nullable SharedPreferences preferences);
|
||||||
|
|
||||||
|
void save(@NotNull Context context);
|
||||||
|
}
|
@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
* or visit http://se.solovyev.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.android.calculator.history;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.android.calculator.R;
|
||||||
|
import org.solovyev.common.history.HistoryAction;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 10/9/11
|
||||||
|
* Time: 6:35 PM
|
||||||
|
*/
|
||||||
|
public enum AndroidCalculatorHistoryImpl implements AndroidCalculatorHistory {
|
||||||
|
|
||||||
|
instance;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final CalculatorHistoryImpl calculatorHistory = new CalculatorHistoryImpl();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(@Nullable Context context, @Nullable SharedPreferences preferences) {
|
||||||
|
if (context != null && preferences != null) {
|
||||||
|
final String value = preferences.getString(context.getString(R.string.p_calc_history), null);
|
||||||
|
calculatorHistory.fromXml(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(@NotNull Context context) {
|
||||||
|
final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
final SharedPreferences.Editor editor = settings.edit();
|
||||||
|
|
||||||
|
editor.putString(context.getString(R.string.p_calc_history), calculatorHistory.toXml());
|
||||||
|
|
||||||
|
editor.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearSavedHistory(@NotNull Context context) {
|
||||||
|
calculatorHistory.clearSavedHistory();
|
||||||
|
save(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeSavedHistory(@NotNull CalculatorHistoryState historyState, @NotNull Context context) {
|
||||||
|
historyState.setSaved(false);
|
||||||
|
calculatorHistory.removeSavedHistory(historyState);
|
||||||
|
save(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return calculatorHistory.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CalculatorHistoryState getLastHistoryState() {
|
||||||
|
return calculatorHistory.getLastHistoryState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUndoAvailable() {
|
||||||
|
return calculatorHistory.isUndoAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) {
|
||||||
|
return calculatorHistory.undo(currentState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRedoAvailable() {
|
||||||
|
return calculatorHistory.isRedoAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) {
|
||||||
|
return calculatorHistory.redo(currentState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActionAvailable(@NotNull HistoryAction historyAction) {
|
||||||
|
return calculatorHistory.isActionAvailable(historyAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CalculatorHistoryState doAction(@NotNull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) {
|
||||||
|
return calculatorHistory.doAction(historyAction, currentState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addState(@Nullable CalculatorHistoryState currentState) {
|
||||||
|
calculatorHistory.addState(currentState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<CalculatorHistoryState> getStates() {
|
||||||
|
return calculatorHistory.getStates();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
calculatorHistory.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public List<CalculatorHistoryState> getSavedHistory() {
|
||||||
|
return calculatorHistory.getSavedHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState) {
|
||||||
|
return calculatorHistory.addSavedState(historyState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromXml(@NotNull String xml) {
|
||||||
|
calculatorHistory.fromXml(xml);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toXml() {
|
||||||
|
return calculatorHistory.toXml();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearSavedHistory() {
|
||||||
|
calculatorHistory.clearSavedHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) {
|
||||||
|
calculatorHistory.removeSavedHistory(historyState);
|
||||||
|
}
|
||||||
|
}
|
@ -1,149 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
|
||||||
* For more information, please, contact se.solovyev@gmail.com
|
|
||||||
* or visit http://se.solovyev.org
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.solovyev.android.calculator.history;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.solovyev.android.calculator.R;
|
|
||||||
import org.solovyev.common.history.HistoryAction;
|
|
||||||
import org.solovyev.common.history.HistoryHelper;
|
|
||||||
import org.solovyev.common.history.SimpleHistoryHelper;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User: serso
|
|
||||||
* Date: 10/9/11
|
|
||||||
* Time: 6:35 PM
|
|
||||||
*/
|
|
||||||
public enum CalculatorHistory implements HistoryHelper<CalculatorHistoryState> {
|
|
||||||
|
|
||||||
instance;
|
|
||||||
|
|
||||||
// todo serso: not synchronized
|
|
||||||
private int counter = 0;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final HistoryHelper<CalculatorHistoryState> history = new SimpleHistoryHelper<CalculatorHistoryState>();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final List<CalculatorHistoryState> savedHistory = new ArrayList<CalculatorHistoryState> ();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return this.history.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CalculatorHistoryState getLastHistoryState() {
|
|
||||||
return this.history.getLastHistoryState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isUndoAvailable() {
|
|
||||||
return history.isUndoAvailable();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) {
|
|
||||||
return history.undo(currentState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRedoAvailable() {
|
|
||||||
return history.isRedoAvailable();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) {
|
|
||||||
return history.redo(currentState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isActionAvailable(@NotNull HistoryAction historyAction) {
|
|
||||||
return history.isActionAvailable(historyAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CalculatorHistoryState doAction(@NotNull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) {
|
|
||||||
return history.doAction(historyAction, currentState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addState(@Nullable CalculatorHistoryState currentState) {
|
|
||||||
history.addState(currentState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public List<CalculatorHistoryState> getStates() {
|
|
||||||
return history.getStates();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {
|
|
||||||
this.history.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load(@Nullable Context context, @Nullable SharedPreferences preferences) {
|
|
||||||
if (context != null && preferences != null) {
|
|
||||||
final String value = preferences.getString(context.getString(R.string.p_calc_history), null);
|
|
||||||
this.savedHistory.clear();
|
|
||||||
HistoryUtils.fromXml(value, this.savedHistory);
|
|
||||||
for (CalculatorHistoryState historyState : savedHistory) {
|
|
||||||
historyState.setSaved(true);
|
|
||||||
historyState.setId(counter++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save(@NotNull Context context) {
|
|
||||||
final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
|
||||||
final SharedPreferences.Editor editor = settings.edit();
|
|
||||||
|
|
||||||
editor.putString(context.getString(R.string.p_calc_history), HistoryUtils.toXml(this.savedHistory));
|
|
||||||
|
|
||||||
editor.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public List<CalculatorHistoryState> getSavedHistory() {
|
|
||||||
return Collections.unmodifiableList(savedHistory);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState) {
|
|
||||||
if (historyState.isSaved()) {
|
|
||||||
return historyState;
|
|
||||||
} else {
|
|
||||||
final CalculatorHistoryState savedState = historyState.clone();
|
|
||||||
|
|
||||||
savedState.setId(counter++);
|
|
||||||
savedState.setSaved(true);
|
|
||||||
|
|
||||||
savedHistory.add(savedState);
|
|
||||||
|
|
||||||
return savedState;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearSavedHistory(@NotNull Context context) {
|
|
||||||
this.savedHistory.clear();
|
|
||||||
save(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeSavedHistory(@NotNull CalculatorHistoryState historyState, @NotNull Context context) {
|
|
||||||
historyState.setSaved(false);
|
|
||||||
this.savedHistory.remove(historyState);
|
|
||||||
save(context);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +1,37 @@
|
|||||||
/*
|
/*
|
||||||
* 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
|
||||||
* or visit http://se.solovyev.org
|
* or visit http://se.solovyev.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator.history;
|
package org.solovyev.android.calculator.history;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 12/18/11
|
* Date: 12/18/11
|
||||||
* Time: 7:39 PM
|
* Time: 7:39 PM
|
||||||
*/
|
*/
|
||||||
public class HistoryActivityTab extends AbstractHistoryActivity {
|
public class HistoryActivityTab extends AbstractHistoryActivity {
|
||||||
@Override
|
@Override
|
||||||
protected int getLayoutId() {
|
protected int getLayoutId() {
|
||||||
return R.layout.history;
|
return R.layout.history;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
protected List<CalculatorHistoryState> getHistoryItems() {
|
protected List<CalculatorHistoryState> getHistoryItems() {
|
||||||
return new ArrayList<CalculatorHistoryState>(CalculatorHistory.instance.getStates());
|
return new ArrayList<CalculatorHistoryState>(AndroidCalculatorHistoryImpl.instance.getStates());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void clearHistory() {
|
protected void clearHistory() {
|
||||||
CalculatorHistory.instance.clear();
|
AndroidCalculatorHistoryImpl.instance.clear();
|
||||||
getAdapter().clear();
|
getAdapter().clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,154 +1,154 @@
|
|||||||
/*
|
/*
|
||||||
* 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
|
||||||
* or visit http://se.solovyev.org
|
* or visit http://se.solovyev.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator.history;
|
package org.solovyev.android.calculator.history;
|
||||||
|
|
||||||
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.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
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.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
import org.solovyev.android.menu.LabeledMenuItem;
|
import org.solovyev.android.menu.LabeledMenuItem;
|
||||||
import org.solovyev.common.text.StringUtils;
|
import org.solovyev.common.text.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 12/18/11
|
* Date: 12/18/11
|
||||||
* Time: 3:09 PM
|
* Time: 3:09 PM
|
||||||
*/
|
*/
|
||||||
public enum HistoryItemMenuItem implements LabeledMenuItem<HistoryItemMenuData> {
|
public enum HistoryItemMenuItem implements LabeledMenuItem<HistoryItemMenuData> {
|
||||||
|
|
||||||
use(R.string.c_use) {
|
use(R.string.c_use) {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) {
|
public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) {
|
||||||
if (context instanceof AbstractHistoryActivity) {
|
if (context instanceof AbstractHistoryActivity) {
|
||||||
AbstractHistoryActivity.useHistoryItem(data.getHistoryState(), (AbstractHistoryActivity) context);
|
AbstractHistoryActivity.useHistoryItem(data.getHistoryState(), (AbstractHistoryActivity) context);
|
||||||
} else {
|
} else {
|
||||||
Log.e(HistoryItemMenuItem.class.getName(), AbstractHistoryActivity.class + " must be passed as context!");
|
Log.e(HistoryItemMenuItem.class.getName(), AbstractHistoryActivity.class + " must be passed as context!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
copy_expression(R.string.c_copy_expression) {
|
copy_expression(R.string.c_copy_expression) {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) {
|
public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) {
|
||||||
final CalculatorHistoryState calculatorHistoryState = data.getHistoryState();
|
final CalculatorHistoryState calculatorHistoryState = data.getHistoryState();
|
||||||
final String text = calculatorHistoryState.getEditorState().getText();
|
final String text = calculatorHistoryState.getEditorState().getText();
|
||||||
if (!StringUtils.isEmpty(text)) {
|
if (!StringUtils.isEmpty(text)) {
|
||||||
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
|
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
|
||||||
clipboard.setText(text);
|
clipboard.setText(text);
|
||||||
Toast.makeText(context, context.getText(R.string.c_expression_copied), Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, context.getText(R.string.c_expression_copied), Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
copy_result(R.string.c_copy_result) {
|
copy_result(R.string.c_copy_result) {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) {
|
public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) {
|
||||||
final CalculatorHistoryState calculatorHistoryState = data.getHistoryState();
|
final CalculatorHistoryState calculatorHistoryState = data.getHistoryState();
|
||||||
final String text = calculatorHistoryState.getDisplayState().getEditorState().getText();
|
final String text = calculatorHistoryState.getDisplayState().getEditorState().getText();
|
||||||
if (!StringUtils.isEmpty(text)) {
|
if (!StringUtils.isEmpty(text)) {
|
||||||
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
|
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
|
||||||
clipboard.setText(text);
|
clipboard.setText(text);
|
||||||
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
save(R.string.c_save) {
|
save(R.string.c_save) {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(@NotNull final HistoryItemMenuData data, @NotNull final Context context) {
|
public void onClick(@NotNull final HistoryItemMenuData data, @NotNull final Context context) {
|
||||||
final CalculatorHistoryState historyState = data.getHistoryState();
|
final CalculatorHistoryState historyState = data.getHistoryState();
|
||||||
if (!historyState.isSaved()) {
|
if (!historyState.isSaved()) {
|
||||||
createEditHistoryDialog(data, context, true);
|
createEditHistoryDialog(data, context, true);
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(context, context.getText(R.string.c_history_already_saved), Toast.LENGTH_LONG).show();
|
Toast.makeText(context, context.getText(R.string.c_history_already_saved), Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
edit(R.string.c_edit) {
|
edit(R.string.c_edit) {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(@NotNull final HistoryItemMenuData data, @NotNull final Context context) {
|
public void onClick(@NotNull final HistoryItemMenuData data, @NotNull final Context context) {
|
||||||
final CalculatorHistoryState historyState = data.getHistoryState();
|
final CalculatorHistoryState historyState = data.getHistoryState();
|
||||||
if (historyState.isSaved()) {
|
if (historyState.isSaved()) {
|
||||||
createEditHistoryDialog(data, context, false);
|
createEditHistoryDialog(data, context, false);
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(context, context.getText(R.string.c_history_must_be_saved), Toast.LENGTH_LONG).show();
|
Toast.makeText(context, context.getText(R.string.c_history_must_be_saved), Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
remove(R.string.c_remove) {
|
remove(R.string.c_remove) {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) {
|
public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) {
|
||||||
final CalculatorHistoryState historyState = data.getHistoryState();
|
final CalculatorHistoryState historyState = data.getHistoryState();
|
||||||
if (historyState.isSaved()) {
|
if (historyState.isSaved()) {
|
||||||
data.getAdapter().remove(historyState);
|
data.getAdapter().remove(historyState);
|
||||||
CalculatorHistory.instance.removeSavedHistory(historyState, context);
|
AndroidCalculatorHistoryImpl.instance.removeSavedHistory(historyState, context);
|
||||||
Toast.makeText(context, context.getText(R.string.c_history_was_removed), Toast.LENGTH_LONG).show();
|
Toast.makeText(context, context.getText(R.string.c_history_was_removed), Toast.LENGTH_LONG).show();
|
||||||
data.getAdapter().notifyDataSetChanged();
|
data.getAdapter().notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static void createEditHistoryDialog(@NotNull final HistoryItemMenuData data, @NotNull final Context context, final boolean save) {
|
private static void createEditHistoryDialog(@NotNull final HistoryItemMenuData data, @NotNull final Context context, final boolean save) {
|
||||||
final CalculatorHistoryState historyState = data.getHistoryState();
|
final CalculatorHistoryState historyState = data.getHistoryState();
|
||||||
|
|
||||||
final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
final View editView = layoutInflater.inflate(R.layout.history_edit, null);
|
final View editView = layoutInflater.inflate(R.layout.history_edit, null);
|
||||||
final TextView historyExpression = (TextView)editView.findViewById(R.id.history_edit_expression);
|
final TextView historyExpression = (TextView)editView.findViewById(R.id.history_edit_expression);
|
||||||
historyExpression.setText(AbstractHistoryActivity.getHistoryText(historyState));
|
historyExpression.setText(AbstractHistoryActivity.getHistoryText(historyState));
|
||||||
|
|
||||||
final EditText comment = (EditText)editView.findViewById(R.id.history_edit_comment);
|
final EditText comment = (EditText)editView.findViewById(R.id.history_edit_comment);
|
||||||
comment.setText(historyState.getComment());
|
comment.setText(historyState.getComment());
|
||||||
|
|
||||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context)
|
final AlertDialog.Builder builder = new AlertDialog.Builder(context)
|
||||||
.setTitle(save ? R.string.c_save_history : R.string.c_edit_history)
|
.setTitle(save ? R.string.c_save_history : R.string.c_edit_history)
|
||||||
.setCancelable(true)
|
.setCancelable(true)
|
||||||
.setNegativeButton(R.string.c_cancel, null)
|
.setNegativeButton(R.string.c_cancel, null)
|
||||||
.setPositiveButton(R.string.c_save, new DialogInterface.OnClickListener() {
|
.setPositiveButton(R.string.c_save, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
if (save) {
|
if (save) {
|
||||||
final CalculatorHistoryState savedHistoryItem = CalculatorHistory.instance.addSavedState(historyState);
|
final CalculatorHistoryState savedHistoryItem = AndroidCalculatorHistoryImpl.instance.addSavedState(historyState);
|
||||||
savedHistoryItem.setComment(comment.getText().toString());
|
savedHistoryItem.setComment(comment.getText().toString());
|
||||||
CalculatorHistory.instance.save(context);
|
AndroidCalculatorHistoryImpl.instance.save(context);
|
||||||
// we don't need to add element to the adapter as adapter of another activity must be updated and not this
|
// we don't need to add element to the adapter as adapter of another activity must be updated and not this
|
||||||
//data.getAdapter().add(savedHistoryItem);
|
//data.getAdapter().add(savedHistoryItem);
|
||||||
} else {
|
} else {
|
||||||
historyState.setComment(comment.getText().toString());
|
historyState.setComment(comment.getText().toString());
|
||||||
CalculatorHistory.instance.save(context);
|
AndroidCalculatorHistoryImpl.instance.save(context);
|
||||||
}
|
}
|
||||||
data.getAdapter().notifyDataSetChanged();
|
data.getAdapter().notifyDataSetChanged();
|
||||||
Toast.makeText(context, context.getText(R.string.c_history_saved), Toast.LENGTH_LONG).show();
|
Toast.makeText(context, context.getText(R.string.c_history_saved), Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.setView(editView);
|
.setView(editView);
|
||||||
|
|
||||||
builder.create().show();
|
builder.create().show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final int captionId;
|
private final int captionId;
|
||||||
|
|
||||||
private HistoryItemMenuItem(int captionId) {
|
private HistoryItemMenuItem(int captionId) {
|
||||||
this.captionId = captionId;
|
this.captionId = captionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public String getCaption(@NotNull Context context) {
|
public String getCaption(@NotNull Context context) {
|
||||||
return context.getString(captionId);
|
return context.getString(captionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,37 +1,37 @@
|
|||||||
/*
|
/*
|
||||||
* 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
|
||||||
* or visit http://se.solovyev.org
|
* or visit http://se.solovyev.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator.history;
|
package org.solovyev.android.calculator.history;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 12/18/11
|
* Date: 12/18/11
|
||||||
* Time: 7:40 PM
|
* Time: 7:40 PM
|
||||||
*/
|
*/
|
||||||
public class SavedHistoryActivityTab extends AbstractHistoryActivity {
|
public class SavedHistoryActivityTab extends AbstractHistoryActivity {
|
||||||
@Override
|
@Override
|
||||||
protected int getLayoutId() {
|
protected int getLayoutId() {
|
||||||
return R.layout.saved_history;
|
return R.layout.saved_history;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
protected List<CalculatorHistoryState> getHistoryItems() {
|
protected List<CalculatorHistoryState> getHistoryItems() {
|
||||||
return new ArrayList<CalculatorHistoryState>(CalculatorHistory.instance.getSavedHistory());
|
return new ArrayList<CalculatorHistoryState>(AndroidCalculatorHistoryImpl.instance.getSavedHistory());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void clearHistory() {
|
protected void clearHistory() {
|
||||||
CalculatorHistory.instance.clearSavedHistory(this);
|
AndroidCalculatorHistoryImpl.instance.clearSavedHistory(this);
|
||||||
getAdapter().clear();
|
getAdapter().clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,7 @@ import jscl.math.operator.Operator;
|
|||||||
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.CalculatorApplication;
|
import org.solovyev.android.calculator.*;
|
||||||
import org.solovyev.android.calculator.CalculatorParseException;
|
|
||||||
import org.solovyev.android.calculator.JCalculatorEngine;
|
|
||||||
import org.solovyev.android.calculator.R;
|
|
||||||
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.android.msg.AndroidMessage;
|
import org.solovyev.android.msg.AndroidMessage;
|
||||||
|
@ -36,8 +36,8 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
import org.solovyev.android.calculator.CalculatorParseException;
|
import org.solovyev.android.calculator.CalculatorParseException;
|
||||||
import org.solovyev.android.calculator.model.PreparedExpression;
|
import org.solovyev.android.calculator.PreparedExpression;
|
||||||
import org.solovyev.android.calculator.model.ToJsclTextProcessor;
|
import org.solovyev.android.calculator.ToJsclTextProcessor;
|
||||||
import org.solovyev.common.MutableObject;
|
import org.solovyev.common.MutableObject;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
@ -13,7 +13,7 @@ import org.solovyev.android.calculator.CalculatorModel;
|
|||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
import org.solovyev.android.calculator.model.CalculatorEngine;
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
import org.solovyev.android.calculator.CalculatorParseException;
|
import org.solovyev.android.calculator.CalculatorParseException;
|
||||||
import org.solovyev.android.calculator.model.ToJsclTextProcessor;
|
import org.solovyev.android.calculator.ToJsclTextProcessor;
|
||||||
import org.solovyev.common.MutableObject;
|
import org.solovyev.common.MutableObject;
|
||||||
import org.solovyev.common.text.StringUtils;
|
import org.solovyev.common.text.StringUtils;
|
||||||
|
|
||||||
|
@ -9,7 +9,10 @@ package org.solovyev.android.calculator.view;
|
|||||||
import jscl.MathContext;
|
import jscl.MathContext;
|
||||||
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.AbstractNumberBuilder;
|
||||||
import org.solovyev.android.calculator.CalculatorParseException;
|
import org.solovyev.android.calculator.CalculatorParseException;
|
||||||
|
import org.solovyev.android.calculator.LiteNumberBuilder;
|
||||||
|
import org.solovyev.android.calculator.NumberBuilder;
|
||||||
import org.solovyev.android.calculator.math.MathType;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
import org.solovyev.android.calculator.model.*;
|
import org.solovyev.android.calculator.model.*;
|
||||||
import org.solovyev.android.calculator.text.TextProcessor;
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
|
@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.solovyev.android.calculator.Editor;
|
import org.solovyev.android.calculator.Editor;
|
||||||
import org.solovyev.android.calculator.ICalculatorDisplay;
|
import org.solovyev.android.calculator.JCalculatorDisplay;
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
import org.solovyev.common.equals.CollectionEqualizer;
|
import org.solovyev.common.equals.CollectionEqualizer;
|
||||||
import org.solovyev.common.equals.EqualsTool;
|
import org.solovyev.common.equals.EqualsTool;
|
||||||
@ -125,7 +125,7 @@ public class HistoryUtilsTest {
|
|||||||
|
|
||||||
HistoryHelper<CalculatorHistoryState> history = new SimpleHistoryHelper<CalculatorHistoryState>();
|
HistoryHelper<CalculatorHistoryState> history = new SimpleHistoryHelper<CalculatorHistoryState>();
|
||||||
|
|
||||||
ICalculatorDisplay calculatorDisplay = new TestCalculatorDisplay();
|
JCalculatorDisplay calculatorDisplay = new TestCalculatorDisplay();
|
||||||
calculatorDisplay.setErrorMessage("error_msg1");
|
calculatorDisplay.setErrorMessage("error_msg1");
|
||||||
calculatorDisplay.setText("Error");
|
calculatorDisplay.setText("Error");
|
||||||
calculatorDisplay.setSelection(1);
|
calculatorDisplay.setSelection(1);
|
||||||
@ -215,7 +215,7 @@ public class HistoryUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class TestCalculatorDisplay implements ICalculatorDisplay {
|
private static class TestCalculatorDisplay implements JCalculatorDisplay {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final TestEditor testEditor = new TestEditor();
|
private final TestEditor testEditor = new TestEditor();
|
||||||
|
@ -15,6 +15,7 @@ import jscl.math.function.CustomFunction;
|
|||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.solovyev.android.calculator.CalculatorEvalException;
|
||||||
import org.solovyev.android.calculator.CalculatorParseException;
|
import org.solovyev.android.calculator.CalculatorParseException;
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.solovyev.android.calculator.CalculatorEvalException;
|
||||||
import org.solovyev.android.calculator.CalculatorParseException;
|
import org.solovyev.android.calculator.CalculatorParseException;
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
import org.solovyev.common.Converter;
|
import org.solovyev.common.Converter;
|
||||||
|
@ -12,6 +12,8 @@ import org.junit.Assert;
|
|||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.solovyev.android.calculator.CalculatorParseException;
|
import org.solovyev.android.calculator.CalculatorParseException;
|
||||||
|
import org.solovyev.android.calculator.PreparedExpression;
|
||||||
|
import org.solovyev.android.calculator.ToJsclTextProcessor;
|
||||||
import org.solovyev.android.calculator.text.TextProcessor;
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user