Merge branch 'master' into dev
This commit is contained in:
commit
e41bc58e9f
46
calculatorpp-core/pom.xml
Normal file
46
calculatorpp-core/pom.xml
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.solovyev.android</groupId>
|
||||||
|
<artifactId>calculatorpp-parent</artifactId>
|
||||||
|
<version>1.3.1</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<groupId>org.solovyev.android</groupId>
|
||||||
|
<artifactId>calculatorpp-core</artifactId>
|
||||||
|
<version>1.3.1</version>
|
||||||
|
<name>Calculator++ Application Core</name>
|
||||||
|
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.intellij</groupId>
|
||||||
|
<artifactId>annotations</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.solovyev</groupId>
|
||||||
|
<artifactId>jscl</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.simpleframework</groupId>
|
||||||
|
<artifactId>simple-xml</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
</project>
|
@ -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,30 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import jscl.NumeralBase;
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
import org.solovyev.common.msg.MessageRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 16:38
|
||||||
|
*/
|
||||||
|
public interface Calculator extends CalculatorEventContainer {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
CalculatorEventDataId createFirstEventDataId();
|
||||||
|
|
||||||
|
void evaluate(@NotNull JsclOperation operation,
|
||||||
|
@NotNull String expression);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
CalculatorEventDataId evaluate(@NotNull JsclOperation operation,
|
||||||
|
@NotNull String expression,
|
||||||
|
@Nullable MessageRegistry mr);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
CalculatorEventDataId convert(@NotNull Generic generic, @NotNull NumeralBase to);
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 12/17/11
|
||||||
|
* Time: 9:45 PM
|
||||||
|
*/
|
||||||
|
public interface CalculatorDisplay extends CalculatorEventListener {
|
||||||
|
|
||||||
|
void setView(@Nullable CalculatorDisplayView view);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
CalculatorDisplayViewState getViewState();
|
||||||
|
|
||||||
|
void setViewState(@NotNull CalculatorDisplayViewState viewState);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
CalculatorEventData getLastEventData();
|
||||||
|
}
|
@ -0,0 +1,147 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import static org.solovyev.android.calculator.CalculatorEventType.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/12
|
||||||
|
* Time: 8:24 PM
|
||||||
|
*/
|
||||||
|
public class CalculatorDisplayImpl implements CalculatorDisplay {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private CalculatorEventData lastCalculatorEventData = CalculatorEventDataImpl.newInstance(CalculatorLocatorImpl.getInstance().getCalculator().createFirstEventDataId());
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private CalculatorDisplayView view;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Object viewLock = new Object();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private CalculatorDisplayViewState lastViewState = CalculatorDisplayViewStateImpl.newDefaultInstance();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setView(@Nullable CalculatorDisplayView view) {
|
||||||
|
synchronized (viewLock) {
|
||||||
|
this.view = view;
|
||||||
|
|
||||||
|
if (view != null) {
|
||||||
|
this.view.setState(lastViewState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public CalculatorDisplayViewState getViewState() {
|
||||||
|
return this.lastViewState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setViewState(@NotNull CalculatorDisplayViewState viewState) {
|
||||||
|
synchronized (viewLock) {
|
||||||
|
this.lastViewState = viewState;
|
||||||
|
if (this.view != null) {
|
||||||
|
this.view.setState(viewState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @Override
|
||||||
|
@Nullable
|
||||||
|
public CharSequence getText() {
|
||||||
|
synchronized (viewLock) {
|
||||||
|
return view != null ? view.getText() : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setText(@Nullable CharSequence text) {
|
||||||
|
synchronized (viewLock) {
|
||||||
|
if (view != null) {
|
||||||
|
view.setText(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSelection() {
|
||||||
|
synchronized (viewLock) {
|
||||||
|
return view != null ? view.getSelection() : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSelection(int selection) {
|
||||||
|
synchronized (viewLock) {
|
||||||
|
if (view != null) {
|
||||||
|
view.setSelection(selection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public CalculatorEventData getLastEventData() {
|
||||||
|
return lastCalculatorEventData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData,
|
||||||
|
@NotNull CalculatorEventType calculatorEventType,
|
||||||
|
@Nullable Object data) {
|
||||||
|
if (calculatorEventType.isOfType(calculation_result, calculation_failed, calculation_cancelled)) {
|
||||||
|
|
||||||
|
if (calculatorEventData.isAfter(lastCalculatorEventData)) {
|
||||||
|
lastCalculatorEventData = calculatorEventData;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (calculatorEventType) {
|
||||||
|
case calculation_result:
|
||||||
|
processCalculationResult((CalculatorEvaluationEventData)calculatorEventData, (CalculatorOutput) data);
|
||||||
|
break;
|
||||||
|
case calculation_cancelled:
|
||||||
|
processCalculationCancelled((CalculatorEvaluationEventData)calculatorEventData);
|
||||||
|
break;
|
||||||
|
case calculation_failed:
|
||||||
|
processCalculationFailed((CalculatorEvaluationEventData)calculatorEventData, (CalculatorFailure) data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processCalculationFailed(@NotNull CalculatorEvaluationEventData calculatorEventData, @NotNull CalculatorFailure data) {
|
||||||
|
|
||||||
|
final CalculatorEvalException calculatorEvalException = data.getCalculationEvalException();
|
||||||
|
|
||||||
|
final String errorMessage;
|
||||||
|
if (calculatorEvalException != null) {
|
||||||
|
errorMessage = CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error);
|
||||||
|
} else {
|
||||||
|
final CalculatorParseException calculationParseException = data.getCalculationParseException();
|
||||||
|
if (calculationParseException != null) {
|
||||||
|
errorMessage = calculationParseException.getLocalizedMessage();
|
||||||
|
} else {
|
||||||
|
errorMessage = CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setViewState(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getOperation(), errorMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processCalculationCancelled(@NotNull CalculatorEvaluationEventData calculatorEventData) {
|
||||||
|
final String errorMessage = CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error);
|
||||||
|
|
||||||
|
this.setViewState(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getOperation(), errorMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processCalculationResult(@NotNull CalculatorEvaluationEventData calculatorEventData, @NotNull CalculatorOutput data) {
|
||||||
|
final String stringResult = data.getStringResult();
|
||||||
|
this.setViewState(CalculatorDisplayViewStateImpl.newValidState(calculatorEventData.getOperation(), data.getResult(), stringResult, 0));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/12
|
||||||
|
* Time: 8:25 PM
|
||||||
|
*/
|
||||||
|
public interface CalculatorDisplayView {
|
||||||
|
|
||||||
|
void setState(@NotNull CalculatorDisplayViewState state);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
CalculatorDisplayViewState getState();
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/12
|
||||||
|
* Time: 9:50 PM
|
||||||
|
*/
|
||||||
|
public interface CalculatorDisplayViewState {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
String getText();
|
||||||
|
|
||||||
|
int getSelection();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
Generic getResult();
|
||||||
|
|
||||||
|
boolean isValid();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
String getErrorMessage();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
JsclOperation getOperation();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
String getStringResult();
|
||||||
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
import org.solovyev.common.text.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/12
|
||||||
|
* Time: 9:50 PM
|
||||||
|
*/
|
||||||
|
public class CalculatorDisplayViewStateImpl implements CalculatorDisplayViewState {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private JsclOperation operation = JsclOperation.numeric;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Generic result;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String stringResult = "";
|
||||||
|
|
||||||
|
private boolean valid = true;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String errorMessage;
|
||||||
|
|
||||||
|
private int selection = 0;
|
||||||
|
|
||||||
|
private CalculatorDisplayViewStateImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static CalculatorDisplayViewState newDefaultInstance() {
|
||||||
|
return new CalculatorDisplayViewStateImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static CalculatorDisplayViewState newErrorState(@NotNull JsclOperation operation,
|
||||||
|
@NotNull String errorMessage) {
|
||||||
|
final CalculatorDisplayViewStateImpl calculatorDisplayState = new CalculatorDisplayViewStateImpl();
|
||||||
|
calculatorDisplayState.valid = false;
|
||||||
|
calculatorDisplayState.errorMessage = errorMessage;
|
||||||
|
calculatorDisplayState.operation = operation;
|
||||||
|
return calculatorDisplayState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static CalculatorDisplayViewState newValidState(@NotNull JsclOperation operation,
|
||||||
|
@Nullable Generic result,
|
||||||
|
@NotNull String stringResult,
|
||||||
|
int selection) {
|
||||||
|
final CalculatorDisplayViewStateImpl calculatorDisplayState = new CalculatorDisplayViewStateImpl();
|
||||||
|
calculatorDisplayState.valid = true;
|
||||||
|
calculatorDisplayState.result = result;
|
||||||
|
calculatorDisplayState.stringResult = stringResult;
|
||||||
|
calculatorDisplayState.operation = operation;
|
||||||
|
calculatorDisplayState.selection = selection;
|
||||||
|
|
||||||
|
return calculatorDisplayState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getText() {
|
||||||
|
return StringUtils.getNotEmpty(isValid() ? stringResult : errorMessage, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSelection() {
|
||||||
|
return selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Generic getResult() {
|
||||||
|
return this.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid() {
|
||||||
|
return this.valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return this.errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public String getStringResult() {
|
||||||
|
return stringResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public JsclOperation getOperation() {
|
||||||
|
return this.operation;
|
||||||
|
}
|
||||||
|
}
|
@ -1,19 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
* 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;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 10/24/11
|
* Date: 10/24/11
|
||||||
* Time: 9:55 PM
|
* Time: 9:55 PM
|
||||||
*/
|
*/
|
||||||
public interface CalculatorEngineControl {
|
public interface CalculatorEngineControl {
|
||||||
|
|
||||||
void evaluate();
|
void evaluate();
|
||||||
|
|
||||||
void simplify();
|
void simplify();
|
||||||
}
|
}
|
@ -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,18 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/12
|
||||||
|
* Time: 10:00 PM
|
||||||
|
*/
|
||||||
|
public interface CalculatorEvaluationEventData extends CalculatorEventData{
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
JsclOperation getOperation();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
String getExpression();
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/12
|
||||||
|
* Time: 10:01 PM
|
||||||
|
*/
|
||||||
|
public class CalculatorEvaluationEventDataImpl implements CalculatorEvaluationEventData {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final CalculatorEventData calculatorEventData;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final JsclOperation operation;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final String expression;
|
||||||
|
|
||||||
|
public CalculatorEvaluationEventDataImpl(@NotNull CalculatorEventData calculatorEventData,
|
||||||
|
@NotNull JsclOperation operation,
|
||||||
|
@NotNull String expression) {
|
||||||
|
this.calculatorEventData = calculatorEventData;
|
||||||
|
this.operation = operation;
|
||||||
|
this.expression = expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public JsclOperation getOperation() {
|
||||||
|
return this.operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getExpression() {
|
||||||
|
return this.expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getEventId() {
|
||||||
|
return calculatorEventData.getEventId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Long getSequenceId() {
|
||||||
|
return calculatorEventData.getSequenceId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) {
|
||||||
|
return calculatorEventData.isAfter(calculatorEventDataId);
|
||||||
|
}
|
||||||
|
}
|
@ -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,10 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 16:51
|
||||||
|
*/
|
||||||
|
public interface CalculatorEventData extends CalculatorEventDataId {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
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 interface CalculatorEventDataId {
|
||||||
|
|
||||||
|
// the higher id => the later event
|
||||||
|
long getEventId();
|
||||||
|
|
||||||
|
// the higher id => the later event
|
||||||
|
@Nullable
|
||||||
|
Long getSequenceId();
|
||||||
|
|
||||||
|
boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId);
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
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
|
||||||
|
*/
|
||||||
|
class CalculatorEventDataIdImpl implements CalculatorEventDataId {
|
||||||
|
|
||||||
|
private final long eventId;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final Long sequenceId;
|
||||||
|
|
||||||
|
private CalculatorEventDataIdImpl(long id, @Nullable Long sequenceId) {
|
||||||
|
this.eventId = id;
|
||||||
|
this.sequenceId = sequenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
static CalculatorEventDataId newInstance(long id, @Nullable Long sequenceId) {
|
||||||
|
return new CalculatorEventDataIdImpl(id, sequenceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getEventId() {
|
||||||
|
return this.eventId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Long getSequenceId() {
|
||||||
|
return this.sequenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) {
|
||||||
|
return this.eventId > calculatorEventDataId.getEventId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 (sequenceId != null ? !sequenceId.equals(that.sequenceId) : that.sequenceId != null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = (int) (eventId ^ (eventId >>> 32));
|
||||||
|
result = 31 * result + (sequenceId != null ? sequenceId.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
private CalculatorEventDataImpl(@NotNull CalculatorEventDataId calculatorEventDataId) {
|
||||||
|
this.calculatorEventDataId = calculatorEventDataId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static CalculatorEventData newInstance(@NotNull CalculatorEventDataId calculatorEventDataId) {
|
||||||
|
return new CalculatorEventDataImpl(calculatorEventDataId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getEventId() {
|
||||||
|
return calculatorEventDataId.getEventId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Long getSequenceId() {
|
||||||
|
return calculatorEventDataId.getSequenceId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) {
|
||||||
|
return this.calculatorEventDataId.isAfter(calculatorEventDataId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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,55 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 16:40
|
||||||
|
*/
|
||||||
|
public enum CalculatorEventType {
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* org.solovyev.android.calculator.CalculatorEvaluationEventData
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
// @NotNull org.solovyev.android.calculator.CalculatorInput
|
||||||
|
calculation_started,
|
||||||
|
|
||||||
|
// @NotNull org.solovyev.android.calculator.CalculatorOutput
|
||||||
|
calculation_result,
|
||||||
|
|
||||||
|
calculation_cancelled,
|
||||||
|
|
||||||
|
calculation_finished,
|
||||||
|
|
||||||
|
// @NotNull org.solovyev.android.calculator.CalculatorFailure
|
||||||
|
calculation_failed,
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* CONVERSION
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
conversion_started,
|
||||||
|
|
||||||
|
// @NotNull String conversion result
|
||||||
|
conversion_finished;
|
||||||
|
|
||||||
|
public boolean isOfType(@NotNull CalculatorEventType... types) {
|
||||||
|
for (CalculatorEventType type : types) {
|
||||||
|
if ( this == type ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/12
|
||||||
|
* Time: 7:33 PM
|
||||||
|
*/
|
||||||
|
public interface CalculatorFailure {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
Exception getException();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
CalculatorParseException getCalculationParseException();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
CalculatorEvalException getCalculationEvalException();
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/12
|
||||||
|
* Time: 7:34 PM
|
||||||
|
*/
|
||||||
|
public class CalculatorFailureImpl implements CalculatorFailure {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Exception exception;
|
||||||
|
|
||||||
|
public CalculatorFailureImpl(@NotNull Exception exception) {
|
||||||
|
this.exception = exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Exception getException() {
|
||||||
|
return this.exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CalculatorParseException getCalculationParseException() {
|
||||||
|
return exception instanceof CalculatorParseException ? (CalculatorParseException)exception : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CalculatorEvalException getCalculationEvalException() {
|
||||||
|
return exception instanceof CalculatorEvalException ? (CalculatorEvalException)exception : null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,291 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import jscl.AbstractJsclArithmeticException;
|
||||||
|
import jscl.NumeralBase;
|
||||||
|
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 org.solovyev.common.msg.MessageType;
|
||||||
|
import org.solovyev.common.text.StringUtils;
|
||||||
|
import org.solovyev.math.units.UnitConverter;
|
||||||
|
import org.solovyev.math.units.UnitImpl;
|
||||||
|
import org.solovyev.math.units.UnitType;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 16:42
|
||||||
|
*/
|
||||||
|
public class CalculatorImpl implements Calculator {
|
||||||
|
|
||||||
|
private static final long FIRST_ID = 0;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final CalculatorEventContainer calculatorEventContainer = new ListCalculatorEventContainer();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final AtomicLong counter = new AtomicLong(FIRST_ID);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Object lock = new Object();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Executor threadPoolExecutor = Executors.newFixedThreadPool(10);
|
||||||
|
|
||||||
|
public CalculatorImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static String doConversion(@NotNull UnitConverter<String> converter,
|
||||||
|
@Nullable String from,
|
||||||
|
@NotNull UnitType<String> fromUnitType,
|
||||||
|
@NotNull UnitType<String> toUnitType) throws ConversionException{
|
||||||
|
final String result;
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(from)) {
|
||||||
|
result = "";
|
||||||
|
} else {
|
||||||
|
|
||||||
|
String to = null;
|
||||||
|
try {
|
||||||
|
if (converter.isSupported(fromUnitType, toUnitType)) {
|
||||||
|
to = converter.convert(UnitImpl.newInstance(from, fromUnitType), toUnitType).getValue();
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw new ConversionException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private CalculatorEventDataId nextCalculatorEventDataId() {
|
||||||
|
long eventId = counter.incrementAndGet();
|
||||||
|
return CalculatorEventDataIdImpl.newInstance(eventId, eventId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private CalculatorEventDataId nextEventDataId(@NotNull Long sequenceId) {
|
||||||
|
long eventId = counter.incrementAndGet();
|
||||||
|
return CalculatorEventDataIdImpl.newInstance(eventId, sequenceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* CALCULATION
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public CalculatorEventDataId createFirstEventDataId() {
|
||||||
|
return CalculatorEventDataIdImpl.newInstance(FIRST_ID, FIRST_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void evaluate(@NotNull JsclOperation operation,
|
||||||
|
@NotNull String expression) {
|
||||||
|
evaluate(operation, expression, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public CalculatorEventDataId 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.getSequenceId(), operation, expression, mr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return eventDataId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public CalculatorEventDataId convert(@NotNull final Generic generic,
|
||||||
|
@NotNull final NumeralBase to) {
|
||||||
|
final CalculatorEventDataId eventDataId = nextCalculatorEventDataId();
|
||||||
|
|
||||||
|
threadPoolExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
final Long sequenceId = eventDataId.getSequenceId();
|
||||||
|
assert sequenceId != null;
|
||||||
|
|
||||||
|
fireCalculatorEvent(newConversionEventData(sequenceId), CalculatorEventType.conversion_started, null);
|
||||||
|
|
||||||
|
final NumeralBase from = CalculatorLocatorImpl.getInstance().getCalculatorEngine().getEngine().getNumeralBase();
|
||||||
|
|
||||||
|
if (from != to) {
|
||||||
|
String fromString = generic.toString();
|
||||||
|
if (!StringUtils.isEmpty(fromString)) {
|
||||||
|
try {
|
||||||
|
fromString = ToJsclTextProcessor.getInstance().process(fromString).getExpression();
|
||||||
|
} catch (CalculatorParseException e) {
|
||||||
|
// ok, problems while processing occurred
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo serso: continue
|
||||||
|
//doConversion(AndroidNumeralBase.getConverter(), fromString, AndroidNumeralBase.valueOf(fromString), AndroidNumeralBase.valueOf(to));
|
||||||
|
} else {
|
||||||
|
fireCalculatorEvent(newConversionEventData(sequenceId), CalculatorEventType.conversion_finished, generic.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return eventDataId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private CalculatorEventData newConversionEventData(@NotNull Long sequenceId) {
|
||||||
|
return CalculatorEventDataImpl.newInstance(nextEventDataId(sequenceId));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void evaluate(@NotNull Long sequenceId,
|
||||||
|
@NotNull JsclOperation operation,
|
||||||
|
@NotNull String expression,
|
||||||
|
@Nullable MessageRegistry mr) {
|
||||||
|
synchronized (lock) {
|
||||||
|
|
||||||
|
PreparedExpression preparedExpression = null;
|
||||||
|
|
||||||
|
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_started, new CalculatorInputImpl(expression, operation));
|
||||||
|
|
||||||
|
try {
|
||||||
|
preparedExpression = preprocessor.process(expression);
|
||||||
|
|
||||||
|
final String jsclExpression = preparedExpression.toString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
final Generic result = operation.evaluateGeneric(jsclExpression);
|
||||||
|
|
||||||
|
// NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!)
|
||||||
|
result.toString();
|
||||||
|
|
||||||
|
final CalculatorOutputImpl data = new CalculatorOutputImpl(operation.getFromProcessor().process(result), operation, result);
|
||||||
|
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_result, data);
|
||||||
|
|
||||||
|
} catch (AbstractJsclArithmeticException e) {
|
||||||
|
handleException(sequenceId, operation, expression, mr, new CalculatorEvalException(e, e, jsclExpression));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_001, MessageType.error, e.getMessage())));
|
||||||
|
} catch (StackOverflowError e) {
|
||||||
|
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_002, MessageType.error)));
|
||||||
|
} catch (jscl.text.ParseException e) {
|
||||||
|
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(e));
|
||||||
|
} catch (ParseInterruptedException e) {
|
||||||
|
|
||||||
|
// do nothing - we ourselves interrupt the calculations
|
||||||
|
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_cancelled, null);
|
||||||
|
|
||||||
|
} catch (CalculatorParseException e) {
|
||||||
|
handleException(sequenceId, operation, expression, mr, preparedExpression, e);
|
||||||
|
} finally {
|
||||||
|
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_finished, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private CalculatorEventData newCalculationEventData(@NotNull JsclOperation operation,
|
||||||
|
@NotNull String expression,
|
||||||
|
@NotNull Long calculationId) {
|
||||||
|
return new CalculatorEvaluationEventDataImpl(CalculatorEventDataImpl.newInstance(nextEventDataId(calculationId)), operation, expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleException(@NotNull Long calculationId,
|
||||||
|
@NotNull JsclOperation operation,
|
||||||
|
@NotNull String expression,
|
||||||
|
@Nullable MessageRegistry mr,
|
||||||
|
@Nullable PreparedExpression preparedExpression,
|
||||||
|
@NotNull CalculatorParseException parseException) {
|
||||||
|
|
||||||
|
if (operation == JsclOperation.numeric
|
||||||
|
&& preparedExpression != null
|
||||||
|
&& preparedExpression.isExistsUndefinedVar()) {
|
||||||
|
|
||||||
|
evaluate(calculationId, JsclOperation.simplify, expression, mr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(parseException));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleException(@NotNull Long calculationId,
|
||||||
|
@NotNull JsclOperation operation,
|
||||||
|
@NotNull String expression,
|
||||||
|
@Nullable MessageRegistry mr,
|
||||||
|
@NotNull CalculatorEvalException evalException) {
|
||||||
|
|
||||||
|
if (operation == JsclOperation.numeric && evalException.getCause() instanceof NumeralBaseException) {
|
||||||
|
evaluate(calculationId, JsclOperation.simplify, expression, mr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(evalException));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* EVENTS
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) {
|
||||||
|
calculatorEventContainer.addCalculatorEventListener(calculatorEventListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) {
|
||||||
|
calculatorEventContainer.removeCalculatorEventListener(calculatorEventListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||||
|
calculatorEventContainer.fireCalculatorEvent(calculatorEventData, calculatorEventType, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireCalculatorEvents(@NotNull List<CalculatorEvent> calculatorEvents) {
|
||||||
|
calculatorEventContainer.fireCalculatorEvents(calculatorEvents);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class ConversionException extends Exception {
|
||||||
|
private ConversionException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConversionException(Throwable throwable) {
|
||||||
|
super(throwable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/12
|
||||||
|
* Time: 7:25 PM
|
||||||
|
*/
|
||||||
|
public interface CalculatorInput {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
String getExpression();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
JsclOperation getOperation();
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/12
|
||||||
|
* Time: 7:26 PM
|
||||||
|
*/
|
||||||
|
public class CalculatorInputImpl implements CalculatorInput {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String expression;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private JsclOperation operation;
|
||||||
|
|
||||||
|
public CalculatorInputImpl(@NotNull String expression, @NotNull JsclOperation operation) {
|
||||||
|
this.expression = expression;
|
||||||
|
this.operation = operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public String getExpression() {
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public JsclOperation getOperation() {
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 12:45
|
||||||
|
*/
|
||||||
|
public interface CalculatorLocator {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
JCalculatorEngine getCalculatorEngine();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
Calculator getCalculator();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
CalculatorDisplay getCalculatorDisplay();
|
||||||
|
|
||||||
|
void setCalculatorEngine(@NotNull JCalculatorEngine calculatorEngine);
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 12:45
|
||||||
|
*/
|
||||||
|
public class CalculatorLocatorImpl implements CalculatorLocator {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private JCalculatorEngine calculatorEngine;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private CalculatorDisplay calculatorDisplay = new CalculatorDisplayImpl();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Calculator calculator = new CalculatorImpl();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static final CalculatorLocator instance = new CalculatorLocatorImpl();
|
||||||
|
|
||||||
|
private CalculatorLocatorImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static CalculatorLocator getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public JCalculatorEngine getCalculatorEngine() {
|
||||||
|
return calculatorEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Calculator getCalculator() {
|
||||||
|
return this.calculator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCalculatorEngine(@NotNull JCalculatorEngine calculatorEngine) {
|
||||||
|
this.calculatorEngine = calculatorEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public CalculatorDisplay getCalculatorDisplay() {
|
||||||
|
return calculatorDisplay;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.common.msg.AbstractMessage;
|
||||||
|
import org.solovyev.common.msg.MessageType;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/12
|
||||||
|
* Time: 8:06 PM
|
||||||
|
*/
|
||||||
|
public class CalculatorMessage extends AbstractMessage {
|
||||||
|
|
||||||
|
protected CalculatorMessage(@NotNull String messageCode, @NotNull MessageType messageType, @org.jetbrains.annotations.Nullable Object... parameters) {
|
||||||
|
super(messageCode, messageType, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CalculatorMessage(@NotNull String messageCode, @NotNull MessageType messageType, @NotNull List<?> parameters) {
|
||||||
|
super(messageCode, messageType, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getMessagePattern(@NotNull Locale locale) {
|
||||||
|
final ResourceBundle rb = CalculatorMessages.getBundle(locale);
|
||||||
|
return rb.getString(getMessageCode());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/12
|
||||||
|
* Time: 8:10 PM
|
||||||
|
*/
|
||||||
|
public final class CalculatorMessages {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static final Map<Locale, ResourceBundle> bundlesByLocale = new HashMap<Locale, ResourceBundle>();
|
||||||
|
|
||||||
|
private CalculatorMessages() {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static ResourceBundle getBundle() {
|
||||||
|
return getBundle(Locale.getDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static ResourceBundle getBundle(@NotNull Locale locale) {
|
||||||
|
synchronized (bundlesByLocale) {
|
||||||
|
ResourceBundle result = bundlesByLocale.get(locale);
|
||||||
|
if (result == null) {
|
||||||
|
result = ResourceBundle.getBundle("org/solovyev/android/calculator/messages", locale);
|
||||||
|
bundlesByLocale.put(locale, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Arithmetic error occurred: {0} */
|
||||||
|
@NotNull
|
||||||
|
public static final String msg_001 = "msg_1";
|
||||||
|
|
||||||
|
/* Too complex expression*/
|
||||||
|
@NotNull
|
||||||
|
public static final String msg_002 = "msg_2";
|
||||||
|
|
||||||
|
/* Too long execution time - check the expression*/
|
||||||
|
@NotNull
|
||||||
|
public static final String msg_003 = "msg_3";
|
||||||
|
|
||||||
|
/* Evaluation was cancelled*/
|
||||||
|
@NotNull
|
||||||
|
public static final String msg_004 = "msg_4";
|
||||||
|
|
||||||
|
/* No parameters are specified for function: {0}*/
|
||||||
|
@NotNull
|
||||||
|
public static final String msg_005 = "msg_5";
|
||||||
|
|
||||||
|
/* Infinite loop is detected in expression*/
|
||||||
|
@NotNull
|
||||||
|
public static final String msg_006 = "msg_6";
|
||||||
|
|
||||||
|
/* Error */
|
||||||
|
@NotNull
|
||||||
|
public static final String syntax_error = "syntax_error";
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/12
|
||||||
|
* Time: 7:29 PM
|
||||||
|
*/
|
||||||
|
public interface CalculatorOutput {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
String getStringResult();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
JsclOperation getOperation();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
Generic getResult();
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/12
|
||||||
|
* Time: 7:28 PM
|
||||||
|
*/
|
||||||
|
public class CalculatorOutputImpl implements CalculatorOutput {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Generic result;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String stringResult;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private JsclOperation operation;
|
||||||
|
|
||||||
|
public CalculatorOutputImpl(@NotNull String stringResult, @NotNull JsclOperation operation, @NotNull Generic result) {
|
||||||
|
this.stringResult = stringResult;
|
||||||
|
this.operation = operation;
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public String getStringResult() {
|
||||||
|
return stringResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public JsclOperation getOperation() {
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public Generic getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -4,12 +4,10 @@
|
|||||||
* or visit http://se.solovyev.org
|
* or visit http://se.solovyev.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import android.app.Application;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.msg.AndroidMessage;
|
|
||||||
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;
|
||||||
@ -39,14 +37,17 @@ public class CalculatorParseException extends SersoException implements Message
|
|||||||
this.position = jsclParseException.getPosition();
|
this.position = jsclParseException.getPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CalculatorParseException(@NotNull Integer messageId, @NotNull Application application, @Nullable Integer position, @NotNull String expression, Object... parameters) {
|
public CalculatorParseException(@Nullable Integer position,
|
||||||
this.message = new AndroidMessage(messageId, MessageType.error, application, parameters);
|
@NotNull String expression,
|
||||||
|
@NotNull Message message) {
|
||||||
|
this.message = message;
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CalculatorParseException(@NotNull Integer messageId, @NotNull Application application, @NotNull String expression, Object... parameters) {
|
public CalculatorParseException(@NotNull String expression,
|
||||||
this(messageId, application, null, expression, parameters);
|
@NotNull Message message) {
|
||||||
|
this(null, expression, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
@ -1,27 +1,27 @@
|
|||||||
/*
|
/*
|
||||||
* 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;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 12/17/11
|
* Date: 12/17/11
|
||||||
* Time: 9:37 PM
|
* Time: 9:37 PM
|
||||||
*/
|
*/
|
||||||
public interface Editor {
|
public interface Editor {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
CharSequence getText();
|
CharSequence getText();
|
||||||
|
|
||||||
void setText(@Nullable CharSequence text);
|
void setText(@Nullable CharSequence text);
|
||||||
|
|
||||||
int getSelection();
|
int getSelection();
|
||||||
|
|
||||||
void setSelection(int selection);
|
void setSelection(int selection);
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import jscl.MathEngine;
|
||||||
|
import jscl.math.function.Function;
|
||||||
|
import jscl.math.function.IConstant;
|
||||||
|
import jscl.math.operator.Operator;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.common.math.MathRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 20.09.12
|
||||||
|
* Time: 12:43
|
||||||
|
*/
|
||||||
|
public interface JCalculatorEngine {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
String getMultiplicationSign();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
MathRegistry<IConstant> getVarsRegistry();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
MathRegistry<Function> getFunctionsRegistry();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
MathRegistry<Operator> getOperatorsRegistry();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
MathRegistry<Operator> getPostfixFunctionsRegistry();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
MathEngine getEngine();
|
||||||
|
}
|
@ -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,15 +4,20 @@
|
|||||||
* 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.PreparedExpression;
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
|
import org.solovyev.android.msg.AndroidMessage;
|
||||||
import org.solovyev.common.StartsWithFinder;
|
import org.solovyev.common.StartsWithFinder;
|
||||||
import org.solovyev.android.calculator.math.MathType;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
import org.solovyev.common.collections.CollectionsUtils;
|
import org.solovyev.common.collections.CollectionsUtils;
|
||||||
|
import org.solovyev.common.msg.MessageType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -75,7 +80,8 @@ public class ToJsclTextProcessor implements TextProcessor<PreparedExpression, St
|
|||||||
if (mathTypeBefore != null &&
|
if (mathTypeBefore != null &&
|
||||||
(mathTypeBefore.getMathType() == MathType.function || mathTypeBefore.getMathType() == MathType.operator) &&
|
(mathTypeBefore.getMathType() == MathType.function || mathTypeBefore.getMathType() == MathType.operator) &&
|
||||||
CollectionsUtils.find(MathType.openGroupSymbols, startsWithFinder) != null) {
|
CollectionsUtils.find(MathType.openGroupSymbols, startsWithFinder) != null) {
|
||||||
throw new CalculatorParseException(R.string.msg_5, CalculatorApplication.getInstance(), i, s, mathTypeBefore.getMatch());
|
final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_5, MessageType.error, CalculatorApplication.getInstance(), mathTypeBefore.getMatch());
|
||||||
|
throw new CalculatorParseException(i, s, androidMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
i = mathTypeResult.processToJscl(result, i);
|
i = mathTypeResult.processToJscl(result, i);
|
||||||
@ -86,7 +92,8 @@ public class ToJsclTextProcessor implements TextProcessor<PreparedExpression, St
|
|||||||
@NotNull
|
@NotNull
|
||||||
private static PreparedExpression replaceVariables(@NotNull final String s, int depth, @NotNull List<IConstant> undefinedVars) throws CalculatorParseException {
|
private static PreparedExpression replaceVariables(@NotNull final String s, int depth, @NotNull List<IConstant> undefinedVars) throws CalculatorParseException {
|
||||||
if (depth >= MAX_DEPTH) {
|
if (depth >= MAX_DEPTH) {
|
||||||
throw new CalculatorParseException(R.string.msg_6, CalculatorApplication.getInstance(), s);
|
final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_6, MessageType.error, CalculatorApplication.getInstance());
|
||||||
|
throw new CalculatorParseException(s, androidMessage);
|
||||||
} else {
|
} else {
|
||||||
depth++;
|
depth++;
|
||||||
}
|
}
|
@ -1,81 +1,80 @@
|
|||||||
/*
|
/*
|
||||||
* 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.Nullable;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.simpleframework.xml.Element;
|
||||||
import org.simpleframework.xml.Element;
|
import org.simpleframework.xml.Transient;
|
||||||
import org.simpleframework.xml.Transient;
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.Date;
|
|
||||||
|
/**
|
||||||
/**
|
* User: serso
|
||||||
* User: serso
|
* Date: 10/15/11
|
||||||
* Date: 10/15/11
|
* Time: 1:45 PM
|
||||||
* Time: 1:45 PM
|
*/
|
||||||
*/
|
public class AbstractHistoryState implements Cloneable{
|
||||||
public class AbstractHistoryState implements Cloneable{
|
|
||||||
|
@Element
|
||||||
@Element
|
private long time = new Date().getTime();
|
||||||
private long time = new Date().getTime();
|
|
||||||
|
@Element(required = false)
|
||||||
@Element(required = false)
|
@Nullable
|
||||||
@Nullable
|
private String comment;
|
||||||
private String comment;
|
|
||||||
|
@Transient
|
||||||
@Transient
|
private boolean saved;
|
||||||
private boolean saved;
|
|
||||||
|
@Transient
|
||||||
@Transient
|
private int id = 0;
|
||||||
private int id = 0;
|
|
||||||
|
public int getId() {
|
||||||
public int getId() {
|
return id;
|
||||||
return id;
|
}
|
||||||
}
|
|
||||||
|
public void setId(int id) {
|
||||||
public void setId(int id) {
|
this.id = id;
|
||||||
this.id = id;
|
}
|
||||||
}
|
|
||||||
|
public long getTime() {
|
||||||
public long getTime() {
|
return time;
|
||||||
return time;
|
}
|
||||||
}
|
|
||||||
|
public void setTime(long time) {
|
||||||
public void setTime(long time) {
|
this.time = time;
|
||||||
this.time = time;
|
}
|
||||||
}
|
|
||||||
|
@Nullable
|
||||||
@Nullable
|
public String getComment() {
|
||||||
public String getComment() {
|
return comment;
|
||||||
return comment;
|
}
|
||||||
}
|
|
||||||
|
public void setComment(@Nullable String comment) {
|
||||||
public void setComment(@Nullable String comment) {
|
this.comment = comment;
|
||||||
this.comment = comment;
|
}
|
||||||
}
|
|
||||||
|
public boolean isSaved() {
|
||||||
public boolean isSaved() {
|
return saved;
|
||||||
return saved;
|
}
|
||||||
}
|
|
||||||
|
public void setSaved(boolean saved) {
|
||||||
public void setSaved(boolean saved) {
|
this.saved = saved;
|
||||||
this.saved = saved;
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
@Override
|
protected AbstractHistoryState clone() {
|
||||||
protected AbstractHistoryState clone() {
|
AbstractHistoryState clone;
|
||||||
AbstractHistoryState clone;
|
|
||||||
|
try {
|
||||||
try {
|
clone = (AbstractHistoryState)super.clone();
|
||||||
clone = (AbstractHistoryState)super.clone();
|
} catch (CloneNotSupportedException e) {
|
||||||
} catch (CloneNotSupportedException e) {
|
throw new UnsupportedOperationException(e);
|
||||||
throw new UnsupportedOperationException(e);
|
}
|
||||||
}
|
|
||||||
|
return clone;
|
||||||
return clone;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
@ -11,8 +11,11 @@ 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.CalculatorDisplay;
|
||||||
|
import org.solovyev.android.calculator.CalculatorDisplayViewState;
|
||||||
|
import org.solovyev.android.calculator.CalculatorDisplayViewStateImpl;
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
import org.solovyev.common.text.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
@ -47,24 +50,27 @@ public class CalculatorDisplayHistoryState implements Cloneable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static CalculatorDisplayHistoryState newInstance(@NotNull ICalculatorDisplay display) {
|
public static CalculatorDisplayHistoryState newInstance(@NotNull CalculatorDisplay display) {
|
||||||
final CalculatorDisplayHistoryState result = new CalculatorDisplayHistoryState();
|
final CalculatorDisplayHistoryState result = new CalculatorDisplayHistoryState();
|
||||||
|
|
||||||
result.editorState = EditorHistoryState.newInstance(display);
|
result.editorState = EditorHistoryState.newInstance(display.getViewState());
|
||||||
result.valid = display.isValid();
|
|
||||||
result.jsclOperation = display.getJsclOperation();
|
final CalculatorDisplayViewState displayViewState = display.getViewState();
|
||||||
result.genericResult = display.getGenericResult();
|
|
||||||
result.errorMessage = display.getErrorMessage();
|
result.valid = displayViewState.isValid();
|
||||||
|
result.jsclOperation = displayViewState.getOperation();
|
||||||
|
result.genericResult = displayViewState.getResult();
|
||||||
|
result.errorMessage = displayViewState.getErrorMessage();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setValuesFromHistory(@NotNull ICalculatorDisplay display) {
|
public void setValuesFromHistory(@NotNull CalculatorDisplay display) {
|
||||||
this.getEditorState().setValuesFromHistory(display);
|
if ( this.isValid() ) {
|
||||||
display.setValid(this.isValid());
|
display.setViewState(CalculatorDisplayViewStateImpl.newValidState(this.getJsclOperation(), this.getGenericResult(), StringUtils.getNotEmpty(this.getEditorState().getText(), ""), this.getEditorState().getCursorPosition()));
|
||||||
display.setErrorMessage(this.getErrorMessage());
|
} else {
|
||||||
display.setJsclOperation(this.getJsclOperation());
|
display.setViewState(CalculatorDisplayViewStateImpl.newErrorState(this.getJsclOperation(), StringUtils.getNotEmpty(this.getErrorMessage(), "")));
|
||||||
display.setGenericResult(this.getGenericResult());
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,8 @@ package org.solovyev.android.calculator.history;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
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.ICalculatorDisplay;
|
import org.solovyev.android.calculator.CalculatorDisplay;
|
||||||
|
import org.solovyev.android.calculator.Editor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
@ -37,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 CalculatorDisplay 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);
|
||||||
@ -93,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 CalculatorDisplay display) {
|
||||||
this.getEditorState().setValuesFromHistory(editor);
|
this.getEditorState().setValuesFromHistory(editor);
|
||||||
this.getDisplayState().setValuesFromHistory(display);
|
this.getDisplayState().setValuesFromHistory(display);
|
||||||
}
|
}
|
@ -9,6 +9,8 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
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.solovyev.android.calculator.CalculatorDisplayViewState;
|
||||||
|
import org.solovyev.android.calculator.Editor;
|
||||||
|
|
||||||
@Root
|
@Root
|
||||||
public class EditorHistoryState implements Cloneable{
|
public class EditorHistoryState implements Cloneable{
|
||||||
@ -34,6 +36,16 @@ public class EditorHistoryState implements Cloneable{
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static EditorHistoryState newInstance(@NotNull CalculatorDisplayViewState viewState) {
|
||||||
|
final EditorHistoryState result = new EditorHistoryState();
|
||||||
|
|
||||||
|
result.text = viewState.getText();
|
||||||
|
result.cursorPosition = viewState.getSelection();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public void setValuesFromHistory(@NotNull Editor editor) {
|
public void setValuesFromHistory(@NotNull Editor editor) {
|
||||||
editor.setText(this.getText());
|
editor.setText(this.getText());
|
||||||
editor.setSelection(this.getCursorPosition());
|
editor.setSelection(this.getCursorPosition());
|
@ -1,33 +1,33 @@
|
|||||||
/*
|
/*
|
||||||
* 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.simpleframework.xml.ElementList;
|
import org.simpleframework.xml.ElementList;
|
||||||
import org.simpleframework.xml.Root;
|
import org.simpleframework.xml.Root;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 12/17/11
|
* Date: 12/17/11
|
||||||
* Time: 9:30 PM
|
* Time: 9:30 PM
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Root
|
@Root
|
||||||
public class History {
|
public class History {
|
||||||
|
|
||||||
@ElementList
|
@ElementList
|
||||||
private List<CalculatorHistoryState> historyItems = new ArrayList<CalculatorHistoryState>();
|
private List<CalculatorHistoryState> historyItems = new ArrayList<CalculatorHistoryState>();
|
||||||
|
|
||||||
public History() {
|
public History() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<CalculatorHistoryState> getHistoryItems() {
|
public List<CalculatorHistoryState> getHistoryItems() {
|
||||||
return historyItems;
|
return historyItems;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,61 +1,61 @@
|
|||||||
/*
|
/*
|
||||||
* 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.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.simpleframework.xml.Serializer;
|
import org.simpleframework.xml.Serializer;
|
||||||
import org.simpleframework.xml.core.Persister;
|
import org.simpleframework.xml.core.Persister;
|
||||||
|
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 12/17/11
|
* Date: 12/17/11
|
||||||
* Time: 9:59 PM
|
* Time: 9:59 PM
|
||||||
*/
|
*/
|
||||||
class HistoryUtils {
|
class HistoryUtils {
|
||||||
|
|
||||||
// not intended for instantiation
|
// not intended for instantiation
|
||||||
private HistoryUtils() {
|
private HistoryUtils() {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void fromXml(@Nullable String xml, @NotNull List<CalculatorHistoryState> historyItems) {
|
public static void fromXml(@Nullable String xml, @NotNull List<CalculatorHistoryState> historyItems) {
|
||||||
if (xml != null) {
|
if (xml != null) {
|
||||||
final Serializer serializer = new Persister();
|
final Serializer serializer = new Persister();
|
||||||
try {
|
try {
|
||||||
final History history = serializer.read(History.class, xml);
|
final History history = serializer.read(History.class, xml);
|
||||||
for (CalculatorHistoryState historyItem : history.getHistoryItems()) {
|
for (CalculatorHistoryState historyItem : history.getHistoryItems()) {
|
||||||
historyItems.add(historyItem);
|
historyItems.add(historyItem);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static String toXml(@NotNull List<CalculatorHistoryState> historyItems) {
|
public static String toXml(@NotNull List<CalculatorHistoryState> historyItems) {
|
||||||
final History history = new History();
|
final History history = new History();
|
||||||
for (CalculatorHistoryState historyState : historyItems) {
|
for (CalculatorHistoryState historyState : historyItems) {
|
||||||
if (historyState.isSaved()) {
|
if (historyState.isSaved()) {
|
||||||
history.getHistoryItems().add(historyState);
|
history.getHistoryItems().add(historyState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final StringWriter xml = new StringWriter();
|
final StringWriter xml = new StringWriter();
|
||||||
final Serializer serializer = new Persister();
|
final Serializer serializer = new Persister();
|
||||||
try {
|
try {
|
||||||
serializer.write(history, xml);
|
serializer.write(history, xml);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
return xml.toString();
|
return xml.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,28 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
* 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.jscl;
|
package org.solovyev.android.calculator.jscl;
|
||||||
|
|
||||||
import jscl.math.Generic;
|
import jscl.math.Generic;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.calculator.model.CalculatorParseException;
|
import org.solovyev.android.calculator.CalculatorParseException;
|
||||||
import org.solovyev.android.calculator.model.TextProcessor;
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 10/6/11
|
* Date: 10/6/11
|
||||||
* Time: 9:48 PM
|
* Time: 9:48 PM
|
||||||
*/
|
*/
|
||||||
class FromJsclNumericTextProcessor implements TextProcessor<String, Generic> {
|
class FromJsclNumericTextProcessor implements TextProcessor<String, Generic> {
|
||||||
|
|
||||||
public static final FromJsclNumericTextProcessor instance = new FromJsclNumericTextProcessor();
|
public static final FromJsclNumericTextProcessor instance = new FromJsclNumericTextProcessor();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public String process(@NotNull Generic numeric) throws CalculatorParseException {
|
public String process(@NotNull Generic numeric) throws CalculatorParseException {
|
||||||
return numeric.toString().replace("*", "");
|
return numeric.toString().replace("*", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,70 +1,70 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
* For more information, please, contact se.solovyev@gmail.com
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator.jscl;
|
package org.solovyev.android.calculator.jscl;
|
||||||
|
|
||||||
|
|
||||||
import jscl.math.Generic;
|
import jscl.math.Generic;
|
||||||
import jscl.text.ParseException;
|
import jscl.text.ParseException;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.calculator.model.CalculatorEngine;
|
import org.solovyev.android.calculator.CalculatorLocatorImpl;
|
||||||
import org.solovyev.android.calculator.model.DummyTextProcessor;
|
import org.solovyev.android.calculator.text.DummyTextProcessor;
|
||||||
import org.solovyev.android.calculator.model.FromJsclSimplifyTextProcessor;
|
import org.solovyev.android.calculator.text.FromJsclSimplifyTextProcessor;
|
||||||
import org.solovyev.android.calculator.model.TextProcessor;
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
|
|
||||||
public enum JsclOperation {
|
public enum JsclOperation {
|
||||||
|
|
||||||
simplify,
|
simplify,
|
||||||
elementary,
|
elementary,
|
||||||
numeric;
|
numeric;
|
||||||
|
|
||||||
JsclOperation() {
|
JsclOperation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public TextProcessor<String, Generic> getFromProcessor() {
|
public TextProcessor<String, Generic> getFromProcessor() {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case simplify:
|
case simplify:
|
||||||
return FromJsclSimplifyTextProcessor.instance;
|
return FromJsclSimplifyTextProcessor.instance;
|
||||||
case elementary:
|
case elementary:
|
||||||
return DummyTextProcessor.instance;
|
return DummyTextProcessor.instance;
|
||||||
case numeric:
|
case numeric:
|
||||||
return FromJsclNumericTextProcessor.instance;
|
return FromJsclNumericTextProcessor.instance;
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public final String evaluate(@NotNull String expression) throws ParseException {
|
public final String evaluate(@NotNull String expression) throws ParseException {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case simplify:
|
case simplify:
|
||||||
return CalculatorEngine.instance.getEngine().simplify(expression);
|
return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getEngine().simplify(expression);
|
||||||
case elementary:
|
case elementary:
|
||||||
return CalculatorEngine.instance.getEngine().elementary(expression);
|
return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getEngine().elementary(expression);
|
||||||
case numeric:
|
case numeric:
|
||||||
return CalculatorEngine.instance.getEngine().evaluate(expression);
|
return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getEngine().evaluate(expression);
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public final Generic evaluateGeneric(@NotNull String expression) throws ParseException {
|
public final Generic evaluateGeneric(@NotNull String expression) throws ParseException {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case simplify:
|
case simplify:
|
||||||
return CalculatorEngine.instance.getEngine().simplifyGeneric(expression);
|
return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getEngine().simplifyGeneric(expression);
|
||||||
case elementary:
|
case elementary:
|
||||||
return CalculatorEngine.instance.getEngine().elementaryGeneric(expression);
|
return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getEngine().elementaryGeneric(expression);
|
||||||
case numeric:
|
case numeric:
|
||||||
return CalculatorEngine.instance.getEngine().evaluateGeneric(expression);
|
return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getEngine().evaluateGeneric(expression);
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,448 +1,445 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
* For more information, please, contact se.solovyev@gmail.com
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator.math;
|
package org.solovyev.android.calculator.math;
|
||||||
|
|
||||||
import jscl.JsclMathEngine;
|
import jscl.JsclMathEngine;
|
||||||
import jscl.NumeralBase;
|
import jscl.NumeralBase;
|
||||||
import jscl.math.function.Constants;
|
import jscl.math.function.Constants;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.common.JPredicate;
|
import org.solovyev.android.calculator.CalculatorLocatorImpl;
|
||||||
import org.solovyev.common.StartsWithFinder;
|
import org.solovyev.common.JPredicate;
|
||||||
import org.solovyev.android.calculator.model.CalculatorEngine;
|
import org.solovyev.common.StartsWithFinder;
|
||||||
import org.solovyev.android.calculator.model.CalculatorParseException;
|
import org.solovyev.android.calculator.CalculatorParseException;
|
||||||
import org.solovyev.common.collections.CollectionsUtils;
|
import org.solovyev.common.collections.CollectionsUtils;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
public enum MathType {
|
public enum MathType {
|
||||||
|
|
||||||
numeral_base(50, true, false, MathGroupType.number) {
|
numeral_base(50, true, false, MathGroupType.number) {
|
||||||
|
|
||||||
private final List<String> tokens = new ArrayList<String>(10);
|
private final List<String> tokens = new ArrayList<String>(10);
|
||||||
{
|
{
|
||||||
for (NumeralBase numeralBase : NumeralBase.values()) {
|
for (NumeralBase numeralBase : NumeralBase.values()) {
|
||||||
final String jsclPrefix = numeralBase.getJsclPrefix();
|
tokens.add(numeralBase.getJsclPrefix());
|
||||||
if (jsclPrefix != null) {
|
}
|
||||||
tokens.add(jsclPrefix);
|
}
|
||||||
}
|
|
||||||
}
|
@NotNull
|
||||||
}
|
@Override
|
||||||
|
public List<String> getTokens() {
|
||||||
@NotNull
|
return tokens;
|
||||||
@Override
|
}
|
||||||
public List<String> getTokens() {
|
},
|
||||||
return tokens;
|
|
||||||
}
|
dot(200, true, true, MathGroupType.number, ".") {
|
||||||
},
|
@Override
|
||||||
|
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
|
||||||
dot(200, true, true, MathGroupType.number, ".") {
|
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit;
|
||||||
@Override
|
}
|
||||||
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
|
},
|
||||||
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit;
|
|
||||||
}
|
grouping_separator(250, false, false, MathGroupType.number, "'", " "){
|
||||||
},
|
@Override
|
||||||
|
public int processToJscl(@NotNull StringBuilder result, int i, @NotNull String match) throws CalculatorParseException {
|
||||||
grouping_separator(250, false, false, MathGroupType.number, "'", " "){
|
return i;
|
||||||
@Override
|
}
|
||||||
public int processToJscl(@NotNull StringBuilder result, int i, @NotNull String match) throws CalculatorParseException {
|
},
|
||||||
return i;
|
|
||||||
}
|
power_10(300, false, false, MathGroupType.number, "E"),
|
||||||
},
|
|
||||||
|
postfix_function(400, false, true, MathGroupType.function) {
|
||||||
power_10(300, false, false, MathGroupType.number, "E"),
|
@NotNull
|
||||||
|
@Override
|
||||||
postfix_function(400, false, true, MathGroupType.function) {
|
public List<String> getTokens() {
|
||||||
@NotNull
|
return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getPostfixFunctionsRegistry().getNames();
|
||||||
@Override
|
}
|
||||||
public List<String> getTokens() {
|
},
|
||||||
return CalculatorEngine.instance.getPostfixFunctionsRegistry().getNames();
|
|
||||||
}
|
unary_operation(500, false, false, MathGroupType.operation, "-", "="),
|
||||||
},
|
binary_operation(600, false, false, MathGroupType.operation, "-", "+", "*", "×", "∙", "/", "^") {
|
||||||
|
@Override
|
||||||
unary_operation(500, false, false, MathGroupType.operation, "-", "="),
|
protected String getSubstituteToJscl(@NotNull String match) {
|
||||||
binary_operation(600, false, false, MathGroupType.operation, "-", "+", "*", "×", "∙", "/", "^") {
|
if (match.equals("×") || match.equals("∙")) {
|
||||||
@Override
|
return "*";
|
||||||
protected String getSubstituteToJscl(@NotNull String match) {
|
} else {
|
||||||
if (match.equals("×") || match.equals("∙")) {
|
return null;
|
||||||
return "*";
|
}
|
||||||
} else {
|
}
|
||||||
return null;
|
},
|
||||||
}
|
|
||||||
}
|
open_group_symbol(800, true, false, MathGroupType.other, "[", "(", "{") {
|
||||||
},
|
@Override
|
||||||
|
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
|
||||||
open_group_symbol(800, true, false, MathGroupType.other, "[", "(", "{") {
|
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != function && mathTypeBefore != operator;
|
||||||
@Override
|
}
|
||||||
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
|
|
||||||
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != function && mathTypeBefore != operator;
|
@Override
|
||||||
}
|
protected String getSubstituteToJscl(@NotNull String match) {
|
||||||
|
return "(";
|
||||||
@Override
|
}
|
||||||
protected String getSubstituteToJscl(@NotNull String match) {
|
},
|
||||||
return "(";
|
|
||||||
}
|
close_group_symbol(900, false, true, MathGroupType.other, "]", ")", "}") {
|
||||||
},
|
@Override
|
||||||
|
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
|
||||||
close_group_symbol(900, false, true, MathGroupType.other, "]", ")", "}") {
|
return false;
|
||||||
@Override
|
}
|
||||||
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
|
|
||||||
return false;
|
@Override
|
||||||
}
|
protected String getSubstituteToJscl(@NotNull String match) {
|
||||||
|
return ")";
|
||||||
@Override
|
}
|
||||||
protected String getSubstituteToJscl(@NotNull String match) {
|
},
|
||||||
return ")";
|
|
||||||
}
|
function(1000, true, true, MathGroupType.function) {
|
||||||
},
|
@NotNull
|
||||||
|
@Override
|
||||||
function(1000, true, true, MathGroupType.function) {
|
public List<String> getTokens() {
|
||||||
@NotNull
|
return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getFunctionsRegistry().getNames();
|
||||||
@Override
|
}
|
||||||
public List<String> getTokens() {
|
},
|
||||||
return CalculatorEngine.instance.getFunctionsRegistry().getNames();
|
|
||||||
}
|
operator(1050, true, true, MathGroupType.function) {
|
||||||
},
|
@NotNull
|
||||||
|
@Override
|
||||||
operator(1050, true, true, MathGroupType.function) {
|
public List<String> getTokens() {
|
||||||
@NotNull
|
return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getOperatorsRegistry().getNames();
|
||||||
@Override
|
}
|
||||||
public List<String> getTokens() {
|
},
|
||||||
return CalculatorEngine.instance.getOperatorsRegistry().getNames();
|
|
||||||
}
|
constant(1100, true, true, MathGroupType.other) {
|
||||||
},
|
@NotNull
|
||||||
|
@Override
|
||||||
constant(1100, true, true, MathGroupType.other) {
|
public List<String> getTokens() {
|
||||||
@NotNull
|
return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getVarsRegistry().getNames();
|
||||||
@Override
|
}
|
||||||
public List<String> getTokens() {
|
|
||||||
return CalculatorEngine.instance.getVarsRegistry().getNames();
|
@Override
|
||||||
}
|
protected String getSubstituteFromJscl(@NotNull String match) {
|
||||||
|
return Constants.INF_2.getName().equals(match) ? MathType.INFINITY : super.getSubstituteFromJscl(match);
|
||||||
@Override
|
}
|
||||||
protected String getSubstituteFromJscl(@NotNull String match) {
|
},
|
||||||
return Constants.INF_2.getName().equals(match) ? MathType.INFINITY : super.getSubstituteFromJscl(match);
|
|
||||||
}
|
digit(1125, true, true, MathGroupType.number) {
|
||||||
},
|
|
||||||
|
private final List<String> tokens = new ArrayList<String>(16);
|
||||||
digit(1125, true, true, MathGroupType.number) {
|
{
|
||||||
|
for (Character character : NumeralBase.hex.getAcceptableCharacters()) {
|
||||||
private final List<String> tokens = new ArrayList<String>(16);
|
tokens.add(character.toString());
|
||||||
{
|
}
|
||||||
for (Character character : NumeralBase.hex.getAcceptableCharacters()) {
|
}
|
||||||
tokens.add(character.toString());
|
@Override
|
||||||
}
|
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
|
||||||
}
|
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit && mathTypeBefore != dot /*&& mathTypeBefore != numeral_base*/;
|
||||||
@Override
|
}
|
||||||
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
|
|
||||||
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit && mathTypeBefore != dot /*&& mathTypeBefore != numeral_base*/;
|
@NotNull
|
||||||
}
|
@Override
|
||||||
|
public List<String> getTokens() {
|
||||||
@NotNull
|
return tokens;
|
||||||
@Override
|
}
|
||||||
public List<String> getTokens() {
|
},
|
||||||
return tokens;
|
|
||||||
}
|
comma(1150, false, false, MathGroupType.other, ","),
|
||||||
},
|
|
||||||
|
text(1200, false, false, MathGroupType.other) {
|
||||||
comma(1150, false, false, MathGroupType.other, ","),
|
@Override
|
||||||
|
public int processToJscl(@NotNull StringBuilder result, int i, @NotNull String match) {
|
||||||
text(1200, false, false, MathGroupType.other) {
|
if (match.length() > 0) {
|
||||||
@Override
|
result.append(match.charAt(0));
|
||||||
public int processToJscl(@NotNull StringBuilder result, int i, @NotNull String match) {
|
}
|
||||||
if (match.length() > 0) {
|
return i;
|
||||||
result.append(match.charAt(0));
|
}
|
||||||
}
|
|
||||||
return i;
|
@Override
|
||||||
}
|
public int processFromJscl(@NotNull StringBuilder result, int i, @NotNull String match) {
|
||||||
|
if (match.length() > 0) {
|
||||||
@Override
|
result.append(match.charAt(0));
|
||||||
public int processFromJscl(@NotNull StringBuilder result, int i, @NotNull String match) {
|
}
|
||||||
if (match.length() > 0) {
|
return i;
|
||||||
result.append(match.charAt(0));
|
}
|
||||||
}
|
};
|
||||||
return i;
|
|
||||||
}
|
public static enum MathGroupType {
|
||||||
};
|
function,
|
||||||
|
number,
|
||||||
public static enum MathGroupType {
|
operation,
|
||||||
function,
|
other
|
||||||
number,
|
}
|
||||||
operation,
|
|
||||||
other
|
@NotNull
|
||||||
}
|
private final List<String> tokens;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final List<String> tokens;
|
private final Integer priority;
|
||||||
|
|
||||||
@NotNull
|
private final boolean needMultiplicationSignBefore;
|
||||||
private final Integer priority;
|
|
||||||
|
private final boolean needMultiplicationSignAfter;
|
||||||
private final boolean needMultiplicationSignBefore;
|
|
||||||
|
@NotNull
|
||||||
private final boolean needMultiplicationSignAfter;
|
private final MathGroupType groupType;
|
||||||
|
|
||||||
@NotNull
|
MathType(@NotNull Integer priority,
|
||||||
private final MathGroupType groupType;
|
boolean needMultiplicationSignBefore,
|
||||||
|
boolean needMultiplicationSignAfter,
|
||||||
MathType(@NotNull Integer priority,
|
@NotNull MathGroupType groupType,
|
||||||
boolean needMultiplicationSignBefore,
|
@NotNull String... tokens) {
|
||||||
boolean needMultiplicationSignAfter,
|
this(priority, needMultiplicationSignBefore, needMultiplicationSignAfter, groupType, CollectionsUtils.asList(tokens));
|
||||||
@NotNull MathGroupType groupType,
|
}
|
||||||
@NotNull String... tokens) {
|
|
||||||
this(priority, needMultiplicationSignBefore, needMultiplicationSignAfter, groupType, CollectionsUtils.asList(tokens));
|
MathType(@NotNull Integer priority,
|
||||||
}
|
boolean needMultiplicationSignBefore,
|
||||||
|
boolean needMultiplicationSignAfter,
|
||||||
MathType(@NotNull Integer priority,
|
@NotNull MathGroupType groupType,
|
||||||
boolean needMultiplicationSignBefore,
|
@NotNull List<String> tokens) {
|
||||||
boolean needMultiplicationSignAfter,
|
this.priority = priority;
|
||||||
@NotNull MathGroupType groupType,
|
this.needMultiplicationSignBefore = needMultiplicationSignBefore;
|
||||||
@NotNull List<String> tokens) {
|
this.needMultiplicationSignAfter = needMultiplicationSignAfter;
|
||||||
this.priority = priority;
|
this.groupType = groupType;
|
||||||
this.needMultiplicationSignBefore = needMultiplicationSignBefore;
|
this.tokens = Collections.unmodifiableList(tokens);
|
||||||
this.needMultiplicationSignAfter = needMultiplicationSignAfter;
|
}
|
||||||
this.groupType = groupType;
|
|
||||||
this.tokens = Collections.unmodifiableList(tokens);
|
@NotNull
|
||||||
}
|
public MathGroupType getGroupType() {
|
||||||
|
return groupType;
|
||||||
@NotNull
|
}
|
||||||
public MathGroupType getGroupType() {
|
|
||||||
return groupType;
|
/* public static int getPostfixFunctionStart(@NotNull CharSequence s, int position) throws ParseException {
|
||||||
}
|
assert s.length() > position;
|
||||||
|
|
||||||
/* public static int getPostfixFunctionStart(@NotNull CharSequence s, int position) throws ParseException {
|
int numberOfOpenGroups = 0;
|
||||||
assert s.length() > position;
|
int result = position;
|
||||||
|
for (; result >= 0; result--) {
|
||||||
int numberOfOpenGroups = 0;
|
|
||||||
int result = position;
|
final MathType mathType = getType(s.toString(), result).getMathType();
|
||||||
for (; result >= 0; result--) {
|
|
||||||
|
if (CollectionsUtils.contains(mathType, digit, dot, grouping_separator, power_10)) {
|
||||||
final MathType mathType = getType(s.toString(), result).getMathType();
|
// continue
|
||||||
|
} else if (mathType == close_group_symbol) {
|
||||||
if (CollectionsUtils.contains(mathType, digit, dot, grouping_separator, power_10)) {
|
numberOfOpenGroups++;
|
||||||
// continue
|
} else if (mathType == open_group_symbol) {
|
||||||
} else if (mathType == close_group_symbol) {
|
if (numberOfOpenGroups > 0) {
|
||||||
numberOfOpenGroups++;
|
numberOfOpenGroups--;
|
||||||
} else if (mathType == open_group_symbol) {
|
} else {
|
||||||
if (numberOfOpenGroups > 0) {
|
break;
|
||||||
numberOfOpenGroups--;
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
if (stop(s, numberOfOpenGroups, result)) break;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
if (stop(s, numberOfOpenGroups, result)) break;
|
|
||||||
}
|
if (numberOfOpenGroups != 0){
|
||||||
}
|
throw new ParseException("Could not find start of prefix function!");
|
||||||
|
}
|
||||||
if (numberOfOpenGroups != 0){
|
|
||||||
throw new ParseException("Could not find start of prefix function!");
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
public static boolean stop(CharSequence s, int numberOfOpenGroups, int i) {
|
||||||
}
|
if (numberOfOpenGroups == 0) {
|
||||||
|
if (i > 0) {
|
||||||
public static boolean stop(CharSequence s, int numberOfOpenGroups, int i) {
|
final EndsWithFinder endsWithFinder = new EndsWithFinder(s);
|
||||||
if (numberOfOpenGroups == 0) {
|
endsWithFinder.setI(i + 1);
|
||||||
if (i > 0) {
|
if (!CollectionsUtils.contains(function.getTokens(), FilterType.included, endsWithFinder)) {
|
||||||
final EndsWithFinder endsWithFinder = new EndsWithFinder(s);
|
MathType type = getType(s.toString(), i).getMathType();
|
||||||
endsWithFinder.setI(i + 1);
|
if (type != constant) {
|
||||||
if (!CollectionsUtils.contains(function.getTokens(), FilterType.included, endsWithFinder)) {
|
return true;
|
||||||
MathType type = getType(s.toString(), i).getMathType();
|
}
|
||||||
if (type != constant) {
|
}
|
||||||
return true;
|
} else {
|
||||||
}
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
return true;
|
|
||||||
}
|
return false;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
return false;
|
@NotNull
|
||||||
}*/
|
public List<String> getTokens() {
|
||||||
|
return tokens;
|
||||||
@NotNull
|
}
|
||||||
public List<String> getTokens() {
|
|
||||||
return tokens;
|
private boolean isNeedMultiplicationSignBefore() {
|
||||||
}
|
return needMultiplicationSignBefore;
|
||||||
|
}
|
||||||
private boolean isNeedMultiplicationSignBefore() {
|
|
||||||
return needMultiplicationSignBefore;
|
private boolean isNeedMultiplicationSignAfter() {
|
||||||
}
|
return needMultiplicationSignAfter;
|
||||||
|
}
|
||||||
private boolean isNeedMultiplicationSignAfter() {
|
|
||||||
return needMultiplicationSignAfter;
|
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
|
||||||
}
|
return needMultiplicationSignBefore && mathTypeBefore.isNeedMultiplicationSignAfter();
|
||||||
|
}
|
||||||
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
|
|
||||||
return needMultiplicationSignBefore && mathTypeBefore.isNeedMultiplicationSignAfter();
|
public int processToJscl(@NotNull StringBuilder result, int i, @NotNull String match) throws CalculatorParseException {
|
||||||
}
|
final String substitute = getSubstituteToJscl(match);
|
||||||
|
result.append(substitute == null ? match : substitute);
|
||||||
public int processToJscl(@NotNull StringBuilder result, int i, @NotNull String match) throws CalculatorParseException {
|
return returnI(i, match);
|
||||||
final String substitute = getSubstituteToJscl(match);
|
}
|
||||||
result.append(substitute == null ? match : substitute);
|
|
||||||
return returnI(i, match);
|
protected int returnI(int i, @NotNull String match) {
|
||||||
}
|
if (match.length() > 1) {
|
||||||
|
return i + match.length() - 1;
|
||||||
protected int returnI(int i, @NotNull String match) {
|
} else {
|
||||||
if (match.length() > 1) {
|
return i;
|
||||||
return i + match.length() - 1;
|
}
|
||||||
} else {
|
}
|
||||||
return i;
|
|
||||||
}
|
public int processFromJscl(@NotNull StringBuilder result, int i, @NotNull String match) {
|
||||||
}
|
final String substitute = getSubstituteFromJscl(match);
|
||||||
|
result.append(substitute == null ? match : substitute);
|
||||||
public int processFromJscl(@NotNull StringBuilder result, int i, @NotNull String match) {
|
return returnI(i, match);
|
||||||
final String substitute = getSubstituteFromJscl(match);
|
}
|
||||||
result.append(substitute == null ? match : substitute);
|
|
||||||
return returnI(i, match);
|
@Nullable
|
||||||
}
|
protected String getSubstituteFromJscl(@NotNull String match) {
|
||||||
|
return null;
|
||||||
@Nullable
|
}
|
||||||
protected String getSubstituteFromJscl(@NotNull String match) {
|
|
||||||
return null;
|
@Nullable
|
||||||
}
|
protected String getSubstituteToJscl(@NotNull String match) {
|
||||||
|
return null;
|
||||||
@Nullable
|
}
|
||||||
protected String getSubstituteToJscl(@NotNull String match) {
|
|
||||||
return null;
|
public static final List<String> openGroupSymbols = Arrays.asList("[]", "()", "{}");
|
||||||
}
|
|
||||||
|
public final static Character POWER_10 = 'E';
|
||||||
public static final List<String> openGroupSymbols = Arrays.asList("[]", "()", "{}");
|
|
||||||
|
public static final String IMAGINARY_NUMBER = "i";
|
||||||
public final static Character POWER_10 = 'E';
|
public static final String IMAGINARY_NUMBER_JSCL = "√(-1)";
|
||||||
|
|
||||||
public static final String IMAGINARY_NUMBER = "i";
|
public static final String PI = "π";
|
||||||
public static final String IMAGINARY_NUMBER_JSCL = "√(-1)";
|
public static final String E = "e";
|
||||||
|
public static final String C = "c";
|
||||||
public static final String PI = "π";
|
public static final Double C_VALUE = 299792458d;
|
||||||
public static final String E = "e";
|
public static final String G = "G";
|
||||||
public static final String C = "c";
|
public static final Double G_VALUE = 6.6738480E-11;
|
||||||
public static final Double C_VALUE = 299792458d;
|
public static final String H_REDUCED = "h";
|
||||||
public static final String G = "G";
|
public static final Double H_REDUCED_VALUE = 6.6260695729E-34 / ( 2 * Math.PI );
|
||||||
public static final Double G_VALUE = 6.6738480E-11;
|
public final static String NAN = "NaN";
|
||||||
public static final String H_REDUCED = "h";
|
|
||||||
public static final Double H_REDUCED_VALUE = 6.6260695729E-34 / ( 2 * Math.PI );
|
public final static String INFINITY = "∞";
|
||||||
public final static String NAN = "NaN";
|
public final static String INFINITY_JSCL = "Infinity";
|
||||||
|
|
||||||
public final static String INFINITY = "∞";
|
|
||||||
public final static String INFINITY_JSCL = "Infinity";
|
/**
|
||||||
|
* Method determines mathematical entity type for text substring starting from ith index
|
||||||
|
*
|
||||||
/**
|
*
|
||||||
* Method determines mathematical entity type for text substring starting from ith index
|
* @param text analyzed text
|
||||||
*
|
* @param i index which points to start of substring
|
||||||
*
|
* @param hexMode
|
||||||
* @param text analyzed text
|
* @return math entity type of substring starting from ith index of specified text
|
||||||
* @param i index which points to start of substring
|
*/
|
||||||
* @param hexMode
|
@NotNull
|
||||||
* @return math entity type of substring starting from ith index of specified text
|
public static Result getType(@NotNull String text, int i, boolean hexMode) {
|
||||||
*/
|
if (i < 0) {
|
||||||
@NotNull
|
throw new IllegalArgumentException("I must be more or equals to 0.");
|
||||||
public static Result getType(@NotNull String text, int i, boolean hexMode) {
|
} else if (i >= text.length() && i != 0) {
|
||||||
if (i < 0) {
|
throw new IllegalArgumentException("I must be less than size of text.");
|
||||||
throw new IllegalArgumentException("I must be more or equals to 0.");
|
} else if (i == 0 && text.length() == 0) {
|
||||||
} else if (i >= text.length() && i != 0) {
|
return new Result(MathType.text, text);
|
||||||
throw new IllegalArgumentException("I must be less than size of text.");
|
}
|
||||||
} else if (i == 0 && text.length() == 0) {
|
|
||||||
return new Result(MathType.text, text);
|
final StartsWithFinder startsWithFinder = new StartsWithFinder(text, i);
|
||||||
}
|
|
||||||
|
for (MathType mathType : getMathTypesByPriority()) {
|
||||||
final StartsWithFinder startsWithFinder = new StartsWithFinder(text, i);
|
final String s = CollectionsUtils.find(mathType.getTokens(), startsWithFinder);
|
||||||
|
if (s != null) {
|
||||||
for (MathType mathType : getMathTypesByPriority()) {
|
if ( s.length() == 1 ) {
|
||||||
final String s = CollectionsUtils.find(mathType.getTokens(), startsWithFinder);
|
if (hexMode || JsclMathEngine.instance.getNumeralBase() == NumeralBase.hex) {
|
||||||
if (s != null) {
|
final Character ch = s.charAt(0);
|
||||||
if ( s.length() == 1 ) {
|
if ( NumeralBase.hex.getAcceptableCharacters().contains(ch) ) {
|
||||||
if (hexMode || JsclMathEngine.instance.getNumeralBase() == NumeralBase.hex) {
|
return new Result(MathType.digit, s);
|
||||||
final Character ch = s.charAt(0);
|
}
|
||||||
if ( NumeralBase.hex.getAcceptableCharacters().contains(ch) ) {
|
}
|
||||||
return new Result(MathType.digit, s);
|
}
|
||||||
}
|
return new Result(mathType, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new Result(mathType, s);
|
|
||||||
}
|
return new Result(MathType.text, text.substring(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Result(MathType.text, text.substring(i));
|
|
||||||
}
|
private static List<MathType> mathTypesByPriority;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
private static List<MathType> mathTypesByPriority;
|
private static List<MathType> getMathTypesByPriority() {
|
||||||
|
if (mathTypesByPriority == null) {
|
||||||
@NotNull
|
final List<MathType> result = CollectionsUtils.asList(MathType.values());
|
||||||
private static List<MathType> getMathTypesByPriority() {
|
|
||||||
if (mathTypesByPriority == null) {
|
Collections.sort(result, new Comparator<MathType>() {
|
||||||
final List<MathType> result = CollectionsUtils.asList(MathType.values());
|
@Override
|
||||||
|
public int compare(MathType l, MathType r) {
|
||||||
Collections.sort(result, new Comparator<MathType>() {
|
return l.priority.compareTo(r.priority);
|
||||||
@Override
|
}
|
||||||
public int compare(MathType l, MathType r) {
|
});
|
||||||
return l.priority.compareTo(r.priority);
|
|
||||||
}
|
mathTypesByPriority = result;
|
||||||
});
|
}
|
||||||
|
|
||||||
mathTypesByPriority = result;
|
return mathTypesByPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mathTypesByPriority;
|
public static class Result {
|
||||||
}
|
|
||||||
|
@NotNull
|
||||||
public static class Result {
|
private final MathType mathType;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final MathType mathType;
|
private final String match;
|
||||||
|
|
||||||
@NotNull
|
public Result(@NotNull MathType mathType, @NotNull String match) {
|
||||||
private final String match;
|
this.mathType = mathType;
|
||||||
|
|
||||||
public Result(@NotNull MathType mathType, @NotNull String match) {
|
this.match = match;
|
||||||
this.mathType = mathType;
|
}
|
||||||
|
|
||||||
this.match = match;
|
public int processToJscl(@NotNull StringBuilder result, int i) throws CalculatorParseException {
|
||||||
}
|
return mathType.processToJscl(result, i, match);
|
||||||
|
}
|
||||||
public int processToJscl(@NotNull StringBuilder result, int i) throws CalculatorParseException {
|
|
||||||
return mathType.processToJscl(result, i, match);
|
public int processFromJscl(@NotNull StringBuilder result, int i) {
|
||||||
}
|
return mathType.processFromJscl(result, i, match);
|
||||||
|
}
|
||||||
public int processFromJscl(@NotNull StringBuilder result, int i) {
|
|
||||||
return mathType.processFromJscl(result, i, match);
|
@NotNull
|
||||||
}
|
public String getMatch() {
|
||||||
|
return match;
|
||||||
@NotNull
|
}
|
||||||
public String getMatch() {
|
|
||||||
return match;
|
@NotNull
|
||||||
}
|
public MathType getMathType() {
|
||||||
|
return mathType;
|
||||||
@NotNull
|
}
|
||||||
public MathType getMathType() {
|
}
|
||||||
return mathType;
|
|
||||||
}
|
private static class EndsWithFinder implements JPredicate<String> {
|
||||||
}
|
|
||||||
|
private int i;
|
||||||
private static class EndsWithFinder implements JPredicate<String> {
|
|
||||||
|
@NotNull
|
||||||
private int i;
|
private final CharSequence targetString;
|
||||||
|
|
||||||
@NotNull
|
private EndsWithFinder(@NotNull CharSequence targetString) {
|
||||||
private final CharSequence targetString;
|
this.targetString = targetString;
|
||||||
|
}
|
||||||
private EndsWithFinder(@NotNull CharSequence targetString) {
|
|
||||||
this.targetString = targetString;
|
@Override
|
||||||
}
|
public boolean apply(@Nullable String s) {
|
||||||
|
return targetString.subSequence(0, i).toString().endsWith(s);
|
||||||
@Override
|
}
|
||||||
public boolean apply(@Nullable String s) {
|
|
||||||
return targetString.subSequence(0, i).toString().endsWith(s);
|
public void setI(int i) {
|
||||||
}
|
this.i = i;
|
||||||
|
}
|
||||||
public void setI(int i) {
|
}
|
||||||
this.i = i;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +1,27 @@
|
|||||||
/*
|
/*
|
||||||
* 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.text;
|
||||||
|
|
||||||
import jscl.math.Generic;
|
import jscl.math.Generic;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.android.calculator.CalculatorParseException;
|
||||||
/**
|
|
||||||
* User: serso
|
/**
|
||||||
* Date: 10/18/11
|
* User: serso
|
||||||
* Time: 10:39 PM
|
* Date: 10/18/11
|
||||||
*/
|
* Time: 10:39 PM
|
||||||
public enum DummyTextProcessor implements TextProcessor<String, Generic> {
|
*/
|
||||||
|
public enum DummyTextProcessor implements TextProcessor<String, Generic> {
|
||||||
instance;
|
|
||||||
|
instance;
|
||||||
@NotNull
|
|
||||||
@Override
|
@NotNull
|
||||||
public String process(@NotNull Generic s) throws CalculatorParseException {
|
@Override
|
||||||
return s.toString();
|
public String process(@NotNull Generic s) throws CalculatorParseException {
|
||||||
}
|
return s.toString();
|
||||||
}
|
}
|
||||||
|
}
|
@ -1,92 +1,94 @@
|
|||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator.text;
|
||||||
|
|
||||||
import jscl.math.Generic;
|
import jscl.math.Generic;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.calculator.math.MathType;
|
import org.solovyev.android.calculator.CalculatorLocatorImpl;
|
||||||
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
import java.util.Arrays;
|
import org.solovyev.android.calculator.CalculatorParseException;
|
||||||
import java.util.List;
|
|
||||||
|
import java.util.Arrays;
|
||||||
/**
|
import java.util.List;
|
||||||
* User: serso
|
|
||||||
* Date: 10/20/11
|
/**
|
||||||
* Time: 2:59 PM
|
* User: serso
|
||||||
*/
|
* Date: 10/20/11
|
||||||
public class FromJsclSimplifyTextProcessor implements TextProcessor<String, Generic> {
|
* Time: 2:59 PM
|
||||||
|
*/
|
||||||
public static final FromJsclSimplifyTextProcessor instance = new FromJsclSimplifyTextProcessor();
|
public class FromJsclSimplifyTextProcessor implements TextProcessor<String, Generic> {
|
||||||
|
|
||||||
public FromJsclSimplifyTextProcessor() {
|
public static final FromJsclSimplifyTextProcessor instance = new FromJsclSimplifyTextProcessor();
|
||||||
}
|
|
||||||
|
public FromJsclSimplifyTextProcessor() {
|
||||||
@NotNull
|
}
|
||||||
@Override
|
|
||||||
public String process(@NotNull Generic from) throws CalculatorParseException {
|
@NotNull
|
||||||
return removeMultiplicationSigns(from.toString());
|
@Override
|
||||||
}
|
public String process(@NotNull Generic from) throws CalculatorParseException {
|
||||||
|
return removeMultiplicationSigns(from.toString());
|
||||||
public String process(@NotNull String s) {
|
}
|
||||||
return removeMultiplicationSigns(s);
|
|
||||||
}
|
public String process(@NotNull String s) {
|
||||||
|
return removeMultiplicationSigns(s);
|
||||||
@NotNull
|
}
|
||||||
private String removeMultiplicationSigns(String s) {
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
@NotNull
|
||||||
|
private String removeMultiplicationSigns(String s) {
|
||||||
MathType.Result mathTypeBefore;
|
final StringBuilder sb = new StringBuilder();
|
||||||
MathType.Result mathType = null;
|
|
||||||
MathType.Result mathTypeAfter = null;
|
MathType.Result mathTypeBefore;
|
||||||
|
MathType.Result mathType = null;
|
||||||
for (int i = 0; i < s.length(); i++) {
|
MathType.Result mathTypeAfter = null;
|
||||||
mathTypeBefore = mathType;
|
|
||||||
if (mathTypeAfter == null) {
|
for (int i = 0; i < s.length(); i++) {
|
||||||
mathType = MathType.getType(s, i, false);
|
mathTypeBefore = mathType;
|
||||||
} else {
|
if (mathTypeAfter == null) {
|
||||||
mathType = mathTypeAfter;
|
mathType = MathType.getType(s, i, false);
|
||||||
}
|
} else {
|
||||||
|
mathType = mathTypeAfter;
|
||||||
char ch = s.charAt(i);
|
}
|
||||||
if (ch == '*') {
|
|
||||||
if (i + 1 < s.length()) {
|
char ch = s.charAt(i);
|
||||||
mathTypeAfter = MathType.getType(s, i + 1, false);
|
if (ch == '*') {
|
||||||
} else {
|
if (i + 1 < s.length()) {
|
||||||
mathTypeAfter = null;
|
mathTypeAfter = MathType.getType(s, i + 1, false);
|
||||||
}
|
} else {
|
||||||
|
mathTypeAfter = null;
|
||||||
if (needMultiplicationSign(mathTypeBefore == null ? null : mathTypeBefore.getMathType(), mathTypeAfter == null ? null : mathTypeAfter.getMathType())) {
|
}
|
||||||
sb.append(CalculatorEngine.instance.getMultiplicationSign());
|
|
||||||
}
|
if (needMultiplicationSign(mathTypeBefore == null ? null : mathTypeBefore.getMathType(), mathTypeAfter == null ? null : mathTypeAfter.getMathType())) {
|
||||||
|
sb.append(CalculatorLocatorImpl.getInstance().getCalculatorEngine().getMultiplicationSign());
|
||||||
} else {
|
}
|
||||||
if (mathType.getMathType() == MathType.constant || mathType.getMathType() == MathType.function || mathType.getMathType() == MathType.operator) {
|
|
||||||
sb.append(mathType.getMatch());
|
} else {
|
||||||
i += mathType.getMatch().length() - 1;
|
if (mathType.getMathType() == MathType.constant || mathType.getMathType() == MathType.function || mathType.getMathType() == MathType.operator) {
|
||||||
} else {
|
sb.append(mathType.getMatch());
|
||||||
sb.append(ch);
|
i += mathType.getMatch().length() - 1;
|
||||||
}
|
} else {
|
||||||
mathTypeAfter = null;
|
sb.append(ch);
|
||||||
}
|
}
|
||||||
|
mathTypeAfter = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.toString();
|
}
|
||||||
}
|
|
||||||
|
return sb.toString();
|
||||||
private final List<MathType> mathTypes = Arrays.asList(MathType.function, MathType.constant);
|
}
|
||||||
|
|
||||||
private boolean needMultiplicationSign(@Nullable MathType mathTypeBefore, @Nullable MathType mathTypeAfter) {
|
private final List<MathType> mathTypes = Arrays.asList(MathType.function, MathType.constant);
|
||||||
if (mathTypeBefore == null || mathTypeAfter == null) {
|
|
||||||
return true;
|
private boolean needMultiplicationSign(@Nullable MathType mathTypeBefore, @Nullable MathType mathTypeAfter) {
|
||||||
} else if (mathTypes.contains(mathTypeBefore) || mathTypes.contains(mathTypeAfter)) {
|
if (mathTypeBefore == null || mathTypeAfter == null) {
|
||||||
return false;
|
return true;
|
||||||
} else if ( mathTypeBefore == MathType.close_group_symbol ) {
|
} else if (mathTypes.contains(mathTypeBefore) || mathTypes.contains(mathTypeAfter)) {
|
||||||
return false;
|
return false;
|
||||||
} else if ( mathTypeAfter == MathType.open_group_symbol ) {
|
} else if ( mathTypeBefore == MathType.close_group_symbol ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
} else if ( mathTypeAfter == MathType.open_group_symbol ) {
|
||||||
|
return false;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,14 +1,15 @@
|
|||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator.text;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.android.calculator.CalculatorParseException;
|
||||||
/**
|
|
||||||
* User: serso
|
/**
|
||||||
* Date: 9/26/11
|
* User: serso
|
||||||
* Time: 12:12 PM
|
* Date: 9/26/11
|
||||||
*/
|
* Time: 12:12 PM
|
||||||
public interface TextProcessor<TO extends CharSequence, FROM> {
|
*/
|
||||||
|
public interface TextProcessor<TO extends CharSequence, FROM> {
|
||||||
@NotNull
|
|
||||||
TO process(@NotNull FROM from) throws CalculatorParseException;
|
@NotNull
|
||||||
}
|
TO process(@NotNull FROM from) throws CalculatorParseException;
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,17 @@
|
|||||||
package org.solovyev.android;
|
package org.solovyev.math.units;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 4/21/12
|
* Date: 4/21/12
|
||||||
* Time: 7:54 PM
|
* Time: 7:54 PM
|
||||||
*/
|
*/
|
||||||
public interface Unit<V> {
|
public interface Unit<V> {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
V getValue();
|
V getValue();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
UnitType<V> getUnitType();
|
UnitType<V> getUnitType();
|
||||||
}
|
}
|
@ -1,42 +1,42 @@
|
|||||||
package org.solovyev.android;
|
package org.solovyev.math.units;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 4/21/12
|
* Date: 4/21/12
|
||||||
* Time: 7:53 PM
|
* Time: 7:53 PM
|
||||||
*/
|
*/
|
||||||
public interface UnitConverter<T> {
|
public interface UnitConverter<T> {
|
||||||
|
|
||||||
boolean isSupported(@NotNull UnitType<?> from, @NotNull UnitType<T> to);
|
boolean isSupported(@NotNull UnitType<?> from, @NotNull UnitType<T> to);
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
Unit<T> convert(@NotNull Unit<?> from, @NotNull UnitType<T> toType);
|
Unit<T> convert(@NotNull Unit<?> from, @NotNull UnitType<T> toType);
|
||||||
|
|
||||||
public static class Dummy implements UnitConverter<Object> {
|
public static class Dummy implements UnitConverter<Object> {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static final Dummy instance = new Dummy();
|
private static final Dummy instance = new Dummy();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static <T> UnitConverter<T> getInstance() {
|
public static <T> UnitConverter<T> getInstance() {
|
||||||
return (UnitConverter<T>)instance;
|
return (UnitConverter<T>)instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dummy() {
|
private Dummy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSupported(@NotNull UnitType<?> from, @NotNull UnitType<Object> to) {
|
public boolean isSupported(@NotNull UnitType<?> from, @NotNull UnitType<Object> to) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Unit<Object> convert(@NotNull Unit<?> from, @NotNull UnitType<Object> toType) {
|
public Unit<Object> convert(@NotNull Unit<?> from, @NotNull UnitType<Object> toType) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,42 +1,42 @@
|
|||||||
package org.solovyev.android;
|
package org.solovyev.math.units;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 4/21/12
|
* Date: 4/21/12
|
||||||
* Time: 8:01 PM
|
* Time: 8:01 PM
|
||||||
*/
|
*/
|
||||||
public class UnitImpl<V> implements Unit<V> {
|
public class UnitImpl<V> implements Unit<V> {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private V value;
|
private V value;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private UnitType<V> unitType;
|
private UnitType<V> unitType;
|
||||||
|
|
||||||
private UnitImpl() {
|
private UnitImpl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static <V> Unit<V> newInstance(@NotNull V value, @NotNull UnitType<V> unitType) {
|
public static <V> Unit<V> newInstance(@NotNull V value, @NotNull UnitType<V> unitType) {
|
||||||
final UnitImpl<V> result = new UnitImpl<V>();
|
final UnitImpl<V> result = new UnitImpl<V>();
|
||||||
|
|
||||||
result.value = value;
|
result.value = value;
|
||||||
result.unitType = unitType;
|
result.unitType = unitType;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public V getValue() {
|
public V getValue() {
|
||||||
return this.value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public UnitType<V> getUnitType() {
|
public UnitType<V> getUnitType() {
|
||||||
return unitType;
|
return unitType;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,16 +1,16 @@
|
|||||||
package org.solovyev.android;
|
package org.solovyev.math.units;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 4/21/12
|
* Date: 4/21/12
|
||||||
* Time: 7:55 PM
|
* Time: 7:55 PM
|
||||||
*/
|
*/
|
||||||
public interface UnitType<V> {
|
public interface UnitType<V> {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
Class<V> getUnitValueClass();
|
Class<V> getUnitValueClass();
|
||||||
|
|
||||||
boolean equals(@NotNull Object o);
|
boolean equals(@NotNull Object o);
|
||||||
}
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
msg_1=Arithmetic error occurred: {0}
|
||||||
|
msg_2=Too complex expression
|
||||||
|
msg_3=Too long execution time - check the expression
|
||||||
|
msg_4=Evaluation was cancelled
|
||||||
|
msg_5=No parameters are specified for function: {0}
|
||||||
|
msg_6=Infinite loop is detected in expression
|
||||||
|
|
||||||
|
syntax_error=Error
|
@ -1,36 +1,35 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.solovyev.android</groupId>
|
<groupId>org.solovyev.android</groupId>
|
||||||
<artifactId>calculatorpp-parent</artifactId>
|
<artifactId>calculatorpp-parent</artifactId>
|
||||||
<version>1.3.1</version>
|
<version>1.3.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>org.solovyev.android</groupId>
|
<groupId>org.solovyev.android</groupId>
|
||||||
<artifactId>calculatorpp-service</artifactId>
|
<artifactId>calculatorpp-service</artifactId>
|
||||||
<version>0.1</version>
|
<version>0.1</version>
|
||||||
<packaging>apklib</packaging>
|
<packaging>apklib</packaging>
|
||||||
<name>Calculator++ Service</name>
|
<name>Calculator++ Service</name>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.intellij</groupId>
|
<groupId>com.intellij</groupId>
|
||||||
<artifactId>annotations</artifactId>
|
<artifactId>annotations</artifactId>
|
||||||
<version>7.0.3</version>
|
</dependency>
|
||||||
</dependency>
|
|
||||||
|
<dependency>
|
||||||
<dependency>
|
<groupId>com.google.android</groupId>
|
||||||
<groupId>com.google.android</groupId>
|
<artifactId>android</artifactId>
|
||||||
<artifactId>android</artifactId>
|
<scope>provided</scope>
|
||||||
<scope>provided</scope>
|
</dependency>
|
||||||
</dependency>
|
|
||||||
|
</dependencies>
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -1,353 +1,340 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.solovyev.android</groupId>
|
<groupId>org.solovyev.android</groupId>
|
||||||
<artifactId>calculatorpp-parent</artifactId>
|
<artifactId>calculatorpp-parent</artifactId>
|
||||||
<version>1.3.1</version>
|
<version>1.3.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>org.solovyev.android</groupId>
|
<groupId>org.solovyev.android</groupId>
|
||||||
<artifactId>calculatorpp</artifactId>
|
<artifactId>calculatorpp</artifactId>
|
||||||
<packaging>apk</packaging>
|
<packaging>apk</packaging>
|
||||||
<name>Calculator++ Application</name>
|
<name>Calculator++ Application</name>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<!-- OWN -->
|
<!-- OWN -->
|
||||||
<dependency>
|
|
||||||
<groupId>org.solovyev</groupId>
|
<dependency>
|
||||||
<artifactId>common-core</artifactId>
|
<groupId>org.solovyev.android</groupId>
|
||||||
</dependency>
|
<artifactId>calculatorpp-core</artifactId>
|
||||||
|
<version>1.3.1</version>
|
||||||
<dependency>
|
</dependency>
|
||||||
<groupId>org.solovyev</groupId>
|
|
||||||
<artifactId>common-text</artifactId>
|
<dependency>
|
||||||
</dependency>
|
<groupId>org.solovyev</groupId>
|
||||||
|
<artifactId>common-core</artifactId>
|
||||||
<dependency>
|
</dependency>
|
||||||
<groupId>org.solovyev.android</groupId>
|
|
||||||
<artifactId>android-common-core</artifactId>
|
<dependency>
|
||||||
<type>apklib</type>
|
<groupId>org.solovyev</groupId>
|
||||||
</dependency>
|
<artifactId>common-text</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.solovyev.android</groupId>
|
<dependency>
|
||||||
<artifactId>android-common-ads</artifactId>
|
<groupId>org.solovyev.android</groupId>
|
||||||
<type>apklib</type>
|
<artifactId>android-common-core</artifactId>
|
||||||
</dependency>
|
<type>apklib</type>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.solovyev.android</groupId>
|
<dependency>
|
||||||
<artifactId>android-common-view</artifactId>
|
<groupId>org.solovyev.android</groupId>
|
||||||
<type>apklib</type>
|
<artifactId>android-common-ads</artifactId>
|
||||||
</dependency>
|
<type>apklib</type>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.solovyev.android</groupId>
|
<dependency>
|
||||||
<artifactId>android-common-preferences</artifactId>
|
<groupId>org.solovyev.android</groupId>
|
||||||
<type>apklib</type>
|
<artifactId>android-common-view</artifactId>
|
||||||
</dependency>
|
<type>apklib</type>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.solovyev.android</groupId>
|
<dependency>
|
||||||
<artifactId>android-common-other</artifactId>
|
<groupId>org.solovyev.android</groupId>
|
||||||
<type>apklib</type>
|
<artifactId>android-common-preferences</artifactId>
|
||||||
</dependency>
|
<type>apklib</type>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.solovyev.android</groupId>
|
<dependency>
|
||||||
<artifactId>android-common-menu</artifactId>
|
<groupId>org.solovyev.android</groupId>
|
||||||
<type>apklib</type>
|
<artifactId>android-common-other</artifactId>
|
||||||
</dependency>
|
<type>apklib</type>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.solovyev.android</groupId>
|
<dependency>
|
||||||
<artifactId>calculatorpp-service</artifactId>
|
<groupId>org.solovyev.android</groupId>
|
||||||
<version>0.1</version>
|
<artifactId>android-common-menu</artifactId>
|
||||||
<type>apklib</type>
|
<type>apklib</type>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.solovyev</groupId>
|
<groupId>org.solovyev.android</groupId>
|
||||||
<artifactId>jscl</artifactId>
|
<artifactId>calculatorpp-service</artifactId>
|
||||||
<version>0.0.2</version>
|
<version>0.1</version>
|
||||||
<exclusions>
|
<type>apklib</type>
|
||||||
<exclusion>
|
</dependency>
|
||||||
<artifactId>xercesImpl</artifactId>
|
|
||||||
<groupId>xerces</groupId>
|
<dependency>
|
||||||
</exclusion>
|
<groupId>org.solovyev</groupId>
|
||||||
</exclusions>
|
<artifactId>jscl</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--OTHER-->
|
<!--OTHER-->
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.android</groupId>
|
<groupId>com.google.android</groupId>
|
||||||
<artifactId>android</artifactId>
|
<artifactId>android</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>net.sf.opencsv</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>opencsv</artifactId>
|
||||||
<version>4.8.2</version>
|
<version>2.0</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.sf.opencsv</groupId>
|
<groupId>org.simpleframework</groupId>
|
||||||
<artifactId>opencsv</artifactId>
|
<artifactId>simple-xml</artifactId>
|
||||||
<version>2.0</version>
|
</dependency>
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
<dependency>
|
||||||
|
<groupId>achartengine</groupId>
|
||||||
<dependency>
|
<artifactId>achartengine</artifactId>
|
||||||
<groupId>org.simpleframework</groupId>
|
<version>0.7.0</version>
|
||||||
<artifactId>simple-xml</artifactId>
|
</dependency>
|
||||||
<version>2.6.1</version>
|
|
||||||
<exclusions>
|
<dependency>
|
||||||
<exclusion>
|
<groupId>admob</groupId>
|
||||||
<artifactId>stax-api</artifactId>
|
<artifactId>admob</artifactId>
|
||||||
<groupId>stax</groupId>
|
<version>6.1.0</version>
|
||||||
</exclusion>
|
</dependency>
|
||||||
<exclusion>
|
|
||||||
<artifactId>xpp3</artifactId>
|
<dependency>
|
||||||
<groupId>xpp3</groupId>
|
<groupId>org.solovyev.android</groupId>
|
||||||
</exclusion>
|
<artifactId>billing</artifactId>
|
||||||
</exclusions>
|
<version>0.1</version>
|
||||||
</dependency>
|
<!--<type>apklib</type>-->
|
||||||
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>achartengine</groupId>
|
<dependency>
|
||||||
<artifactId>achartengine</artifactId>
|
<groupId>com.google.guava</groupId>
|
||||||
<version>0.7.0</version>
|
<artifactId>guava</artifactId>
|
||||||
</dependency>
|
<version>11.0.2</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>admob</groupId>
|
<dependency>
|
||||||
<artifactId>admob</artifactId>
|
<groupId>junit</groupId>
|
||||||
<version>6.1.0</version>
|
<artifactId>junit</artifactId>
|
||||||
</dependency>
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.solovyev.android</groupId>
|
<dependency>
|
||||||
<artifactId>billing</artifactId>
|
<groupId>com.intellij</groupId>
|
||||||
<version>0.1</version>
|
<artifactId>annotations</artifactId>
|
||||||
<!--<type>apklib</type>-->
|
</dependency>
|
||||||
</dependency>
|
|
||||||
|
</dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.guava</groupId>
|
<build>
|
||||||
<artifactId>guava</artifactId>
|
|
||||||
<version>11.0.2</version>
|
|
||||||
</dependency>
|
<plugins>
|
||||||
|
|
||||||
<dependency>
|
<plugin>
|
||||||
<groupId>com.intellij</groupId>
|
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
|
||||||
<artifactId>annotations</artifactId>
|
<artifactId>android-maven-plugin</artifactId>
|
||||||
<version>7.0.3</version>
|
<extensions>true</extensions>
|
||||||
</dependency>
|
<configuration>
|
||||||
|
<manifest>
|
||||||
</dependencies>
|
<debuggable>true</debuggable>
|
||||||
|
</manifest>
|
||||||
<build>
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
<plugins>
|
<id>manifestUpdate</id>
|
||||||
|
<phase>process-resources</phase>
|
||||||
<plugin>
|
<goals>
|
||||||
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
|
<goal>manifest-update</goal>
|
||||||
<artifactId>android-maven-plugin</artifactId>
|
</goals>
|
||||||
<extensions>true</extensions>
|
</execution>
|
||||||
<configuration>
|
<execution>
|
||||||
<manifest>
|
<id>alignApk</id>
|
||||||
<debuggable>true</debuggable>
|
<phase>package</phase>
|
||||||
</manifest>
|
<goals>
|
||||||
</configuration>
|
<goal>zipalign</goal>
|
||||||
<executions>
|
</goals>
|
||||||
<execution>
|
</execution>
|
||||||
<id>manifestUpdate</id>
|
</executions>
|
||||||
<phase>process-resources</phase>
|
</plugin>
|
||||||
<goals>
|
|
||||||
<goal>manifest-update</goal>
|
</plugins>
|
||||||
</goals>
|
|
||||||
</execution>
|
</build>
|
||||||
<execution>
|
|
||||||
<id>alignApk</id>
|
<profiles>
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
<profile>
|
||||||
<goal>zipalign</goal>
|
<id>release</id>
|
||||||
</goals>
|
<!-- via this activation the profile is automatically used when the release is done with the maven release
|
||||||
</execution>
|
plugin -->
|
||||||
</executions>
|
<activation>
|
||||||
</plugin>
|
<property>
|
||||||
|
<name>performRelease</name>
|
||||||
</plugins>
|
<value>true</value>
|
||||||
|
</property>
|
||||||
</build>
|
</activation>
|
||||||
|
|
||||||
<profiles>
|
<build>
|
||||||
|
<plugins>
|
||||||
<profile>
|
|
||||||
<id>release</id>
|
<plugin>
|
||||||
<!-- via this activation the profile is automatically used when the release is done with the maven release
|
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
|
||||||
plugin -->
|
<artifactId>android-maven-plugin</artifactId>
|
||||||
<activation>
|
|
||||||
<property>
|
<executions>
|
||||||
<name>performRelease</name>
|
<execution>
|
||||||
<value>true</value>
|
<id>alignApk</id>
|
||||||
</property>
|
<phase>package</phase>
|
||||||
</activation>
|
<goals>
|
||||||
|
<goal>zipalign</goal>
|
||||||
<build>
|
</goals>
|
||||||
<plugins>
|
</execution>
|
||||||
|
</executions>
|
||||||
<plugin>
|
|
||||||
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
|
</plugin>
|
||||||
<artifactId>android-maven-plugin</artifactId>
|
|
||||||
|
<plugin>
|
||||||
<executions>
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
<execution>
|
<artifactId>properties-maven-plugin</artifactId>
|
||||||
<id>alignApk</id>
|
<version>1.0-alpha-2</version>
|
||||||
<phase>package</phase>
|
<executions>
|
||||||
<goals>
|
<execution>
|
||||||
<goal>zipalign</goal>
|
<phase>initialize</phase>
|
||||||
</goals>
|
<goals>
|
||||||
</execution>
|
<goal>read-project-properties</goal>
|
||||||
</executions>
|
</goals>
|
||||||
|
<configuration>
|
||||||
</plugin>
|
<files>
|
||||||
|
<file>${project.basedir}/misc/env/jarsigner.properties</file>
|
||||||
<plugin>
|
</files>
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
</configuration>
|
||||||
<artifactId>properties-maven-plugin</artifactId>
|
</execution>
|
||||||
<version>1.0-alpha-2</version>
|
</executions>
|
||||||
<executions>
|
</plugin>
|
||||||
<execution>
|
|
||||||
<phase>initialize</phase>
|
<plugin>
|
||||||
<goals>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<goal>read-project-properties</goal>
|
<artifactId>maven-jarsigner-plugin</artifactId>
|
||||||
</goals>
|
<executions>
|
||||||
<configuration>
|
<execution>
|
||||||
<files>
|
<id>signing</id>
|
||||||
<file>${project.basedir}/misc/env/jarsigner.properties</file>
|
<goals>
|
||||||
</files>
|
<goal>sign</goal>
|
||||||
</configuration>
|
<goal>verify</goal>
|
||||||
</execution>
|
</goals>
|
||||||
</executions>
|
<phase>package</phase>
|
||||||
</plugin>
|
<inherited>true</inherited>
|
||||||
|
<configuration>
|
||||||
<plugin>
|
<removeExistingSignatures>true</removeExistingSignatures>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<archiveDirectory/>
|
||||||
<artifactId>maven-jarsigner-plugin</artifactId>
|
<includes>
|
||||||
<executions>
|
<include>${project.build.directory}/${project.artifactId}-${project.version}.apk</include>
|
||||||
<execution>
|
</includes>
|
||||||
<id>signing</id>
|
<keystore>${sign.keystore}</keystore>
|
||||||
<goals>
|
<alias>${sign.alias}</alias>
|
||||||
<goal>sign</goal>
|
<storepass>${sign.storepass}</storepass>
|
||||||
<goal>verify</goal>
|
<keypass>${sign.keypass}</keypass>
|
||||||
</goals>
|
<verbose>false</verbose>
|
||||||
<phase>package</phase>
|
</configuration>
|
||||||
<inherited>true</inherited>
|
</execution>
|
||||||
<configuration>
|
</executions>
|
||||||
<removeExistingSignatures>true</removeExistingSignatures>
|
</plugin>
|
||||||
<archiveDirectory/>
|
|
||||||
<includes>
|
<!-- the signed apk then needs to be zipaligned and we activate proguard and we run the manifest
|
||||||
<include>${project.build.directory}/${project.artifactId}-${project.version}.apk</include>
|
update -->
|
||||||
</includes>
|
<plugin>
|
||||||
<keystore>${sign.keystore}</keystore>
|
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
|
||||||
<alias>${sign.alias}</alias>
|
<artifactId>android-maven-plugin</artifactId>
|
||||||
<storepass>${sign.storepass}</storepass>
|
<inherited>true</inherited>
|
||||||
<keypass>${sign.keypass}</keypass>
|
<configuration>
|
||||||
<verbose>false</verbose>
|
|
||||||
</configuration>
|
<sign>
|
||||||
</execution>
|
<debug>false</debug>
|
||||||
</executions>
|
</sign>
|
||||||
</plugin>
|
|
||||||
|
<zipalign>
|
||||||
<!-- the signed apk then needs to be zipaligned and we activate proguard and we run the manifest
|
<verbose>false</verbose>
|
||||||
update -->
|
<inputApk>${project.build.directory}/${project.artifactId}-${project.version}.apk</inputApk>
|
||||||
<plugin>
|
<outputApk>${project.build.directory}/${project.artifactId}-${project.version}-signed-aligned.apk</outputApk>
|
||||||
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
|
</zipalign>
|
||||||
<artifactId>android-maven-plugin</artifactId>
|
|
||||||
<inherited>true</inherited>
|
<manifest>
|
||||||
<configuration>
|
<debuggable>false</debuggable>
|
||||||
|
<versionCodeAutoIncrement>true</versionCodeAutoIncrement>
|
||||||
<sign>
|
</manifest>
|
||||||
<debug>false</debug>
|
|
||||||
</sign>
|
<proguard>
|
||||||
|
<skip>true</skip>
|
||||||
<zipalign>
|
</proguard>
|
||||||
<verbose>false</verbose>
|
</configuration>
|
||||||
<inputApk>${project.build.directory}/${project.artifactId}-${project.version}.apk</inputApk>
|
|
||||||
<outputApk>${project.build.directory}/${project.artifactId}-${project.version}-signed-aligned.apk</outputApk>
|
<executions>
|
||||||
</zipalign>
|
<execution>
|
||||||
|
<id>manifestUpdate</id>
|
||||||
<manifest>
|
<phase>process-resources</phase>
|
||||||
<debuggable>false</debuggable>
|
<goals>
|
||||||
<versionCodeAutoIncrement>true</versionCodeAutoIncrement>
|
<goal>manifest-update</goal>
|
||||||
</manifest>
|
</goals>
|
||||||
|
</execution>
|
||||||
<proguard>
|
<execution>
|
||||||
<skip>true</skip>
|
<id>alignApk</id>
|
||||||
</proguard>
|
<phase>package</phase>
|
||||||
</configuration>
|
<goals>
|
||||||
|
<goal>zipalign</goal>
|
||||||
<executions>
|
</goals>
|
||||||
<execution>
|
</execution>
|
||||||
<id>manifestUpdate</id>
|
</executions>
|
||||||
<phase>process-resources</phase>
|
</plugin>
|
||||||
<goals>
|
|
||||||
<goal>manifest-update</goal>
|
<plugin>
|
||||||
</goals>
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
</execution>
|
<artifactId>build-helper-maven-plugin</artifactId>
|
||||||
<execution>
|
<configuration>
|
||||||
<id>alignApk</id>
|
<artifacts>
|
||||||
<phase>package</phase>
|
<artifact>
|
||||||
<goals>
|
<file>${project.build.directory}/${project.artifactId}-${project.version}-signed-aligned.apk</file>
|
||||||
<goal>zipalign</goal>
|
<type>apk</type>
|
||||||
</goals>
|
<classifier>signed-aligned</classifier>
|
||||||
</execution>
|
</artifact>
|
||||||
</executions>
|
<artifact>
|
||||||
</plugin>
|
<file>${project.build.directory}/proguard/mapping.txt</file>
|
||||||
|
<type>map</type>
|
||||||
<plugin>
|
<classifier>release</classifier>
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
</artifact>
|
||||||
<artifactId>build-helper-maven-plugin</artifactId>
|
</artifacts>
|
||||||
<configuration>
|
</configuration>
|
||||||
<artifacts>
|
<executions>
|
||||||
<artifact>
|
<execution>
|
||||||
<file>${project.build.directory}/${project.artifactId}-${project.version}-signed-aligned.apk</file>
|
<id>attach-signed-aligned</id>
|
||||||
<type>apk</type>
|
<phase>package</phase>
|
||||||
<classifier>signed-aligned</classifier>
|
<goals>
|
||||||
</artifact>
|
<goal>attach-artifact</goal>
|
||||||
<artifact>
|
</goals>
|
||||||
<file>${project.build.directory}/proguard/mapping.txt</file>
|
</execution>
|
||||||
<type>map</type>
|
</executions>
|
||||||
<classifier>release</classifier>
|
</plugin>
|
||||||
</artifact>
|
|
||||||
</artifacts>
|
</plugins>
|
||||||
</configuration>
|
</build>
|
||||||
<executions>
|
</profile>
|
||||||
<execution>
|
</profiles>
|
||||||
<id>attach-signed-aligned</id>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>attach-artifact</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
|
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -1,20 +1,19 @@
|
|||||||
# This file is automatically generated by Android Tools.
|
# This file is automatically generated by Android Tools.
|
||||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
#
|
#
|
||||||
# This file must be checked in Version Control Systems.
|
# This file must be checked in Version Control Systems.
|
||||||
#
|
#
|
||||||
# To customize properties used by the Ant build system use,
|
# To customize properties used by the Ant build system use,
|
||||||
# "ant.properties", and override values to adapt the script to your
|
# "ant.properties", and override values to adapt the script to your
|
||||||
# project structure.
|
# project structure.
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-15
|
target=android-15
|
||||||
android.library.reference.1=../calculatorpp-service
|
android.library.reference.1=gen-external-apklibs/org.solovyev.android_android-common-core_1.0.0
|
||||||
android.library.reference.2=gen-external-apklibs/org.solovyev.android_android-common-core_1.0.0
|
android.library.reference.2=gen-external-apklibs/org.solovyev.android_android-common-ads_1.0.0
|
||||||
android.library.reference.3=gen-external-apklibs/org.solovyev.android_android-common-ads_1.0.0
|
android.library.reference.3=gen-external-apklibs/org.solovyev.android_android-common-view_1.0.0
|
||||||
android.library.reference.4=gen-external-apklibs/org.solovyev.android_android-common-view_1.0.0
|
android.library.reference.4=gen-external-apklibs/org.solovyev.android_android-common-preferences_1.0.0
|
||||||
android.library.reference.5=gen-external-apklibs/org.solovyev.android_android-common-preferences_1.0.0
|
android.library.reference.5=gen-external-apklibs/org.solovyev.android_android-common-other_1.0.0
|
||||||
android.library.reference.6=gen-external-apklibs/org.solovyev.android_android-common-other_1.0.0
|
android.library.reference.6=gen-external-apklibs/org.solovyev.android_android-common-menu_1.0.0
|
||||||
android.library.reference.7=gen-external-apklibs/org.solovyev.android_android-common-menu_1.0.0
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
~ or visit http://se.solovyev.org
|
~ or visit http://se.solovyev.org
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<org.solovyev.android.calculator.CalculatorDisplay
|
<org.solovyev.android.calculator.AndroidCalculatorDisplayView
|
||||||
xmlns:a="http://schemas.android.com/apk/res/android"
|
xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
a:id="@+id/calculatorDisplay"
|
a:id="@+id/calculatorDisplay"
|
||||||
style="@style/display_style"
|
style="@style/display_style"
|
||||||
|
@ -0,0 +1,235 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import jscl.math.function.Constant;
|
||||||
|
import jscl.math.function.IConstant;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
|
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
|
||||||
|
import org.solovyev.android.calculator.view.TextHighlighter;
|
||||||
|
import org.solovyev.android.menu.LabeledMenuItem;
|
||||||
|
import org.solovyev.android.view.AutoResizeTextView;
|
||||||
|
import org.solovyev.common.collections.CollectionsUtils;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/17/11
|
||||||
|
* Time: 10:58 PM
|
||||||
|
*/
|
||||||
|
public class AndroidCalculatorDisplayView extends AutoResizeTextView implements CalculatorDisplayView {
|
||||||
|
|
||||||
|
public static enum MenuItem implements LabeledMenuItem<CalculatorDisplayViewState> {
|
||||||
|
|
||||||
|
copy(R.string.c_copy) {
|
||||||
|
@Override
|
||||||
|
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
||||||
|
CalculatorModel.copyResult(context, data);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
convert_to_bin(R.string.convert_to_bin) {
|
||||||
|
@Override
|
||||||
|
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
||||||
|
ConversionMenuItem.convert_to_bin.onClick(data, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||||
|
return ConversionMenuItem.convert_to_bin.isItemVisibleFor(generic, operation);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
convert_to_dec(R.string.convert_to_dec) {
|
||||||
|
@Override
|
||||||
|
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
||||||
|
ConversionMenuItem.convert_to_dec.onClick(data, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||||
|
return ConversionMenuItem.convert_to_dec.isItemVisibleFor(generic, operation);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
convert_to_hex(R.string.convert_to_hex) {
|
||||||
|
@Override
|
||||||
|
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
||||||
|
ConversionMenuItem.convert_to_hex.onClick(data, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||||
|
return ConversionMenuItem.convert_to_hex.isItemVisibleFor(generic, operation);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
convert(R.string.c_convert) {
|
||||||
|
@Override
|
||||||
|
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
||||||
|
final Generic result = data.getResult();
|
||||||
|
if (result != null) {
|
||||||
|
new NumeralBaseConverterDialog(result.toString()).show(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||||
|
return operation == JsclOperation.numeric && generic.getConstants().isEmpty();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
plot(R.string.c_plot) {
|
||||||
|
@Override
|
||||||
|
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
||||||
|
final Generic generic = data.getResult();
|
||||||
|
assert generic != null;
|
||||||
|
|
||||||
|
final Constant constant = CollectionsUtils.getFirstCollectionElement(getNotSystemConstants(generic));
|
||||||
|
assert constant != null;
|
||||||
|
CalculatorActivityLauncher.plotGraph(context, generic, constant);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||||
|
boolean result = false;
|
||||||
|
|
||||||
|
if (operation == JsclOperation.simplify) {
|
||||||
|
if (getNotSystemConstants(generic).size() == 1) {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Set<Constant> getNotSystemConstants(@NotNull Generic generic) {
|
||||||
|
final Set<Constant> notSystemConstants = new HashSet<Constant>();
|
||||||
|
|
||||||
|
for (Constant constant : generic.getConstants()) {
|
||||||
|
IConstant var = CalculatorEngine.instance.getVarsRegistry().get(constant.getName());
|
||||||
|
if (var != null && !var.isSystem() && !var.isDefined()) {
|
||||||
|
notSystemConstants.add(constant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return notSystemConstants;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final int captionId;
|
||||||
|
|
||||||
|
MenuItem(int captionId) {
|
||||||
|
this.captionId = captionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean isItemVisible(@NotNull CalculatorDisplayViewState displayViewState) {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
return displayViewState.isValid() && displayViewState.getResult() != null && isItemVisibleFor(displayViewState.getResult(), displayViewState.getOperation());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getCaption(@NotNull Context context) {
|
||||||
|
return context.getString(captionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private CalculatorDisplayViewState state = CalculatorDisplayViewStateImpl.newDefaultInstance();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine());
|
||||||
|
|
||||||
|
public AndroidCalculatorDisplayView(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AndroidCalculatorDisplayView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AndroidCalculatorDisplayView(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return this.state.isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(@NotNull CalculatorDisplayViewState state) {
|
||||||
|
this.state = state;
|
||||||
|
if ( state.isValid() ) {
|
||||||
|
setTextColor(getResources().getColor(R.color.default_text_color));
|
||||||
|
setText(state.getStringResult());
|
||||||
|
} else {
|
||||||
|
setTextColor(getResources().getColor(R.color.display_error_text_color));
|
||||||
|
setText(state.getErrorMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public CalculatorDisplayViewState getState() {
|
||||||
|
return this.state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setText(CharSequence text, BufferType type) {
|
||||||
|
super.setText(text, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void redraw() {
|
||||||
|
if (isValid()) {
|
||||||
|
String text = getText().toString();
|
||||||
|
|
||||||
|
Log.d(this.getClass().getName(), text);
|
||||||
|
|
||||||
|
try {
|
||||||
|
TextHighlighter.Result result = textHighlighter.process(text);
|
||||||
|
text = result.toString();
|
||||||
|
} catch (CalculatorParseException e) {
|
||||||
|
Log.e(this.getClass().getName(), e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(this.getClass().getName(), text);
|
||||||
|
super.setText(Html.fromHtml(text), BufferType.EDITABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo serso: think where to move it (keep in mind org.solovyev.android.view.AutoResizeTextView.resetTextSize())
|
||||||
|
setAddEllipsis(false);
|
||||||
|
setMinTextSize(10);
|
||||||
|
resizeText();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSelection() {
|
||||||
|
return this.getSelectionStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSelection(int selection) {
|
||||||
|
// not supported by TextView
|
||||||
|
}
|
||||||
|
}
|
@ -1,158 +1,158 @@
|
|||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import jscl.NumeralBase;
|
import jscl.NumeralBase;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.Unit;
|
import org.solovyev.math.units.Unit;
|
||||||
import org.solovyev.android.UnitConverter;
|
import org.solovyev.math.units.UnitConverter;
|
||||||
import org.solovyev.android.UnitImpl;
|
import org.solovyev.math.units.UnitImpl;
|
||||||
import org.solovyev.android.UnitType;
|
import org.solovyev.math.units.UnitType;
|
||||||
import org.solovyev.android.view.drag.DirectionDragButton;
|
import org.solovyev.android.view.drag.DirectionDragButton;
|
||||||
import org.solovyev.android.view.drag.DragDirection;
|
import org.solovyev.android.view.drag.DragDirection;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 4/21/12
|
* Date: 4/21/12
|
||||||
* Time: 8:00 PM
|
* Time: 8:00 PM
|
||||||
*/
|
*/
|
||||||
public enum AndroidNumeralBase implements UnitType<String> {
|
public enum AndroidNumeralBase implements UnitType<String> {
|
||||||
|
|
||||||
bin(NumeralBase.bin) {
|
bin(NumeralBase.bin) {
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public List<Integer> getButtonIds() {
|
public List<Integer> getButtonIds() {
|
||||||
return Arrays.asList(R.id.zeroDigitButton, R.id.oneDigitButton);
|
return Arrays.asList(R.id.zeroDigitButton, R.id.oneDigitButton);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
oct(NumeralBase.oct) {
|
oct(NumeralBase.oct) {
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public List<Integer> getButtonIds() {
|
public List<Integer> getButtonIds() {
|
||||||
final List<Integer> result = new ArrayList<Integer>(bin.getButtonIds());
|
final List<Integer> result = new ArrayList<Integer>(bin.getButtonIds());
|
||||||
result.addAll(Arrays.asList(R.id.twoDigitButton, R.id.threeDigitButton, R.id.fourDigitButton, R.id.fiveDigitButton, R.id.sixDigitButton, R.id.sevenDigitButton));
|
result.addAll(Arrays.asList(R.id.twoDigitButton, R.id.threeDigitButton, R.id.fourDigitButton, R.id.fiveDigitButton, R.id.sixDigitButton, R.id.sevenDigitButton));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
dec(NumeralBase.dec) {
|
dec(NumeralBase.dec) {
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public List<Integer> getButtonIds() {
|
public List<Integer> getButtonIds() {
|
||||||
final List<Integer> result = new ArrayList<Integer>(oct.getButtonIds());
|
final List<Integer> result = new ArrayList<Integer>(oct.getButtonIds());
|
||||||
result.addAll(Arrays.asList(R.id.eightDigitButton, R.id.nineDigitButton));
|
result.addAll(Arrays.asList(R.id.eightDigitButton, R.id.nineDigitButton));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
hex(NumeralBase.hex) {
|
hex(NumeralBase.hex) {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private List<Integer> specialHexButtonIds = Arrays.asList(R.id.oneDigitButton, R.id.twoDigitButton, R.id.threeDigitButton, R.id.fourDigitButton, R.id.fiveDigitButton, R.id.sixDigitButton);
|
private List<Integer> specialHexButtonIds = Arrays.asList(R.id.oneDigitButton, R.id.twoDigitButton, R.id.threeDigitButton, R.id.fourDigitButton, R.id.fiveDigitButton, R.id.sixDigitButton);
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public List<Integer> getButtonIds() {
|
public List<Integer> getButtonIds() {
|
||||||
return dec.getButtonIds();
|
return dec.getButtonIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void toggleButton(boolean show, @NotNull DirectionDragButton button) {
|
protected void toggleButton(boolean show, @NotNull DirectionDragButton button) {
|
||||||
super.toggleButton(show, button);
|
super.toggleButton(show, button);
|
||||||
if (specialHexButtonIds.contains(button.getId())) {
|
if (specialHexButtonIds.contains(button.getId())) {
|
||||||
button.showDirectionText(show, DragDirection.left);
|
button.showDirectionText(show, DragDirection.left);
|
||||||
button.invalidate();
|
button.invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final NumeralBase numeralBase;
|
private final NumeralBase numeralBase;
|
||||||
|
|
||||||
private AndroidNumeralBase(@NotNull NumeralBase numeralBase) {
|
private AndroidNumeralBase(@NotNull NumeralBase numeralBase) {
|
||||||
this.numeralBase = numeralBase;
|
this.numeralBase = numeralBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Unit<String> createUnit(@NotNull String value) {
|
public Unit<String> createUnit(@NotNull String value) {
|
||||||
return UnitImpl.newInstance(value, this);
|
return UnitImpl.newInstance(value, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public abstract List<Integer> getButtonIds();
|
public abstract List<Integer> getButtonIds();
|
||||||
|
|
||||||
public void toggleButtons(boolean show, @NotNull Activity activity) {
|
public void toggleButtons(boolean show, @NotNull Activity activity) {
|
||||||
for (Integer buttonId : getButtonIds()) {
|
for (Integer buttonId : getButtonIds()) {
|
||||||
final DirectionDragButton button = (DirectionDragButton) activity.findViewById(buttonId);
|
final DirectionDragButton button = (DirectionDragButton) activity.findViewById(buttonId);
|
||||||
if (button != null) {
|
if (button != null) {
|
||||||
toggleButton(show, button);
|
toggleButton(show, button);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void toggleButton(boolean show, @NotNull DirectionDragButton button) {
|
protected void toggleButton(boolean show, @NotNull DirectionDragButton button) {
|
||||||
button.setShowText(show);
|
button.setShowText(show);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public NumeralBase getNumeralBase() {
|
public NumeralBase getNumeralBase() {
|
||||||
return numeralBase;
|
return numeralBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Class<String> getUnitValueClass() {
|
public Class<String> getUnitValueClass() {
|
||||||
return String.class;
|
return String.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static final Converter converter = new Converter();
|
private static final Converter converter = new Converter();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Converter getConverter() {
|
public static Converter getConverter() {
|
||||||
return converter;
|
return converter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Converter implements UnitConverter<String> {
|
public static class Converter implements UnitConverter<String> {
|
||||||
|
|
||||||
private Converter() {
|
private Converter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSupported(@NotNull UnitType<?> from, @NotNull UnitType<String> to) {
|
public boolean isSupported(@NotNull UnitType<?> from, @NotNull UnitType<String> to) {
|
||||||
return AndroidNumeralBase.class.isAssignableFrom(from.getClass()) && AndroidNumeralBase.class.isAssignableFrom(to.getClass());
|
return AndroidNumeralBase.class.isAssignableFrom(from.getClass()) && AndroidNumeralBase.class.isAssignableFrom(to.getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Unit<String> convert(@NotNull Unit<?> from, @NotNull UnitType<String> toType) {
|
public Unit<String> convert(@NotNull Unit<?> from, @NotNull UnitType<String> toType) {
|
||||||
if (!isSupported(from.getUnitType(), toType)) {
|
if (!isSupported(from.getUnitType(), toType)) {
|
||||||
throw new IllegalArgumentException("Types are not supported!");
|
throw new IllegalArgumentException("Types are not supported!");
|
||||||
}
|
}
|
||||||
|
|
||||||
final AndroidNumeralBase fromTypeAndroid = (AndroidNumeralBase) from.getUnitType();
|
final AndroidNumeralBase fromTypeAndroid = (AndroidNumeralBase) from.getUnitType();
|
||||||
final NumeralBase fromNumeralBase = fromTypeAndroid.numeralBase;
|
final NumeralBase fromNumeralBase = fromTypeAndroid.numeralBase;
|
||||||
final NumeralBase toNumeralBase = ((AndroidNumeralBase) toType).numeralBase;
|
final NumeralBase toNumeralBase = ((AndroidNumeralBase) toType).numeralBase;
|
||||||
final String fromValue = (String) from.getValue();
|
final String fromValue = (String) from.getValue();
|
||||||
|
|
||||||
final BigInteger decBigInteger = fromNumeralBase.toBigInteger(fromValue);
|
final BigInteger decBigInteger = fromNumeralBase.toBigInteger(fromValue);
|
||||||
return UnitImpl.newInstance(toNumeralBase.toString(decBigInteger), (AndroidNumeralBase) toType);
|
return UnitImpl.newInstance(toNumeralBase.toString(decBigInteger), (AndroidNumeralBase) toType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static AndroidNumeralBase valueOf(@NotNull NumeralBase nb) {
|
public static AndroidNumeralBase valueOf(@NotNull NumeralBase nb) {
|
||||||
for (AndroidNumeralBase androidNumeralBase : values()) {
|
for (AndroidNumeralBase androidNumeralBase : values()) {
|
||||||
if (androidNumeralBase.numeralBase == nb) {
|
if (androidNumeralBase.numeralBase == nb) {
|
||||||
return androidNumeralBase;
|
return androidNumeralBase;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalArgumentException(nb + " is not supported numeral base!");
|
throw new IllegalArgumentException(nb + " is not supported numeral base!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -1,92 +1,94 @@
|
|||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
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.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.text.method.LinkMovementMethod;
|
import android.text.method.LinkMovementMethod;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import net.robotmedia.billing.BillingController;
|
import net.robotmedia.billing.BillingController;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.ads.AdsController;
|
import org.solovyev.android.ads.AdsController;
|
||||||
import org.solovyev.android.calculator.model.CalculatorEngine;
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 12/1/11
|
* Date: 12/1/11
|
||||||
* Time: 1:21 PM
|
* Time: 1:21 PM
|
||||||
*/
|
*/
|
||||||
public class CalculatorApplication extends android.app.Application {
|
public class CalculatorApplication extends android.app.Application {
|
||||||
|
|
||||||
private static final String paypalDonateUrl = "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=se%2esolovyev%40gmail%2ecom&lc=RU&item_name=Android%20Calculator¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted";
|
private static final String paypalDonateUrl = "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=se%2esolovyev%40gmail%2ecom&lc=RU&item_name=Android%20Calculator¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted";
|
||||||
|
|
||||||
public static final String AD_FREE_PRODUCT_ID = "ad_free";
|
public static final String AD_FREE_PRODUCT_ID = "ad_free";
|
||||||
public static final String AD_FREE_P_KEY = "org.solovyev.android.calculator_ad_free";
|
public static final String AD_FREE_P_KEY = "org.solovyev.android.calculator_ad_free";
|
||||||
|
|
||||||
public static final String ADMOB_USER_ID = "a14f02cf9c80cbc";
|
public static final String ADMOB_USER_ID = "a14f02cf9c80cbc";
|
||||||
public static final String REMOTE_STACK_TRACE_URL = "http://calculatorpp.com/crash_reports/upload.php";
|
public static final String REMOTE_STACK_TRACE_URL = "http://calculatorpp.com/crash_reports/upload.php";
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static CalculatorApplication instance;
|
private static CalculatorApplication instance;
|
||||||
|
|
||||||
public CalculatorApplication() {
|
public CalculatorApplication() {
|
||||||
instance = this;
|
instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static CalculatorApplication getInstance() {
|
public static CalculatorApplication getInstance() {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
AdsController.getInstance().init(ADMOB_USER_ID, AD_FREE_PRODUCT_ID, new BillingController.IConfiguration() {
|
CalculatorLocatorImpl.getInstance().setCalculatorEngine(CalculatorEngine.instance);
|
||||||
|
|
||||||
@Override
|
AdsController.getInstance().init(ADMOB_USER_ID, AD_FREE_PRODUCT_ID, new BillingController.IConfiguration() {
|
||||||
public byte[] getObfuscationSalt() {
|
|
||||||
return new byte[]{81, -114, 32, -127, -32, -104, -40, -15, -47, 57, -13, -41, -33, 67, -114, 7, -11, 53, 126, 82};
|
@Override
|
||||||
}
|
public byte[] getObfuscationSalt() {
|
||||||
|
return new byte[]{81, -114, 32, -127, -32, -104, -40, -15, -47, 57, -13, -41, -33, 67, -114, 7, -11, 53, 126, 82};
|
||||||
@Override
|
}
|
||||||
public String getPublicKey() {
|
|
||||||
return CalculatorSecurity.getPK();
|
@Override
|
||||||
}
|
public String getPublicKey() {
|
||||||
});
|
return CalculatorSecurity.getPK();
|
||||||
|
}
|
||||||
CalculatorEngine.instance.init(this, PreferenceManager.getDefaultSharedPreferences(this));
|
});
|
||||||
|
|
||||||
}
|
CalculatorEngine.instance.init(this, PreferenceManager.getDefaultSharedPreferences(this));
|
||||||
|
|
||||||
public static void showDonationDialog(@NotNull final Context context) {
|
}
|
||||||
final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
|
|
||||||
final View view = layoutInflater.inflate(R.layout.donate, null);
|
public static void showDonationDialog(@NotNull final Context context) {
|
||||||
|
final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
|
||||||
final TextView donate = (TextView) view.findViewById(R.id.donateText);
|
final View view = layoutInflater.inflate(R.layout.donate, null);
|
||||||
donate.setMovementMethod(LinkMovementMethod.getInstance());
|
|
||||||
|
final TextView donate = (TextView) view.findViewById(R.id.donateText);
|
||||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context)
|
donate.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
.setCancelable(true)
|
|
||||||
.setNegativeButton(R.string.c_cancel, null)
|
final AlertDialog.Builder builder = new AlertDialog.Builder(context)
|
||||||
.setPositiveButton(R.string.c_donate, new DialogInterface.OnClickListener() {
|
.setCancelable(true)
|
||||||
@Override
|
.setNegativeButton(R.string.c_cancel, null)
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
.setPositiveButton(R.string.c_donate, new DialogInterface.OnClickListener() {
|
||||||
final Intent i = new Intent(Intent.ACTION_VIEW);
|
@Override
|
||||||
i.setData(Uri.parse(paypalDonateUrl));
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
context.startActivity(i);
|
final Intent i = new Intent(Intent.ACTION_VIEW);
|
||||||
}
|
i.setData(Uri.parse(paypalDonateUrl));
|
||||||
})
|
context.startActivity(i);
|
||||||
.setView(view);
|
}
|
||||||
|
})
|
||||||
builder.create().show();
|
.setView(view);
|
||||||
}
|
|
||||||
|
builder.create().show();
|
||||||
public static void registerOnRemoteStackTrace() {
|
}
|
||||||
//Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(null, REMOTE_STACK_TRACE_URL));
|
|
||||||
}
|
public static void registerOnRemoteStackTrace() {
|
||||||
}
|
//Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(null, REMOTE_STACK_TRACE_URL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,348 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
|
||||||
* For more information, please, contact se.solovyev@gmail.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.solovyev.android.calculator;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.text.Html;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.util.Log;
|
|
||||||
import jscl.NumeralBase;
|
|
||||||
import jscl.math.Generic;
|
|
||||||
import jscl.math.function.Constant;
|
|
||||||
import jscl.math.function.IConstant;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
|
||||||
import org.solovyev.android.calculator.model.CalculatorEngine;
|
|
||||||
import org.solovyev.android.calculator.model.CalculatorParseException;
|
|
||||||
import org.solovyev.android.calculator.model.TextProcessor;
|
|
||||||
import org.solovyev.android.calculator.model.ToJsclTextProcessor;
|
|
||||||
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
|
|
||||||
import org.solovyev.android.calculator.view.TextHighlighter;
|
|
||||||
import org.solovyev.android.calculator.view.UnitConverterViewBuilder;
|
|
||||||
import org.solovyev.android.menu.AMenuItem;
|
|
||||||
import org.solovyev.android.menu.LabeledMenuItem;
|
|
||||||
import org.solovyev.android.view.AutoResizeTextView;
|
|
||||||
import org.solovyev.common.collections.CollectionsUtils;
|
|
||||||
import org.solovyev.common.text.StringUtils;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User: serso
|
|
||||||
* Date: 9/17/11
|
|
||||||
* Time: 10:58 PM
|
|
||||||
*/
|
|
||||||
public class CalculatorDisplay extends AutoResizeTextView implements ICalculatorDisplay{
|
|
||||||
|
|
||||||
private static enum ConversionMenuItem implements AMenuItem<CalculatorDisplay> {
|
|
||||||
convert_to_bin(NumeralBase.bin),
|
|
||||||
convert_to_dec(NumeralBase.dec),
|
|
||||||
convert_to_hex(NumeralBase.hex);
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final NumeralBase toNumeralBase;
|
|
||||||
|
|
||||||
private ConversionMenuItem(@NotNull NumeralBase toNumeralBase) {
|
|
||||||
this.toNumeralBase = toNumeralBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
|
||||||
boolean result = false;
|
|
||||||
|
|
||||||
if (operation == JsclOperation.numeric) {
|
|
||||||
if (generic.getConstants().isEmpty()) {
|
|
||||||
try {
|
|
||||||
convert(generic);
|
|
||||||
|
|
||||||
// conversion possible => return true
|
|
||||||
result = true;
|
|
||||||
|
|
||||||
} catch (UnitConverterViewBuilder.ConversionException e) {
|
|
||||||
// conversion is not possible => return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) {
|
|
||||||
final NumeralBase fromNumeralBase = CalculatorEngine.instance.getEngine().getNumeralBase();
|
|
||||||
|
|
||||||
String to;
|
|
||||||
try {
|
|
||||||
to = convert(data.getGenericResult());
|
|
||||||
|
|
||||||
// add prefix
|
|
||||||
if (fromNumeralBase != toNumeralBase) {
|
|
||||||
to = toNumeralBase.getJsclPrefix() + to;
|
|
||||||
}
|
|
||||||
} catch (UnitConverterViewBuilder.ConversionException e) {
|
|
||||||
to = context.getString(R.string.c_error);
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setText(to);
|
|
||||||
data.redraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private String convert(@NotNull Generic generic) throws UnitConverterViewBuilder.ConversionException {
|
|
||||||
final NumeralBase fromNumeralBase = CalculatorEngine.instance.getEngine().getNumeralBase();
|
|
||||||
|
|
||||||
if (fromNumeralBase != toNumeralBase) {
|
|
||||||
String from = generic.toString();
|
|
||||||
if (!StringUtils.isEmpty(from)) {
|
|
||||||
try {
|
|
||||||
from = ToJsclTextProcessor.getInstance().process(from).getExpression();
|
|
||||||
} catch (CalculatorParseException e) {
|
|
||||||
// ok, problems while processing occurred
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return UnitConverterViewBuilder.doConversion(AndroidNumeralBase.getConverter(), from, AndroidNumeralBase.valueOf(fromNumeralBase), AndroidNumeralBase.valueOf(toNumeralBase));
|
|
||||||
} else {
|
|
||||||
return generic.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum MenuItem implements LabeledMenuItem<CalculatorDisplay> {
|
|
||||||
|
|
||||||
copy(R.string.c_copy) {
|
|
||||||
@Override
|
|
||||||
public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) {
|
|
||||||
CalculatorModel.copyResult(context, data);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
convert_to_bin(R.string.convert_to_bin) {
|
|
||||||
@Override
|
|
||||||
public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) {
|
|
||||||
ConversionMenuItem.convert_to_bin.onClick(data, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
|
||||||
return ConversionMenuItem.convert_to_bin.isItemVisibleFor(generic, operation);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
convert_to_dec(R.string.convert_to_dec) {
|
|
||||||
@Override
|
|
||||||
public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) {
|
|
||||||
ConversionMenuItem.convert_to_dec.onClick(data, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
|
||||||
return ConversionMenuItem.convert_to_dec.isItemVisibleFor(generic, operation);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
convert_to_hex(R.string.convert_to_hex) {
|
|
||||||
@Override
|
|
||||||
public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) {
|
|
||||||
ConversionMenuItem.convert_to_hex.onClick(data, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
|
||||||
return ConversionMenuItem.convert_to_hex.isItemVisibleFor(generic, operation);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
convert(R.string.c_convert) {
|
|
||||||
@Override
|
|
||||||
public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) {
|
|
||||||
new NumeralBaseConverterDialog(data.getGenericResult().toString()).show(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
|
||||||
return operation == JsclOperation.numeric && generic.getConstants().isEmpty();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
plot(R.string.c_plot) {
|
|
||||||
@Override
|
|
||||||
public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) {
|
|
||||||
final Generic generic = data.getGenericResult();
|
|
||||||
assert generic != null;
|
|
||||||
|
|
||||||
final Constant constant = CollectionsUtils.getFirstCollectionElement(getNotSystemConstants(generic));
|
|
||||||
assert constant != null;
|
|
||||||
CalculatorActivityLauncher.plotGraph(context, generic, constant);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
|
||||||
boolean result = false;
|
|
||||||
|
|
||||||
if (operation == JsclOperation.simplify) {
|
|
||||||
if (getNotSystemConstants(generic).size() == 1) {
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private Set<Constant> getNotSystemConstants(@NotNull Generic generic) {
|
|
||||||
final Set<Constant> notSystemConstants = new HashSet<Constant>();
|
|
||||||
|
|
||||||
for (Constant constant : generic.getConstants()) {
|
|
||||||
IConstant var = CalculatorEngine.instance.getVarsRegistry().get(constant.getName());
|
|
||||||
if (var != null && !var.isSystem() && !var.isDefined()) {
|
|
||||||
notSystemConstants.add(constant);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return notSystemConstants;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final int captionId;
|
|
||||||
|
|
||||||
MenuItem(int captionId) {
|
|
||||||
this.captionId = captionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean isItemVisible(@NotNull CalculatorDisplay display) {
|
|
||||||
//noinspection ConstantConditions
|
|
||||||
return display.isValid() && display.getGenericResult() != null && isItemVisibleFor(display.getGenericResult(), display.getJsclOperation());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public String getCaption(@NotNull Context context) {
|
|
||||||
return context.getString(captionId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean valid = true;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private String errorMessage;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private JsclOperation jsclOperation = JsclOperation.numeric;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine());
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private Generic genericResult;
|
|
||||||
|
|
||||||
public CalculatorDisplay(Context context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CalculatorDisplay(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CalculatorDisplay(Context context, AttributeSet attrs, int defStyle) {
|
|
||||||
super(context, attrs, defStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isValid() {
|
|
||||||
return valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setValid(boolean valid) {
|
|
||||||
this.valid = valid;
|
|
||||||
if (valid) {
|
|
||||||
errorMessage = null;
|
|
||||||
setTextColor(getResources().getColor(R.color.default_text_color));
|
|
||||||
} else {
|
|
||||||
setTextColor(getResources().getColor(R.color.display_error_text_color));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public String getErrorMessage() {
|
|
||||||
return errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setErrorMessage(@Nullable String errorMessage) {
|
|
||||||
this.errorMessage = errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setJsclOperation(@NotNull JsclOperation jsclOperation) {
|
|
||||||
this.jsclOperation = jsclOperation;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@NotNull
|
|
||||||
public JsclOperation getJsclOperation() {
|
|
||||||
return jsclOperation;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setText(CharSequence text, BufferType type) {
|
|
||||||
super.setText(text, type);
|
|
||||||
|
|
||||||
setValid(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void redraw() {
|
|
||||||
if (isValid()) {
|
|
||||||
String text = getText().toString();
|
|
||||||
|
|
||||||
Log.d(this.getClass().getName(), text);
|
|
||||||
|
|
||||||
try {
|
|
||||||
TextHighlighter.Result result = textHighlighter.process(text);
|
|
||||||
text = result.toString();
|
|
||||||
} catch (CalculatorParseException e) {
|
|
||||||
Log.e(this.getClass().getName(), e.getMessage(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.d(this.getClass().getName(), text);
|
|
||||||
super.setText(Html.fromHtml(text), BufferType.EDITABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo serso: think where to move it (keep in mind org.solovyev.android.view.AutoResizeTextView.resetTextSize())
|
|
||||||
setAddEllipsis(false);
|
|
||||||
setMinTextSize(10);
|
|
||||||
resizeText();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setGenericResult(@Nullable Generic genericResult) {
|
|
||||||
this.genericResult = genericResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public Generic getGenericResult() {
|
|
||||||
return genericResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSelection() {
|
|
||||||
return this.getSelectionStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSelection(int selection) {
|
|
||||||
// not supported by TextView
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,166 +1,165 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
* For more information, please, contact se.solovyev@gmail.com
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.ContextMenu;
|
import android.view.ContextMenu;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.calculator.model.CalculatorEngine;
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
import org.solovyev.android.calculator.model.CalculatorParseException;
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
import org.solovyev.android.calculator.model.TextProcessor;
|
import org.solovyev.android.calculator.view.TextHighlighter;
|
||||||
import org.solovyev.android.calculator.view.TextHighlighter;
|
import org.solovyev.common.collections.CollectionsUtils;
|
||||||
import org.solovyev.common.collections.CollectionsUtils;
|
|
||||||
|
/**
|
||||||
/**
|
* User: serso
|
||||||
* User: serso
|
* Date: 9/17/11
|
||||||
* Date: 9/17/11
|
* Time: 12:25 AM
|
||||||
* Time: 12:25 AM
|
*/
|
||||||
*/
|
public class CalculatorEditor extends EditText implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
public class CalculatorEditor extends EditText implements SharedPreferences.OnSharedPreferenceChangeListener {
|
|
||||||
|
private static final String CALC_COLOR_DISPLAY_KEY = "org.solovyev.android.calculator.CalculatorModel_color_display";
|
||||||
private static final String CALC_COLOR_DISPLAY_KEY = "org.solovyev.android.calculator.CalculatorModel_color_display";
|
private static final boolean CALC_COLOR_DISPLAY_DEFAULT = true;
|
||||||
private static final boolean CALC_COLOR_DISPLAY_DEFAULT = true;
|
|
||||||
|
private boolean highlightText = true;
|
||||||
private boolean highlightText = true;
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, true, CalculatorEngine.instance.getEngine());
|
||||||
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, true, CalculatorEngine.instance.getEngine());
|
|
||||||
|
public CalculatorEditor(Context context) {
|
||||||
public CalculatorEditor(Context context) {
|
super(context);
|
||||||
super(context);
|
init();
|
||||||
init();
|
}
|
||||||
}
|
|
||||||
|
public CalculatorEditor(Context context, AttributeSet attrs) {
|
||||||
public CalculatorEditor(Context context, AttributeSet attrs) {
|
super(context, attrs);
|
||||||
super(context, attrs);
|
init();
|
||||||
init();
|
}
|
||||||
}
|
|
||||||
|
private void init() {
|
||||||
private void init() {
|
// NOTE: in this solution cursor is missing
|
||||||
// NOTE: in this solution cursor is missing
|
|
||||||
|
/*this.setOnTouchListener(new OnTouchListener() {
|
||||||
/*this.setOnTouchListener(new OnTouchListener() {
|
@Override
|
||||||
@Override
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
public boolean onTouch(View v, MotionEvent event) {
|
final TextView textView = (TextView)v;
|
||||||
final TextView textView = (TextView)v;
|
// backup the input type
|
||||||
// backup the input type
|
int inputType = textView.getInputType();
|
||||||
int inputType = textView.getInputType();
|
|
||||||
|
// disable soft input
|
||||||
// disable soft input
|
textView.setInputType(InputType.TYPE_NULL);
|
||||||
textView.setInputType(InputType.TYPE_NULL);
|
|
||||||
|
// call native handler
|
||||||
// call native handler
|
textView.onTouchEvent(event);
|
||||||
textView.onTouchEvent(event);
|
|
||||||
|
// restore input type
|
||||||
// restore input type
|
textView.setInputType(inputType);
|
||||||
textView.setInputType(inputType);
|
|
||||||
|
// consume touch even
|
||||||
// consume touch even
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
});*/
|
||||||
});*/
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
@Override
|
public boolean onCheckIsTextEditor() {
|
||||||
public boolean onCheckIsTextEditor() {
|
// NOTE: code below can be used carefully and should not be copied without special intention
|
||||||
// NOTE: code below can be used carefully and should not be copied without special intention
|
// The main purpose of code is to disable soft input (virtual keyboard) but leave all the TextEdit functionality, like cursor, scrolling, copy/paste menu etc
|
||||||
// The main purpose of code is to disable soft input (virtual keyboard) but leave all the TextEdit functionality, like cursor, scrolling, copy/paste menu etc
|
|
||||||
|
if ( Build.VERSION.SDK_INT >= 11 ) {
|
||||||
if ( Build.VERSION.SDK_INT >= 11 ) {
|
// fix for missing cursor in android 3 and higher
|
||||||
// fix for missing cursor in android 3 and higher
|
try {
|
||||||
try {
|
// IDEA: return false always except if method was called from TextView.isCursorVisible() method
|
||||||
// IDEA: return false always except if method was called from TextView.isCursorVisible() method
|
for (StackTraceElement stackTraceElement : CollectionsUtils.asList(Thread.currentThread().getStackTrace())) {
|
||||||
for (StackTraceElement stackTraceElement : CollectionsUtils.asList(Thread.currentThread().getStackTrace())) {
|
if ( "isCursorVisible".equals(stackTraceElement.getMethodName()) ) {
|
||||||
if ( "isCursorVisible".equals(stackTraceElement.getMethodName()) ) {
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
}
|
} catch (RuntimeException e) {
|
||||||
} catch (RuntimeException e) {
|
// just in case...
|
||||||
// just in case...
|
}
|
||||||
}
|
|
||||||
|
return false;
|
||||||
return false;
|
} else {
|
||||||
} else {
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public CalculatorEditor(Context context, AttributeSet attrs, int defStyle) {
|
||||||
public CalculatorEditor(Context context, AttributeSet attrs, int defStyle) {
|
super(context, attrs, defStyle);
|
||||||
super(context, attrs, defStyle);
|
init();
|
||||||
init();
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
@Override
|
protected void onCreateContextMenu(ContextMenu menu) {
|
||||||
protected void onCreateContextMenu(ContextMenu menu) {
|
super.onCreateContextMenu(menu);
|
||||||
super.onCreateContextMenu(menu);
|
|
||||||
|
menu.removeItem(android.R.id.selectAll);
|
||||||
menu.removeItem(android.R.id.selectAll);
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
@Override
|
public void setText(CharSequence text, BufferType type) {
|
||||||
public void setText(CharSequence text, BufferType type) {
|
super.setText(text, type);
|
||||||
super.setText(text, type);
|
}
|
||||||
}
|
|
||||||
|
public synchronized void redraw() {
|
||||||
public synchronized void redraw() {
|
String text = getText().toString();
|
||||||
String text = getText().toString();
|
|
||||||
|
int selectionStart = getSelectionStart();
|
||||||
int selectionStart = getSelectionStart();
|
int selectionEnd = getSelectionEnd();
|
||||||
int selectionEnd = getSelectionEnd();
|
|
||||||
|
if (highlightText) {
|
||||||
if (highlightText) {
|
|
||||||
|
Log.d(this.getClass().getName(), text);
|
||||||
Log.d(this.getClass().getName(), text);
|
|
||||||
|
try {
|
||||||
try {
|
final TextHighlighter.Result result = textHighlighter.process(text);
|
||||||
final TextHighlighter.Result result = textHighlighter.process(text);
|
selectionStart += result.getOffset();
|
||||||
selectionStart += result.getOffset();
|
selectionEnd += result.getOffset();
|
||||||
selectionEnd += result.getOffset();
|
text = result.toString();
|
||||||
text = result.toString();
|
} catch (CalculatorParseException e) {
|
||||||
} catch (CalculatorParseException e) {
|
Log.e(this.getClass().getName(), e.getMessage(), e);
|
||||||
Log.e(this.getClass().getName(), e.getMessage(), e);
|
}
|
||||||
}
|
|
||||||
|
Log.d(this.getClass().getName(), text);
|
||||||
Log.d(this.getClass().getName(), text);
|
super.setText(Html.fromHtml(text), BufferType.EDITABLE);
|
||||||
super.setText(Html.fromHtml(text), BufferType.EDITABLE);
|
} else {
|
||||||
} else {
|
super.setText(text, BufferType.EDITABLE);
|
||||||
super.setText(text, BufferType.EDITABLE);
|
}
|
||||||
}
|
|
||||||
|
Log.d(this.getClass().getName(), getText().toString());
|
||||||
Log.d(this.getClass().getName(), getText().toString());
|
|
||||||
|
int length = getText().length();
|
||||||
int length = getText().length();
|
setSelection(Math.max(Math.min(length, selectionStart), 0), Math.max(Math.min(length, selectionEnd), 0));
|
||||||
setSelection(Math.max(Math.min(length, selectionStart), 0), Math.max(Math.min(length, selectionEnd), 0));
|
}
|
||||||
}
|
|
||||||
|
public boolean isHighlightText() {
|
||||||
public boolean isHighlightText() {
|
return highlightText;
|
||||||
return highlightText;
|
}
|
||||||
}
|
|
||||||
|
public void setHighlightText(boolean highlightText) {
|
||||||
public void setHighlightText(boolean highlightText) {
|
this.highlightText = highlightText;
|
||||||
this.highlightText = highlightText;
|
redraw();
|
||||||
redraw();
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
@Override
|
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
if (CALC_COLOR_DISPLAY_KEY.equals(key)) {
|
||||||
if (CALC_COLOR_DISPLAY_KEY.equals(key)) {
|
this.setHighlightText(preferences.getBoolean(CALC_COLOR_DISPLAY_KEY, CALC_COLOR_DISPLAY_DEFAULT));
|
||||||
this.setHighlightText(preferences.getBoolean(CALC_COLOR_DISPLAY_KEY, CALC_COLOR_DISPLAY_DEFAULT));
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public void init(@NotNull SharedPreferences preferences) {
|
||||||
public void init(@NotNull SharedPreferences preferences) {
|
onSharedPreferenceChanged(preferences, CALC_COLOR_DISPLAY_KEY);
|
||||||
onSharedPreferenceChanged(preferences, CALC_COLOR_DISPLAY_KEY);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -20,14 +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.calculator.model.CalculatorParseException;
|
|
||||||
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;
|
||||||
@ -55,7 +53,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
private CalculatorEditor editor;
|
private CalculatorEditor editor;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private CalculatorDisplay display;
|
private AndroidCalculatorDisplayView display;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private CalculatorEngine calculatorEngine;
|
private CalculatorEngine calculatorEngine;
|
||||||
@ -68,10 +66,10 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
this.editor.init(preferences);
|
this.editor.init(preferences);
|
||||||
preferences.registerOnSharedPreferenceChangeListener(editor);
|
preferences.registerOnSharedPreferenceChangeListener(editor);
|
||||||
|
|
||||||
this.display = (CalculatorDisplay) activity.findViewById(R.id.calculatorDisplay);
|
this.display = (AndroidCalculatorDisplayView) activity.findViewById(R.id.calculatorDisplay);
|
||||||
this.display.setOnClickListener(new CalculatorDisplayOnClickListener(activity));
|
this.display.setOnClickListener(new CalculatorDisplayOnClickListener(activity));
|
||||||
|
|
||||||
final CalculatorHistoryState lastState = CalculatorHistory.instance.getLastHistoryState();
|
final CalculatorHistoryState lastState = AndroidCalculatorHistoryImpl.instance.getLastHistoryState();
|
||||||
if (lastState == null) {
|
if (lastState == null) {
|
||||||
saveHistoryState();
|
saveHistoryState();
|
||||||
} else {
|
} else {
|
||||||
@ -99,9 +97,9 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
copyResult(context, display);
|
copyResult(context, display);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void copyResult(@NotNull Context context, @NotNull final CalculatorDisplay display) {
|
public static void copyResult(@NotNull Context context, @NotNull final CalculatorDisplayViewState viewState) {
|
||||||
if (display.isValid()) {
|
if (viewState.isValid()) {
|
||||||
final CharSequence text = display.getText();
|
final CharSequence text = viewState.getText();
|
||||||
if (!StringUtils.isEmpty(text)) {
|
if (!StringUtils.isEmpty(text)) {
|
||||||
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
|
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
|
||||||
clipboard.setText(text.toString());
|
clipboard.setText(text.toString());
|
||||||
@ -111,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() {
|
||||||
@ -197,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,16 +228,16 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
if (!StringUtils.isEmpty(expression)) {
|
if (!StringUtils.isEmpty(expression)) {
|
||||||
try {
|
try {
|
||||||
Log.d(CalculatorModel.class.getName(), "Trying to evaluate '" + operation + "': " + expression /*+ StringUtils.fromStackTrace(Thread.currentThread().getStackTrace())*/);
|
Log.d(CalculatorModel.class.getName(), "Trying to evaluate '" + operation + "': " + expression /*+ StringUtils.fromStackTrace(Thread.currentThread().getStackTrace())*/);
|
||||||
final CalculatorEngine.Result result = calculatorEngine.evaluate(operation, expression);
|
final CalculatorOutput result = calculatorEngine.evaluate(operation, expression);
|
||||||
|
|
||||||
// todo serso: second condition might replaced with expression.equals(this.editor.getText().toString()) ONLY if expression will be formatted with text highlighter
|
// todo serso: second condition might replaced with expression.equals(this.editor.getText().toString()) ONLY if expression will be formatted with text highlighter
|
||||||
if (currentRunner == pendingOperation.getObject() && this.editor.getText().length() > 0) {
|
if (currentRunner == pendingOperation.getObject() && this.editor.getText().length() > 0) {
|
||||||
display.setText(result.getResult());
|
display.setText(result.getStringResult());
|
||||||
} else {
|
} else {
|
||||||
display.setText("");
|
display.setText("");
|
||||||
}
|
}
|
||||||
display.setJsclOperation(result.getUserOperation());
|
display.setJsclOperation(result.getOperation());
|
||||||
display.setGenericResult(result.getGenericResult());
|
display.setGenericResult(result.getResult());
|
||||||
} catch (CalculatorParseException e) {
|
} catch (CalculatorParseException e) {
|
||||||
handleEvaluationException(expression, display, operation, e);
|
handleEvaluationException(expression, display, operation, e);
|
||||||
} catch (CalculatorEvalException e) {
|
} catch (CalculatorEvalException e) {
|
||||||
@ -257,7 +255,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleEvaluationException(@NotNull String expression,
|
private void handleEvaluationException(@NotNull String expression,
|
||||||
@NotNull CalculatorDisplay localDisplay,
|
@NotNull AndroidCalculatorDisplayView localDisplay,
|
||||||
@NotNull JsclOperation operation,
|
@NotNull JsclOperation operation,
|
||||||
@NotNull Message e) {
|
@NotNull Message e) {
|
||||||
Log.d(CalculatorModel.class.getName(), "Evaluation failed for : " + expression + ". Error message: " + e);
|
Log.d(CalculatorModel.class.getName(), "Evaluation failed for : " + expression + ". Error message: " + e);
|
||||||
@ -331,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);
|
||||||
}
|
}
|
||||||
@ -343,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);
|
||||||
@ -363,13 +361,13 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public CalculatorDisplay getDisplay() {
|
public AndroidCalculatorDisplayView getDisplay() {
|
||||||
return display;
|
return display;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,13 +382,15 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (v instanceof CalculatorDisplay) {
|
if (v instanceof CalculatorDisplayView) {
|
||||||
final CalculatorDisplay cd = (CalculatorDisplay) v;
|
final CalculatorDisplay cd = CalculatorLocatorImpl.getInstance().getCalculatorDisplay();
|
||||||
|
|
||||||
if (cd.isValid()) {
|
final CalculatorDisplayViewState displayViewState = cd.getViewState();
|
||||||
final List<CalculatorDisplay.MenuItem> filteredMenuItems = new ArrayList<CalculatorDisplay.MenuItem>(CalculatorDisplay.MenuItem.values().length);
|
|
||||||
for (CalculatorDisplay.MenuItem menuItem : CalculatorDisplay.MenuItem.values()) {
|
if (displayViewState.isValid()) {
|
||||||
if (menuItem.isItemVisible(cd)) {
|
final List<AndroidCalculatorDisplayView.MenuItem> filteredMenuItems = new ArrayList<AndroidCalculatorDisplayView.MenuItem>(AndroidCalculatorDisplayView.MenuItem.values().length);
|
||||||
|
for (AndroidCalculatorDisplayView.MenuItem menuItem : AndroidCalculatorDisplayView.MenuItem.values()) {
|
||||||
|
if (menuItem.isItemVisible(displayViewState)) {
|
||||||
filteredMenuItems.add(menuItem);
|
filteredMenuItems.add(menuItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -400,7 +400,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
final String errorMessage = cd.getErrorMessage();
|
final String errorMessage = displayViewState.getErrorMessage();
|
||||||
if (errorMessage != null) {
|
if (errorMessage != null) {
|
||||||
showEvaluationError(activity, errorMessage);
|
showEvaluationError(activity, errorMessage);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import jscl.NumeralBase;
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
|
import org.solovyev.android.menu.AMenuItem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/21/12
|
||||||
|
* Time: 12:11 AM
|
||||||
|
*/
|
||||||
|
enum ConversionMenuItem implements AMenuItem<CalculatorDisplayViewState> {
|
||||||
|
|
||||||
|
convert_to_bin(NumeralBase.bin),
|
||||||
|
convert_to_dec(NumeralBase.dec),
|
||||||
|
convert_to_hex(NumeralBase.hex);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final NumeralBase toNumeralBase;
|
||||||
|
|
||||||
|
ConversionMenuItem(@NotNull NumeralBase toNumeralBase) {
|
||||||
|
this.toNumeralBase = toNumeralBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||||
|
boolean result = false;
|
||||||
|
|
||||||
|
if (operation == JsclOperation.numeric) {
|
||||||
|
if (generic.getConstants().isEmpty()) {
|
||||||
|
try {
|
||||||
|
convert(generic);
|
||||||
|
|
||||||
|
// conversion possible => return true
|
||||||
|
result = true;
|
||||||
|
|
||||||
|
} catch (CalculatorImpl.ConversionException e) {
|
||||||
|
// conversion is not possible => return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
||||||
|
final NumeralBase fromNumeralBase = CalculatorEngine.instance.getEngine().getNumeralBase();
|
||||||
|
|
||||||
|
final Generic lastResult = data.getResult();
|
||||||
|
|
||||||
|
if (lastResult != null) {
|
||||||
|
convert(lastResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void convert(@NotNull Generic generic) {
|
||||||
|
CalculatorLocatorImpl.getInstance().getCalculator().convert(generic, this.toNumeralBase);
|
||||||
|
}
|
||||||
|
}
|
@ -1,40 +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;
|
|
||||||
|
|
||||||
import jscl.math.Generic;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.solovyev.android.calculator.history.Editor;
|
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User: serso
|
|
||||||
* Date: 12/17/11
|
|
||||||
* Time: 9:45 PM
|
|
||||||
*/
|
|
||||||
public interface ICalculatorDisplay extends Editor{
|
|
||||||
|
|
||||||
boolean isValid();
|
|
||||||
|
|
||||||
void setValid(boolean valid);
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
String getErrorMessage();
|
|
||||||
|
|
||||||
void setErrorMessage(@Nullable String errorMessage);
|
|
||||||
|
|
||||||
void setJsclOperation(@NotNull JsclOperation jsclOperation);
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
JsclOperation getJsclOperation();
|
|
||||||
|
|
||||||
void setGenericResult(@Nullable Generic genericResult);
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
Generic getGenericResult();
|
|
||||||
}
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,49 +1,50 @@
|
|||||||
/*
|
/*
|
||||||
* 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.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
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.Editor;
|
||||||
/**
|
|
||||||
* User: serso
|
/**
|
||||||
* Date: 12/17/11
|
* User: serso
|
||||||
* Time: 9:39 PM
|
* Date: 12/17/11
|
||||||
*/
|
* Time: 9:39 PM
|
||||||
public class TextViewEditorAdapter implements Editor {
|
*/
|
||||||
|
public class TextViewEditorAdapter implements Editor {
|
||||||
@NotNull
|
|
||||||
private final TextView textView;
|
@NotNull
|
||||||
|
private final TextView textView;
|
||||||
public TextViewEditorAdapter(@NotNull TextView textView) {
|
|
||||||
this.textView = textView;
|
public TextViewEditorAdapter(@NotNull TextView textView) {
|
||||||
}
|
this.textView = textView;
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public CharSequence getText() {
|
@Override
|
||||||
return textView.getText().toString();
|
public CharSequence getText() {
|
||||||
}
|
return textView.getText().toString();
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void setText(@Nullable CharSequence text) {
|
@Override
|
||||||
textView.setText(text);
|
public void setText(@Nullable CharSequence text) {
|
||||||
}
|
textView.setText(text);
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public int getSelection() {
|
@Override
|
||||||
return textView.getSelectionStart();
|
public int getSelection() {
|
||||||
}
|
return textView.getSelectionStart();
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void setSelection(int selection) {
|
@Override
|
||||||
if ( textView instanceof EditText ) {
|
public void setSelection(int selection) {
|
||||||
((EditText) textView).setSelection(selection);
|
if ( textView instanceof EditText ) {
|
||||||
}
|
((EditText) textView).setSelection(selection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -1,425 +1,404 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
* For more information, please, contact se.solovyev@gmail.com
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator.model;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import jscl.*;
|
import jscl.*;
|
||||||
import jscl.math.Generic;
|
import jscl.math.Generic;
|
||||||
import jscl.math.function.Function;
|
import jscl.math.function.Function;
|
||||||
import jscl.math.function.IConstant;
|
import jscl.math.function.IConstant;
|
||||||
import jscl.math.operator.Operator;
|
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.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.prefs.BooleanPreference;
|
import org.solovyev.android.msg.AndroidMessage;
|
||||||
import org.solovyev.android.prefs.Preference;
|
import org.solovyev.android.prefs.BooleanPreference;
|
||||||
import org.solovyev.android.prefs.StringPreference;
|
import org.solovyev.android.prefs.Preference;
|
||||||
import org.solovyev.common.MutableObject;
|
import org.solovyev.android.prefs.StringPreference;
|
||||||
import org.solovyev.common.msg.MessageRegistry;
|
import org.solovyev.common.MutableObject;
|
||||||
import org.solovyev.common.text.EnumMapper;
|
import org.solovyev.common.msg.MessageRegistry;
|
||||||
import org.solovyev.common.text.NumberMapper;
|
import org.solovyev.common.msg.MessageType;
|
||||||
import org.solovyev.common.text.StringUtils;
|
import org.solovyev.common.text.EnumMapper;
|
||||||
|
import org.solovyev.common.text.NumberMapper;
|
||||||
import java.text.DecimalFormatSymbols;
|
import org.solovyev.common.text.StringUtils;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.text.DecimalFormatSymbols;
|
||||||
import java.util.List;
|
import java.util.ArrayList;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.Collections;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
/**
|
import java.util.concurrent.TimeUnit;
|
||||||
* User: serso
|
|
||||||
* Date: 9/12/11
|
/**
|
||||||
* Time: 11:38 PM
|
* User: serso
|
||||||
*/
|
* Date: 9/12/11
|
||||||
|
* Time: 11:38 PM
|
||||||
public enum CalculatorEngine {
|
*/
|
||||||
|
|
||||||
instance;
|
public enum CalculatorEngine implements JCalculatorEngine {
|
||||||
|
|
||||||
private static final String GROUPING_SEPARATOR_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_calc_grouping_separator";
|
instance;
|
||||||
|
|
||||||
private static final String MULTIPLICATION_SIGN_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_calc_multiplication_sign";
|
private static final String GROUPING_SEPARATOR_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_calc_grouping_separator";
|
||||||
private static final String MULTIPLICATION_SIGN_DEFAULT = "×";
|
|
||||||
|
private static final String MULTIPLICATION_SIGN_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_calc_multiplication_sign";
|
||||||
private static final String MAX_CALCULATION_TIME_P_KEY = "calculation.max_calculation_time";
|
private static final String MULTIPLICATION_SIGN_DEFAULT = "×";
|
||||||
private static final String MAX_CALCULATION_TIME_DEFAULT = "5";
|
|
||||||
|
private static final String MAX_CALCULATION_TIME_P_KEY = "calculation.max_calculation_time";
|
||||||
private static final String SCIENCE_NOTATION_P_KEY = "calculation.output.science_notation";
|
private static final String MAX_CALCULATION_TIME_DEFAULT = "5";
|
||||||
private static final boolean SCIENCE_NOTATION_DEFAULT = false;
|
|
||||||
|
private static final String SCIENCE_NOTATION_P_KEY = "calculation.output.science_notation";
|
||||||
private static final String ROUND_RESULT_P_KEY = "org.solovyev.android.calculator.CalculatorModel_round_result";
|
private static final boolean SCIENCE_NOTATION_DEFAULT = false;
|
||||||
private static final boolean ROUND_RESULT_DEFAULT = true;
|
|
||||||
|
private static final String ROUND_RESULT_P_KEY = "org.solovyev.android.calculator.CalculatorModel_round_result";
|
||||||
private static final String RESULT_PRECISION_P_KEY = "org.solovyev.android.calculator.CalculatorModel_result_precision";
|
private static final boolean ROUND_RESULT_DEFAULT = true;
|
||||||
private static final String RESULT_PRECISION_DEFAULT = "5";
|
|
||||||
|
private static final String RESULT_PRECISION_P_KEY = "org.solovyev.android.calculator.CalculatorModel_result_precision";
|
||||||
private static final String NUMERAL_BASES_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_numeral_bases";
|
private static final String RESULT_PRECISION_DEFAULT = "5";
|
||||||
private static final String NUMERAL_BASES_DEFAULT = "dec";
|
|
||||||
|
private static final String NUMERAL_BASES_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_numeral_bases";
|
||||||
private static final String ANGLE_UNITS_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_angle_units";
|
private static final String NUMERAL_BASES_DEFAULT = "dec";
|
||||||
private static final String ANGLE_UNITS_DEFAULT = "deg";
|
|
||||||
|
private static final String ANGLE_UNITS_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_angle_units";
|
||||||
public static class Preferences {
|
private static final String ANGLE_UNITS_DEFAULT = "deg";
|
||||||
public static final Preference<String> groupingSeparator = StringPreference.newInstance(GROUPING_SEPARATOR_P_KEY, JsclMathEngine.GROUPING_SEPARATOR_DEFAULT);
|
|
||||||
public static final Preference<String> multiplicationSign = StringPreference.newInstance(MULTIPLICATION_SIGN_P_KEY, MULTIPLICATION_SIGN_DEFAULT);
|
public static class Preferences {
|
||||||
public static final Preference<Integer> precision = StringPreference.newInstance(RESULT_PRECISION_P_KEY, RESULT_PRECISION_DEFAULT, new NumberMapper<Integer>(Integer.class));
|
public static final Preference<String> groupingSeparator = StringPreference.newInstance(GROUPING_SEPARATOR_P_KEY, JsclMathEngine.GROUPING_SEPARATOR_DEFAULT);
|
||||||
public static final Preference<Boolean> roundResult = new BooleanPreference(ROUND_RESULT_P_KEY, ROUND_RESULT_DEFAULT);
|
public static final Preference<String> multiplicationSign = StringPreference.newInstance(MULTIPLICATION_SIGN_P_KEY, MULTIPLICATION_SIGN_DEFAULT);
|
||||||
public static final Preference<NumeralBase> numeralBase = StringPreference.newInstance(NUMERAL_BASES_P_KEY, NUMERAL_BASES_DEFAULT, EnumMapper.newInstance(NumeralBase.class));
|
public static final Preference<Integer> precision = StringPreference.newInstance(RESULT_PRECISION_P_KEY, RESULT_PRECISION_DEFAULT, new NumberMapper<Integer>(Integer.class));
|
||||||
public static final Preference<AngleUnit> angleUnit = StringPreference.newInstance(ANGLE_UNITS_P_KEY, ANGLE_UNITS_DEFAULT, EnumMapper.newInstance(AngleUnit.class));
|
public static final Preference<Boolean> roundResult = new BooleanPreference(ROUND_RESULT_P_KEY, ROUND_RESULT_DEFAULT);
|
||||||
public static final Preference<Boolean> scienceNotation = new BooleanPreference(SCIENCE_NOTATION_P_KEY, SCIENCE_NOTATION_DEFAULT);
|
public static final Preference<NumeralBase> numeralBase = StringPreference.newInstance(NUMERAL_BASES_P_KEY, NUMERAL_BASES_DEFAULT, EnumMapper.newInstance(NumeralBase.class));
|
||||||
public static final Preference<Integer> maxCalculationTime = StringPreference.newInstance(MAX_CALCULATION_TIME_P_KEY, MAX_CALCULATION_TIME_DEFAULT, new NumberMapper<Integer>(Integer.class));
|
public static final Preference<AngleUnit> angleUnit = StringPreference.newInstance(ANGLE_UNITS_P_KEY, ANGLE_UNITS_DEFAULT, EnumMapper.newInstance(AngleUnit.class));
|
||||||
|
public static final Preference<Boolean> scienceNotation = new BooleanPreference(SCIENCE_NOTATION_P_KEY, SCIENCE_NOTATION_DEFAULT);
|
||||||
private static final List<String> preferenceKeys = new ArrayList<String>();
|
public static final Preference<Integer> maxCalculationTime = StringPreference.newInstance(MAX_CALCULATION_TIME_P_KEY, MAX_CALCULATION_TIME_DEFAULT, new NumberMapper<Integer>(Integer.class));
|
||||||
|
|
||||||
static {
|
private static final List<String> preferenceKeys = new ArrayList<String>();
|
||||||
preferenceKeys.add(groupingSeparator.getKey());
|
|
||||||
preferenceKeys.add(multiplicationSign.getKey());
|
static {
|
||||||
preferenceKeys.add(precision.getKey());
|
preferenceKeys.add(groupingSeparator.getKey());
|
||||||
preferenceKeys.add(roundResult.getKey());
|
preferenceKeys.add(multiplicationSign.getKey());
|
||||||
preferenceKeys.add(numeralBase.getKey());
|
preferenceKeys.add(precision.getKey());
|
||||||
preferenceKeys.add(angleUnit.getKey());
|
preferenceKeys.add(roundResult.getKey());
|
||||||
preferenceKeys.add(scienceNotation.getKey());
|
preferenceKeys.add(numeralBase.getKey());
|
||||||
preferenceKeys.add(maxCalculationTime.getKey());
|
preferenceKeys.add(angleUnit.getKey());
|
||||||
}
|
preferenceKeys.add(scienceNotation.getKey());
|
||||||
|
preferenceKeys.add(maxCalculationTime.getKey());
|
||||||
@NotNull
|
}
|
||||||
public static List<String> getPreferenceKeys() {
|
|
||||||
return Collections.unmodifiableList(preferenceKeys);
|
@NotNull
|
||||||
}
|
public static List<String> getPreferenceKeys() {
|
||||||
}
|
return Collections.unmodifiableList(preferenceKeys);
|
||||||
|
}
|
||||||
@NotNull
|
}
|
||||||
private final Object lock = new Object();
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
private final Object lock = new Object();
|
||||||
private MathEngine engine = JsclMathEngine.instance;
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
private MathEngine engine = JsclMathEngine.instance;
|
||||||
public final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
public final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
|
||||||
private final AndroidMathRegistry<IConstant> varsRegistry = new AndroidVarsRegistryImpl(engine.getConstantsRegistry());
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
private final AndroidMathRegistry<IConstant> varsRegistry = new AndroidVarsRegistryImpl(engine.getConstantsRegistry());
|
||||||
private final AndroidMathRegistry<jscl.math.function.Function> functionsRegistry = new AndroidFunctionsMathRegistry(engine.getFunctionsRegistry());
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
private final AndroidMathRegistry<jscl.math.function.Function> functionsRegistry = new AndroidFunctionsMathRegistry(engine.getFunctionsRegistry());
|
||||||
private final AndroidMathRegistry<Operator> operatorsRegistry = new AndroidOperatorsMathRegistry(engine.getOperatorsRegistry());
|
|
||||||
|
@NotNull
|
||||||
private final AndroidMathRegistry<Operator> postfixFunctionsRegistry = new AndroidPostfixFunctionsRegistry(engine.getPostfixFunctionsRegistry());
|
private final AndroidMathRegistry<Operator> operatorsRegistry = new AndroidOperatorsMathRegistry(engine.getOperatorsRegistry());
|
||||||
|
|
||||||
@Nullable
|
private final AndroidMathRegistry<Operator> postfixFunctionsRegistry = new AndroidPostfixFunctionsRegistry(engine.getPostfixFunctionsRegistry());
|
||||||
private ThreadKiller threadKiller = new AndroidThreadKiller();
|
|
||||||
|
@Nullable
|
||||||
// calculation thread timeout in seconds, after timeout thread would be interrupted
|
private ThreadKiller threadKiller = new AndroidThreadKiller();
|
||||||
private int timeout = Integer.valueOf(MAX_CALCULATION_TIME_DEFAULT);
|
|
||||||
|
// calculation thread timeout in seconds, after timeout thread would be interrupted
|
||||||
@NotNull
|
private int timeout = Integer.valueOf(MAX_CALCULATION_TIME_DEFAULT);
|
||||||
private String multiplicationSign = MULTIPLICATION_SIGN_DEFAULT;
|
|
||||||
|
@NotNull
|
||||||
CalculatorEngine() {
|
private String multiplicationSign = MULTIPLICATION_SIGN_DEFAULT;
|
||||||
this.engine.setRoundResult(true);
|
|
||||||
this.engine.setUseGroupingSeparator(true);
|
CalculatorEngine() {
|
||||||
}
|
this.engine.setRoundResult(true);
|
||||||
|
this.engine.setUseGroupingSeparator(true);
|
||||||
@NotNull
|
}
|
||||||
public String getMultiplicationSign() {
|
|
||||||
return multiplicationSign;
|
@Override
|
||||||
}
|
@NotNull
|
||||||
|
public String getMultiplicationSign() {
|
||||||
public void setMultiplicationSign(@NotNull String multiplicationSign) {
|
return multiplicationSign;
|
||||||
this.multiplicationSign = multiplicationSign;
|
}
|
||||||
}
|
|
||||||
|
public void setMultiplicationSign(@NotNull String multiplicationSign) {
|
||||||
public static class Result {
|
this.multiplicationSign = multiplicationSign;
|
||||||
|
}
|
||||||
@NotNull
|
|
||||||
private Generic genericResult;
|
public CalculatorOutput evaluate(@NotNull JsclOperation operation,
|
||||||
|
@NotNull String expression) throws CalculatorParseException, CalculatorEvalException {
|
||||||
@NotNull
|
return evaluate(operation, expression, null);
|
||||||
private String result;
|
}
|
||||||
|
|
||||||
@NotNull
|
public CalculatorOutput evaluate(@NotNull final JsclOperation operation,
|
||||||
private JsclOperation userOperation;
|
@NotNull String expression,
|
||||||
|
@Nullable MessageRegistry mr) throws CalculatorParseException, CalculatorEvalException {
|
||||||
public Result(@NotNull String result, @NotNull JsclOperation userOperation, @NotNull Generic genericResult) {
|
synchronized (lock) {
|
||||||
this.result = result;
|
final StringBuilder sb = new StringBuilder();
|
||||||
this.userOperation = userOperation;
|
|
||||||
this.genericResult = genericResult;
|
final PreparedExpression preparedExpression = preprocessor.process(expression);
|
||||||
}
|
sb.append(preparedExpression);
|
||||||
|
|
||||||
@NotNull
|
//Log.d(CalculatorEngine.class.getName(), "Preprocessed expression: " + preparedExpression);
|
||||||
public String getResult() {
|
/*if (operation == JsclOperation.numeric && preparedExpression.isExistsUndefinedVar()) {
|
||||||
return result;
|
operation = JsclOperation.simplify;
|
||||||
}
|
|
||||||
|
if (mr != null) {
|
||||||
@NotNull
|
final String undefinedVars = CollectionsUtils.formatValue(preparedExpression.getUndefinedVars(), ", ", new Formatter<Var>() {
|
||||||
public JsclOperation getUserOperation() {
|
@Override
|
||||||
return userOperation;
|
public String formatValue(@Nullable Var var) throws IllegalArgumentException {
|
||||||
}
|
return var != null ? var.getName() : "";
|
||||||
|
}
|
||||||
@NotNull
|
});
|
||||||
public Generic getGenericResult() {
|
|
||||||
return genericResult;
|
mr.addMessage(new AndroidMessage(R.string.c_simplify_instead_of_numeric, MessageType.info, undefinedVars));
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
public Result evaluate(@NotNull JsclOperation operation,
|
final String jsclExpression = sb.toString();
|
||||||
@NotNull String expression) throws CalculatorParseException, CalculatorEvalException {
|
|
||||||
return evaluate(operation, expression, null);
|
final MutableObject<Generic> calculationResult = new MutableObject<Generic>(null);
|
||||||
}
|
final MutableObject<CalculatorParseException> parseException = new MutableObject<CalculatorParseException>(null);
|
||||||
|
final MutableObject<CalculatorEvalException> evalException = new MutableObject<CalculatorEvalException>(null);
|
||||||
public Result evaluate(@NotNull final JsclOperation operation,
|
final MutableObject<Thread> calculationThread = new MutableObject<Thread>(null);
|
||||||
@NotNull String expression,
|
|
||||||
@Nullable MessageRegistry mr) throws CalculatorParseException, CalculatorEvalException {
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
synchronized (lock) {
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
final PreparedExpression preparedExpression = preprocessor.process(expression);
|
public void run() {
|
||||||
sb.append(preparedExpression);
|
final Thread thread = Thread.currentThread();
|
||||||
|
try {
|
||||||
//Log.d(CalculatorEngine.class.getName(), "Preprocessed expression: " + preparedExpression);
|
//Log.d(CalculatorEngine.class.getName(), "Calculation thread started work: " + thread.getName());
|
||||||
/*if (operation == JsclOperation.numeric && preparedExpression.isExistsUndefinedVar()) {
|
//System.out.println(jsclExpression);
|
||||||
operation = JsclOperation.simplify;
|
calculationThread.setObject(thread);
|
||||||
|
final Generic genericResult = operation.evaluateGeneric(jsclExpression);
|
||||||
if (mr != null) {
|
|
||||||
final String undefinedVars = CollectionsUtils.formatValue(preparedExpression.getUndefinedVars(), ", ", new Formatter<Var>() {
|
// NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!)
|
||||||
@Override
|
genericResult.toString();
|
||||||
public String formatValue(@Nullable Var var) throws IllegalArgumentException {
|
|
||||||
return var != null ? var.getName() : "";
|
calculationResult.setObject(genericResult);
|
||||||
}
|
} catch (AbstractJsclArithmeticException e) {
|
||||||
});
|
evalException.setObject(new CalculatorEvalException(e, e, jsclExpression));
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
mr.addMessage(new AndroidMessage(R.string.c_simplify_instead_of_numeric, MessageType.info, undefinedVars));
|
//System.out.println(e.getMessage());
|
||||||
}
|
final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_1, MessageType.error, CalculatorApplication.getInstance(), e.getMessage());
|
||||||
}*/
|
parseException.setObject(new CalculatorParseException(jsclExpression, androidMessage));
|
||||||
|
} catch (StackOverflowError e) {
|
||||||
final String jsclExpression = sb.toString();
|
//System.out.println(StringUtils.fromStackTrace(e.getStackTrace()));
|
||||||
|
final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_2, MessageType.error, CalculatorApplication.getInstance());
|
||||||
final MutableObject<Generic> calculationResult = new MutableObject<Generic>(null);
|
parseException.setObject(new CalculatorParseException(jsclExpression, androidMessage));
|
||||||
final MutableObject<CalculatorParseException> parseException = new MutableObject<CalculatorParseException>(null);
|
} catch (jscl.text.ParseException e) {
|
||||||
final MutableObject<CalculatorEvalException> evalException = new MutableObject<CalculatorEvalException>(null);
|
//System.out.println(e.getMessage());
|
||||||
final MutableObject<Thread> calculationThread = new MutableObject<Thread>(null);
|
parseException.setObject(new CalculatorParseException(e));
|
||||||
|
} catch (ParseInterruptedException e) {
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
//System.out.println(e.getMessage());
|
||||||
|
// do nothing - we ourselves interrupt the calculations
|
||||||
new Thread(new Runnable() {
|
} finally {
|
||||||
@Override
|
//Log.d(CalculatorEngine.class.getName(), "Calculation thread ended work: " + thread.getName());
|
||||||
public void run() {
|
calculationThread.setObject(null);
|
||||||
final Thread thread = Thread.currentThread();
|
latch.countDown();
|
||||||
try {
|
}
|
||||||
//Log.d(CalculatorEngine.class.getName(), "Calculation thread started work: " + thread.getName());
|
}
|
||||||
//System.out.println(jsclExpression);
|
}).start();
|
||||||
calculationThread.setObject(thread);
|
|
||||||
final Generic genericResult = operation.evaluateGeneric(jsclExpression);
|
try {
|
||||||
|
//Log.d(CalculatorEngine.class.getName(), "Main thread is waiting: " + Thread.currentThread().getName());
|
||||||
// NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!)
|
latch.await(timeout, TimeUnit.SECONDS);
|
||||||
genericResult.toString();
|
//Log.d(CalculatorEngine.class.getName(), "Main thread got up: " + Thread.currentThread().getName());
|
||||||
|
|
||||||
calculationResult.setObject(genericResult);
|
final CalculatorParseException parseExceptionObject = parseException.getObject();
|
||||||
} catch (AbstractJsclArithmeticException e) {
|
final CalculatorEvalException evalExceptionObject = evalException.getObject();
|
||||||
evalException.setObject(new CalculatorEvalException(e, e, jsclExpression));
|
final Object calculationResultLocal = calculationResult.getObject();
|
||||||
} catch (ArithmeticException e) {
|
final Thread calculationThreadLocal = calculationThread.getObject();
|
||||||
//System.out.println(e.getMessage());
|
|
||||||
parseException.setObject(new CalculatorParseException(R.string.msg_1, CalculatorApplication.getInstance(), jsclExpression, e.getMessage()));
|
if (calculationThreadLocal != null) {
|
||||||
} catch (StackOverflowError e) {
|
if (threadKiller != null) {
|
||||||
//System.out.println(StringUtils.fromStackTrace(e.getStackTrace()));
|
threadKiller.killThread(calculationThreadLocal);
|
||||||
parseException.setObject(new CalculatorParseException(R.string.msg_2, CalculatorApplication.getInstance(), jsclExpression));
|
}
|
||||||
} catch (jscl.text.ParseException e) {
|
//calculationThreadLocal.stop();
|
||||||
//System.out.println(e.getMessage());
|
}
|
||||||
parseException.setObject(new CalculatorParseException(e));
|
|
||||||
} catch (ParseInterruptedException e) {
|
if (parseExceptionObject != null || evalExceptionObject != null) {
|
||||||
//System.out.println(e.getMessage());
|
if (operation == JsclOperation.numeric &&
|
||||||
// do nothing - we ourselves interrupt the calculations
|
(preparedExpression.isExistsUndefinedVar() || (evalExceptionObject != null && evalExceptionObject.getCause() instanceof NumeralBaseException))) {
|
||||||
} finally {
|
return evaluate(JsclOperation.simplify, expression, mr);
|
||||||
//Log.d(CalculatorEngine.class.getName(), "Calculation thread ended work: " + thread.getName());
|
}
|
||||||
calculationThread.setObject(null);
|
|
||||||
latch.countDown();
|
if (parseExceptionObject != null) {
|
||||||
}
|
throw parseExceptionObject;
|
||||||
}
|
} else {
|
||||||
}).start();
|
throw evalExceptionObject;
|
||||||
|
}
|
||||||
try {
|
}
|
||||||
//Log.d(CalculatorEngine.class.getName(), "Main thread is waiting: " + Thread.currentThread().getName());
|
|
||||||
latch.await(timeout, TimeUnit.SECONDS);
|
if (calculationResultLocal == null) {
|
||||||
//Log.d(CalculatorEngine.class.getName(), "Main thread got up: " + Thread.currentThread().getName());
|
final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_3, MessageType.error, CalculatorApplication.getInstance());
|
||||||
|
throw new CalculatorParseException(jsclExpression, androidMessage);
|
||||||
final CalculatorParseException parseExceptionObject = parseException.getObject();
|
}
|
||||||
final CalculatorEvalException evalExceptionObject = evalException.getObject();
|
|
||||||
final Object calculationResultLocal = calculationResult.getObject();
|
} catch (InterruptedException e) {
|
||||||
final Thread calculationThreadLocal = calculationThread.getObject();
|
final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_4, MessageType.error, CalculatorApplication.getInstance());
|
||||||
|
throw new CalculatorParseException(jsclExpression, androidMessage);
|
||||||
if (calculationThreadLocal != null) {
|
}
|
||||||
if (threadKiller != null) {
|
|
||||||
threadKiller.killThread(calculationThreadLocal);
|
final Generic genericResult = calculationResult.getObject();
|
||||||
}
|
|
||||||
//calculationThreadLocal.stop();
|
return new CalculatorOutputImpl(operation.getFromProcessor().process(genericResult), operation, genericResult);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (parseExceptionObject != null || evalExceptionObject != null) {
|
|
||||||
if (operation == JsclOperation.numeric &&
|
public void setPrecision(int precision) {
|
||||||
(preparedExpression.isExistsUndefinedVar() || (evalExceptionObject != null && evalExceptionObject.getCause() instanceof NumeralBaseException))) {
|
this.getEngine().setPrecision(precision);
|
||||||
return evaluate(JsclOperation.simplify, expression, mr);
|
}
|
||||||
}
|
|
||||||
|
public void setRoundResult(boolean roundResult) {
|
||||||
if (parseExceptionObject != null) {
|
this.getEngine().setRoundResult(roundResult);
|
||||||
throw parseExceptionObject;
|
}
|
||||||
} else {
|
|
||||||
throw evalExceptionObject;
|
public void init(@Nullable Context context, @Nullable SharedPreferences preferences) {
|
||||||
}
|
synchronized (lock) {
|
||||||
}
|
reset(context, preferences);
|
||||||
|
}
|
||||||
if (calculationResultLocal == null) {
|
}
|
||||||
throw new CalculatorParseException(R.string.msg_3, CalculatorApplication.getInstance(), jsclExpression);
|
|
||||||
}
|
public void reset(@Nullable Context context, @Nullable SharedPreferences preferences) {
|
||||||
|
synchronized (lock) {
|
||||||
} catch (InterruptedException e) {
|
softReset(context, preferences);
|
||||||
throw new CalculatorParseException(R.string.msg_4, CalculatorApplication.getInstance(), jsclExpression);
|
|
||||||
}
|
varsRegistry.load(context, preferences);
|
||||||
|
functionsRegistry.load(context, preferences);
|
||||||
final Generic genericResult = calculationResult.getObject();
|
operatorsRegistry.load(context, preferences);
|
||||||
|
postfixFunctionsRegistry.load(context, preferences);
|
||||||
return new Result(operation.getFromProcessor().process(genericResult), operation, genericResult);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public void softReset(@Nullable Context context, @Nullable SharedPreferences preferences) {
|
||||||
public void setPrecision(int precision) {
|
synchronized (lock) {
|
||||||
this.getEngine().setPrecision(precision);
|
if (preferences != null) {
|
||||||
}
|
this.setPrecision(Preferences.precision.getPreference(preferences));
|
||||||
|
this.setRoundResult(Preferences.roundResult.getPreference(preferences));
|
||||||
public void setRoundResult(boolean roundResult) {
|
this.setAngleUnits(getAngleUnitsFromPrefs(preferences));
|
||||||
this.getEngine().setRoundResult(roundResult);
|
this.setNumeralBase(getNumeralBaseFromPrefs(preferences));
|
||||||
}
|
this.setMultiplicationSign(Preferences.multiplicationSign.getPreference(preferences));
|
||||||
|
this.setScienceNotation(Preferences.scienceNotation.getPreference(preferences));
|
||||||
public void init(@Nullable Context context, @Nullable SharedPreferences preferences) {
|
this.setTimeout(Preferences.maxCalculationTime.getPreference(preferences));
|
||||||
synchronized (lock) {
|
|
||||||
reset(context, preferences);
|
final String groupingSeparator = Preferences.groupingSeparator.getPreference(preferences);
|
||||||
}
|
if (StringUtils.isEmpty(groupingSeparator)) {
|
||||||
}
|
this.getEngine().setUseGroupingSeparator(false);
|
||||||
|
} else {
|
||||||
public void reset(@Nullable Context context, @Nullable SharedPreferences preferences) {
|
this.getEngine().setUseGroupingSeparator(true);
|
||||||
synchronized (lock) {
|
this.getEngine().setGroupingSeparator(groupingSeparator.charAt(0));
|
||||||
softReset(context, preferences);
|
}
|
||||||
|
}
|
||||||
varsRegistry.load(context, preferences);
|
}
|
||||||
functionsRegistry.load(context, preferences);
|
}
|
||||||
operatorsRegistry.load(context, preferences);
|
|
||||||
postfixFunctionsRegistry.load(context, preferences);
|
|
||||||
}
|
@NotNull
|
||||||
}
|
public NumeralBase getNumeralBaseFromPrefs(@NotNull SharedPreferences preferences) {
|
||||||
|
return Preferences.numeralBase.getPreference(preferences);
|
||||||
public void softReset(@Nullable Context context, @Nullable SharedPreferences preferences) {
|
}
|
||||||
synchronized (lock) {
|
|
||||||
if (preferences != null) {
|
@NotNull
|
||||||
this.setPrecision(Preferences.precision.getPreference(preferences));
|
public AngleUnit getAngleUnitsFromPrefs(@NotNull SharedPreferences preferences) {
|
||||||
this.setRoundResult(Preferences.roundResult.getPreference(preferences));
|
return Preferences.angleUnit.getPreference(preferences);
|
||||||
this.setAngleUnits(getAngleUnitsFromPrefs(preferences));
|
}
|
||||||
this.setNumeralBase(getNumeralBaseFromPrefs(preferences));
|
|
||||||
this.setMultiplicationSign(Preferences.multiplicationSign.getPreference(preferences));
|
//for tests only
|
||||||
this.setScienceNotation(Preferences.scienceNotation.getPreference(preferences));
|
void setDecimalGroupSymbols(@NotNull DecimalFormatSymbols decimalGroupSymbols) {
|
||||||
this.setTimeout(Preferences.maxCalculationTime.getPreference(preferences));
|
synchronized (lock) {
|
||||||
|
this.getEngine().setDecimalGroupSymbols(decimalGroupSymbols);
|
||||||
final String groupingSeparator = Preferences.groupingSeparator.getPreference(preferences);
|
}
|
||||||
if (StringUtils.isEmpty(groupingSeparator)) {
|
}
|
||||||
this.getEngine().setUseGroupingSeparator(false);
|
|
||||||
} else {
|
@Override
|
||||||
this.getEngine().setUseGroupingSeparator(true);
|
@NotNull
|
||||||
this.getEngine().setGroupingSeparator(groupingSeparator.charAt(0));
|
public AndroidMathRegistry<IConstant> getVarsRegistry() {
|
||||||
}
|
return varsRegistry;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public AndroidMathRegistry<Function> getFunctionsRegistry() {
|
||||||
@NotNull
|
return functionsRegistry;
|
||||||
public NumeralBase getNumeralBaseFromPrefs(@NotNull SharedPreferences preferences) {
|
}
|
||||||
return Preferences.numeralBase.getPreference(preferences);
|
|
||||||
}
|
@Override
|
||||||
|
@NotNull
|
||||||
@NotNull
|
public AndroidMathRegistry<Operator> getOperatorsRegistry() {
|
||||||
public AngleUnit getAngleUnitsFromPrefs(@NotNull SharedPreferences preferences) {
|
return operatorsRegistry;
|
||||||
return Preferences.angleUnit.getPreference(preferences);
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
//for tests only
|
@NotNull
|
||||||
void setDecimalGroupSymbols(@NotNull DecimalFormatSymbols decimalGroupSymbols) {
|
public AndroidMathRegistry<Operator> getPostfixFunctionsRegistry() {
|
||||||
synchronized (lock) {
|
return postfixFunctionsRegistry;
|
||||||
this.getEngine().setDecimalGroupSymbols(decimalGroupSymbols);
|
}
|
||||||
}
|
|
||||||
}
|
@Override
|
||||||
|
@NotNull
|
||||||
@NotNull
|
public MathEngine getEngine() {
|
||||||
public AndroidMathRegistry<IConstant> getVarsRegistry() {
|
return engine;
|
||||||
return varsRegistry;
|
}
|
||||||
}
|
|
||||||
|
// package protected for tests
|
||||||
@NotNull
|
void setTimeout(int timeout) {
|
||||||
public AndroidMathRegistry<Function> getFunctionsRegistry() {
|
this.timeout = timeout;
|
||||||
return functionsRegistry;
|
}
|
||||||
}
|
|
||||||
|
public void setAngleUnits(@NotNull AngleUnit angleUnits) {
|
||||||
@NotNull
|
getEngine().setAngleUnits(angleUnits);
|
||||||
public AndroidMathRegistry<Operator> getOperatorsRegistry() {
|
}
|
||||||
return operatorsRegistry;
|
|
||||||
}
|
public void setScienceNotation(boolean scienceNotation) {
|
||||||
|
getEngine().setScienceNotation(scienceNotation);
|
||||||
@NotNull
|
}
|
||||||
public AndroidMathRegistry<Operator> getPostfixFunctionsRegistry() {
|
|
||||||
return postfixFunctionsRegistry;
|
public void setNumeralBase(@NotNull NumeralBase numeralBase) {
|
||||||
}
|
getEngine().setNumeralBase(numeralBase);
|
||||||
|
}
|
||||||
@NotNull
|
|
||||||
public MathEngine getEngine() {
|
// for tests only
|
||||||
return engine;
|
void setThreadKiller(@Nullable ThreadKiller threadKiller) {
|
||||||
}
|
this.threadKiller = threadKiller;
|
||||||
|
}
|
||||||
// package protected for tests
|
|
||||||
void setTimeout(int timeout) {
|
private static interface ThreadKiller {
|
||||||
this.timeout = timeout;
|
void killThread(@NotNull Thread thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAngleUnits(@NotNull AngleUnit angleUnits) {
|
private static class AndroidThreadKiller implements ThreadKiller {
|
||||||
getEngine().setAngleUnits(angleUnits);
|
@Override
|
||||||
}
|
public void killThread(@NotNull Thread thread) {
|
||||||
|
thread.setPriority(Thread.MIN_PRIORITY);
|
||||||
public void setScienceNotation(boolean scienceNotation) {
|
thread.interrupt();
|
||||||
getEngine().setScienceNotation(scienceNotation);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNumeralBase(@NotNull NumeralBase numeralBase) {
|
public static class ThreadKillerImpl implements ThreadKiller {
|
||||||
getEngine().setNumeralBase(numeralBase);
|
@Override
|
||||||
}
|
public void killThread(@NotNull Thread thread) {
|
||||||
|
thread.setPriority(Thread.MIN_PRIORITY);
|
||||||
// for tests only
|
thread.stop();
|
||||||
void setThreadKiller(@Nullable ThreadKiller threadKiller) {
|
}
|
||||||
this.threadKiller = threadKiller;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static interface ThreadKiller {
|
|
||||||
void killThread(@NotNull Thread thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class AndroidThreadKiller implements ThreadKiller {
|
|
||||||
@Override
|
|
||||||
public void killThread(@NotNull Thread thread) {
|
|
||||||
thread.setPriority(Thread.MIN_PRIORITY);
|
|
||||||
thread.interrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ThreadKillerImpl implements ThreadKiller {
|
|
||||||
@Override
|
|
||||||
public void killThread(@NotNull Thread thread) {
|
|
||||||
thread.setPriority(Thread.MIN_PRIORITY);
|
|
||||||
thread.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,360 +1,360 @@
|
|||||||
/*
|
/*
|
||||||
* 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.plot;
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import jscl.math.Expression;
|
import jscl.math.Expression;
|
||||||
import jscl.math.Generic;
|
import jscl.math.Generic;
|
||||||
import jscl.math.function.Constant;
|
import jscl.math.function.Constant;
|
||||||
import jscl.text.ParseException;
|
import jscl.text.ParseException;
|
||||||
import org.achartengine.ChartFactory;
|
import org.achartengine.ChartFactory;
|
||||||
import org.achartengine.GraphicalView;
|
import org.achartengine.GraphicalView;
|
||||||
import org.achartengine.chart.CubicLineChart;
|
import org.achartengine.chart.CubicLineChart;
|
||||||
import org.achartengine.chart.PointStyle;
|
import org.achartengine.chart.PointStyle;
|
||||||
import org.achartengine.chart.XYChart;
|
import org.achartengine.chart.XYChart;
|
||||||
import org.achartengine.model.XYMultipleSeriesDataset;
|
import org.achartengine.model.XYMultipleSeriesDataset;
|
||||||
import org.achartengine.model.XYSeries;
|
import org.achartengine.model.XYSeries;
|
||||||
import org.achartengine.renderer.BasicStroke;
|
import org.achartengine.renderer.BasicStroke;
|
||||||
import org.achartengine.renderer.XYMultipleSeriesRenderer;
|
import org.achartengine.renderer.XYMultipleSeriesRenderer;
|
||||||
import org.achartengine.renderer.XYSeriesRenderer;
|
import org.achartengine.renderer.XYSeriesRenderer;
|
||||||
import org.achartengine.tools.PanListener;
|
import org.achartengine.tools.PanListener;
|
||||||
import org.achartengine.tools.ZoomEvent;
|
import org.achartengine.tools.ZoomEvent;
|
||||||
import org.achartengine.tools.ZoomListener;
|
import org.achartengine.tools.ZoomListener;
|
||||||
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.R;
|
import org.solovyev.android.calculator.R;
|
||||||
import org.solovyev.android.calculator.model.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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 12/1/11
|
* Date: 12/1/11
|
||||||
* Time: 12:40 AM
|
* Time: 12:40 AM
|
||||||
*/
|
*/
|
||||||
public class CalculatorPlotActivity extends Activity {
|
public class CalculatorPlotActivity extends Activity {
|
||||||
|
|
||||||
private static final String TAG = CalculatorPlotActivity.class.getSimpleName();
|
private static final String TAG = CalculatorPlotActivity.class.getSimpleName();
|
||||||
|
|
||||||
private static final int DEFAULT_NUMBER_OF_STEPS = 100;
|
private static final int DEFAULT_NUMBER_OF_STEPS = 100;
|
||||||
|
|
||||||
private static final int DEFAULT_MIN_NUMBER = -10;
|
private static final int DEFAULT_MIN_NUMBER = -10;
|
||||||
|
|
||||||
private static final int DEFAULT_MAX_NUMBER = 10;
|
private static final int DEFAULT_MAX_NUMBER = 10;
|
||||||
|
|
||||||
public static final String INPUT = "org.solovyev.android.calculator.CalculatorPlotActivity_input";
|
public static final String INPUT = "org.solovyev.android.calculator.CalculatorPlotActivity_input";
|
||||||
|
|
||||||
public static final long EVAL_DELAY_MILLIS = 200;
|
public static final long EVAL_DELAY_MILLIS = 200;
|
||||||
|
|
||||||
private XYChart chart;
|
private XYChart chart;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The encapsulated graphical view.
|
* The encapsulated graphical view.
|
||||||
*/
|
*/
|
||||||
private GraphicalView graphicalView;
|
private GraphicalView graphicalView;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Generic expression;
|
private Generic expression;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Constant variable;
|
private Constant variable;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
Bundle extras = getIntent().getExtras();
|
Bundle extras = getIntent().getExtras();
|
||||||
|
|
||||||
final Input input = (Input) extras.getSerializable(INPUT);
|
final Input input = (Input) extras.getSerializable(INPUT);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final PreparedExpression preparedExpression = ToJsclTextProcessor.getInstance().process(input.getExpression());
|
final PreparedExpression preparedExpression = ToJsclTextProcessor.getInstance().process(input.getExpression());
|
||||||
this.expression = Expression.valueOf(preparedExpression.getExpression());
|
this.expression = Expression.valueOf(preparedExpression.getExpression());
|
||||||
this.variable = new Constant(input.getVariableName());
|
this.variable = new Constant(input.getVariableName());
|
||||||
|
|
||||||
String title = extras.getString(ChartFactory.TITLE);
|
String title = extras.getString(ChartFactory.TITLE);
|
||||||
if (title == null) {
|
if (title == null) {
|
||||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||||
} else if (title.length() > 0) {
|
} else if (title.length() > 0) {
|
||||||
setTitle(title);
|
setTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
setContentView(R.layout.calc_plot_view);
|
setContentView(R.layout.calc_plot_view);
|
||||||
|
|
||||||
final Object lastNonConfigurationInstance = getLastNonConfigurationInstance();
|
final Object lastNonConfigurationInstance = getLastNonConfigurationInstance();
|
||||||
setGraphicalView(lastNonConfigurationInstance instanceof PlotBoundaries ? (PlotBoundaries)lastNonConfigurationInstance : null);
|
setGraphicalView(lastNonConfigurationInstance instanceof PlotBoundaries ? (PlotBoundaries)lastNonConfigurationInstance : null);
|
||||||
|
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
|
Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
|
||||||
finish();
|
finish();
|
||||||
} catch (ArithmeticException e) {
|
} catch (ArithmeticException e) {
|
||||||
Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
|
Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
|
||||||
finish();
|
finish();
|
||||||
} catch (CalculatorParseException e) {
|
} catch (CalculatorParseException e) {
|
||||||
Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
|
Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setGraphicalView(@Nullable PlotBoundaries plotBoundaries) {
|
private void setGraphicalView(@Nullable PlotBoundaries plotBoundaries) {
|
||||||
double minValue = plotBoundaries == null ? DEFAULT_MIN_NUMBER : plotBoundaries.xMin;
|
double minValue = plotBoundaries == null ? DEFAULT_MIN_NUMBER : plotBoundaries.xMin;
|
||||||
double maxValue = plotBoundaries == null ? DEFAULT_MAX_NUMBER : plotBoundaries.xMax;
|
double maxValue = plotBoundaries == null ? DEFAULT_MAX_NUMBER : plotBoundaries.xMax;
|
||||||
|
|
||||||
final ViewGroup graphContainer = (ViewGroup) findViewById(R.id.plot_view_container);
|
final ViewGroup graphContainer = (ViewGroup) findViewById(R.id.plot_view_container);
|
||||||
|
|
||||||
if (graphicalView != null) {
|
if (graphicalView != null) {
|
||||||
graphContainer.removeView(graphicalView);
|
graphContainer.removeView(graphicalView);
|
||||||
}
|
}
|
||||||
|
|
||||||
chart = prepareChart(minValue, maxValue, expression, variable);
|
chart = prepareChart(minValue, maxValue, expression, variable);
|
||||||
|
|
||||||
// reverting boundaries (as in prepareChart() we add some cached values )
|
// reverting boundaries (as in prepareChart() we add some cached values )
|
||||||
double minX = Double.MAX_VALUE;
|
double minX = Double.MAX_VALUE;
|
||||||
double minY = Double.MAX_VALUE;
|
double minY = Double.MAX_VALUE;
|
||||||
|
|
||||||
double maxX = Double.MIN_VALUE;
|
double maxX = Double.MIN_VALUE;
|
||||||
double maxY = Double.MIN_VALUE;
|
double maxY = Double.MIN_VALUE;
|
||||||
|
|
||||||
for (XYSeries series : chart.getDataset().getSeries()) {
|
for (XYSeries series : chart.getDataset().getSeries()) {
|
||||||
minX = Math.min(minX, series.getMinX());
|
minX = Math.min(minX, series.getMinX());
|
||||||
minY = Math.min(minY, series.getMinY());
|
minY = Math.min(minY, series.getMinY());
|
||||||
maxX = Math.max(maxX, series.getMaxX());
|
maxX = Math.max(maxX, series.getMaxX());
|
||||||
maxY = Math.max(maxY, series.getMaxY());
|
maxY = Math.max(maxY, series.getMaxY());
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(CalculatorPlotActivity.class.getName(), "min x: " + minX + ", min y: " + minY + ", max x: " + maxX + ", max y: " + maxY);
|
Log.d(CalculatorPlotActivity.class.getName(), "min x: " + minX + ", min y: " + minY + ", max x: " + maxX + ", max y: " + maxY);
|
||||||
Log.d(CalculatorPlotActivity.class.getName(), "Plot boundaries are " + plotBoundaries);
|
Log.d(CalculatorPlotActivity.class.getName(), "Plot boundaries are " + plotBoundaries);
|
||||||
|
|
||||||
|
|
||||||
if (plotBoundaries == null) {
|
if (plotBoundaries == null) {
|
||||||
chart.getRenderer().setXAxisMin(Math.max(minX, minValue));
|
chart.getRenderer().setXAxisMin(Math.max(minX, minValue));
|
||||||
chart.getRenderer().setYAxisMin(Math.max(minY, minValue));
|
chart.getRenderer().setYAxisMin(Math.max(minY, minValue));
|
||||||
chart.getRenderer().setXAxisMax(Math.min(maxX, maxValue));
|
chart.getRenderer().setXAxisMax(Math.min(maxX, maxValue));
|
||||||
chart.getRenderer().setYAxisMax(Math.min(maxY, maxValue));
|
chart.getRenderer().setYAxisMax(Math.min(maxY, maxValue));
|
||||||
} else {
|
} else {
|
||||||
chart.getRenderer().setXAxisMin(plotBoundaries.xMin);
|
chart.getRenderer().setXAxisMin(plotBoundaries.xMin);
|
||||||
chart.getRenderer().setYAxisMin(plotBoundaries.yMin);
|
chart.getRenderer().setYAxisMin(plotBoundaries.yMin);
|
||||||
chart.getRenderer().setXAxisMax(plotBoundaries.xMax);
|
chart.getRenderer().setXAxisMax(plotBoundaries.xMax);
|
||||||
chart.getRenderer().setYAxisMax(plotBoundaries.yMax);
|
chart.getRenderer().setYAxisMax(plotBoundaries.yMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
graphicalView = new GraphicalView(this, chart);
|
graphicalView = new GraphicalView(this, chart);
|
||||||
|
|
||||||
graphicalView.addZoomListener(new ZoomListener() {
|
graphicalView.addZoomListener(new ZoomListener() {
|
||||||
@Override
|
@Override
|
||||||
public void zoomApplied(ZoomEvent e) {
|
public void zoomApplied(ZoomEvent e) {
|
||||||
updateDataSets(chart);
|
updateDataSets(chart);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void zoomReset() {
|
public void zoomReset() {
|
||||||
updateDataSets(chart);
|
updateDataSets(chart);
|
||||||
}
|
}
|
||||||
}, true, true);
|
}, true, true);
|
||||||
|
|
||||||
graphicalView.addPanListener(new PanListener() {
|
graphicalView.addPanListener(new PanListener() {
|
||||||
@Override
|
@Override
|
||||||
public void panApplied() {
|
public void panApplied() {
|
||||||
Log.d(TAG, "org.achartengine.tools.PanListener.panApplied");
|
Log.d(TAG, "org.achartengine.tools.PanListener.panApplied");
|
||||||
updateDataSets(chart);
|
updateDataSets(chart);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
graphContainer.addView(graphicalView);
|
graphContainer.addView(graphicalView);
|
||||||
|
|
||||||
updateDataSets(chart, 50);
|
updateDataSets(chart, 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void updateDataSets(@NotNull final XYChart chart) {
|
private void updateDataSets(@NotNull final XYChart chart) {
|
||||||
updateDataSets(chart, EVAL_DELAY_MILLIS);
|
updateDataSets(chart, EVAL_DELAY_MILLIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateDataSets(@NotNull final XYChart chart, long millisToWait) {
|
private void updateDataSets(@NotNull final XYChart chart, long millisToWait) {
|
||||||
pendingOperation.setObject(new Runnable() {
|
pendingOperation.setObject(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// allow only one runner at one time
|
// allow only one runner at one time
|
||||||
synchronized (pendingOperation) {
|
synchronized (pendingOperation) {
|
||||||
//lock all operations with history
|
//lock all operations with history
|
||||||
if (pendingOperation.getObject() == this) {
|
if (pendingOperation.getObject() == this) {
|
||||||
|
|
||||||
Log.d(TAG, "org.solovyev.android.calculator.plot.CalculatorPlotActivity.updateDataSets");
|
Log.d(TAG, "org.solovyev.android.calculator.plot.CalculatorPlotActivity.updateDataSets");
|
||||||
|
|
||||||
final XYMultipleSeriesRenderer dr = chart.getRenderer();
|
final XYMultipleSeriesRenderer dr = chart.getRenderer();
|
||||||
|
|
||||||
//Log.d(CalculatorPlotActivity.class.getName(), "x = [" + dr.getXAxisMin() + ", " + dr.getXAxisMax() + "], y = [" + dr.getYAxisMin() + ", " + dr.getYAxisMax() + "]");
|
//Log.d(CalculatorPlotActivity.class.getName(), "x = [" + dr.getXAxisMin() + ", " + dr.getXAxisMax() + "], y = [" + dr.getYAxisMin() + ", " + dr.getYAxisMax() + "]");
|
||||||
|
|
||||||
final MyXYSeries realSeries = (MyXYSeries)chart.getDataset().getSeriesAt(0);
|
final MyXYSeries realSeries = (MyXYSeries)chart.getDataset().getSeriesAt(0);
|
||||||
|
|
||||||
final MyXYSeries imagSeries;
|
final MyXYSeries imagSeries;
|
||||||
if (chart.getDataset().getSeriesCount() > 1) {
|
if (chart.getDataset().getSeriesCount() > 1) {
|
||||||
imagSeries = (MyXYSeries)chart.getDataset().getSeriesAt(1);
|
imagSeries = (MyXYSeries)chart.getDataset().getSeriesAt(1);
|
||||||
} else {
|
} else {
|
||||||
imagSeries = new MyXYSeries(getImagFunctionName(CalculatorPlotActivity.this.variable), DEFAULT_NUMBER_OF_STEPS * 2);
|
imagSeries = new MyXYSeries(getImagFunctionName(CalculatorPlotActivity.this.variable), DEFAULT_NUMBER_OF_STEPS * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (PlotUtils.addXY(dr.getXAxisMin(), dr.getXAxisMax(), expression, variable, realSeries, imagSeries, true, DEFAULT_NUMBER_OF_STEPS)) {
|
if (PlotUtils.addXY(dr.getXAxisMin(), dr.getXAxisMax(), expression, variable, realSeries, imagSeries, true, DEFAULT_NUMBER_OF_STEPS)) {
|
||||||
if (chart.getDataset().getSeriesCount() <= 1) {
|
if (chart.getDataset().getSeriesCount() <= 1) {
|
||||||
chart.getDataset().addSeries(imagSeries);
|
chart.getDataset().addSeries(imagSeries);
|
||||||
chart.getRenderer().addSeriesRenderer(createImagRenderer());
|
chart.getRenderer().addSeriesRenderer(createImagRenderer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (ArithmeticException e) {
|
} catch (ArithmeticException e) {
|
||||||
// todo serso: translate
|
// todo serso: translate
|
||||||
Toast.makeText(CalculatorPlotActivity.this, "Arithmetic error: " + e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
|
Toast.makeText(CalculatorPlotActivity.this, "Arithmetic error: " + e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
|
||||||
CalculatorPlotActivity.this.finish();
|
CalculatorPlotActivity.this.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pendingOperation.getObject() == this) {
|
if (pendingOperation.getObject() == this) {
|
||||||
graphicalView.repaint();
|
graphicalView.repaint();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
new Handler().postDelayed(pendingOperation.getObject(), millisToWait);
|
new Handler().postDelayed(pendingOperation.getObject(), millisToWait);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static String getImagFunctionName(@NotNull Constant variable) {
|
private static String getImagFunctionName(@NotNull Constant variable) {
|
||||||
return "g(" + variable.getName() +")" + " = " + "Im(ƒ(" + variable.getName() +"))";
|
return "g(" + variable.getName() +")" + " = " + "Im(ƒ(" + variable.getName() +"))";
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static String getRealFunctionName(@NotNull Generic expression, @NotNull Constant variable) {
|
private static String getRealFunctionName(@NotNull Generic expression, @NotNull Constant variable) {
|
||||||
return "ƒ(" + variable.getName() +")" + " = " + expression.toString();
|
return "ƒ(" + variable.getName() +")" + " = " + expression.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final static MutableObject<Runnable> pendingOperation = new MutableObject<Runnable>();
|
private final static MutableObject<Runnable> pendingOperation = new MutableObject<Runnable>();
|
||||||
|
|
||||||
private static XYChart prepareChart(final double minValue, final double maxValue, @NotNull final Generic expression, @NotNull final Constant variable) {
|
private static XYChart prepareChart(final double minValue, final double maxValue, @NotNull final Generic expression, @NotNull final Constant variable) {
|
||||||
final MyXYSeries realSeries = new MyXYSeries(getRealFunctionName(expression, variable), DEFAULT_NUMBER_OF_STEPS * 2);
|
final MyXYSeries realSeries = new MyXYSeries(getRealFunctionName(expression, variable), DEFAULT_NUMBER_OF_STEPS * 2);
|
||||||
final MyXYSeries imagSeries = new MyXYSeries(getImagFunctionName(variable), DEFAULT_NUMBER_OF_STEPS * 2);
|
final MyXYSeries imagSeries = new MyXYSeries(getImagFunctionName(variable), DEFAULT_NUMBER_OF_STEPS * 2);
|
||||||
|
|
||||||
boolean imagExists = PlotUtils.addXY(minValue, maxValue, expression, variable, realSeries, imagSeries, false, DEFAULT_NUMBER_OF_STEPS);
|
boolean imagExists = PlotUtils.addXY(minValue, maxValue, expression, variable, realSeries, imagSeries, false, DEFAULT_NUMBER_OF_STEPS);
|
||||||
|
|
||||||
final XYMultipleSeriesDataset data = new XYMultipleSeriesDataset();
|
final XYMultipleSeriesDataset data = new XYMultipleSeriesDataset();
|
||||||
data.addSeries(realSeries);
|
data.addSeries(realSeries);
|
||||||
if (imagExists) {
|
if (imagExists) {
|
||||||
data.addSeries(imagSeries);
|
data.addSeries(imagSeries);
|
||||||
}
|
}
|
||||||
|
|
||||||
final XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
|
final XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
|
||||||
renderer.setShowGrid(true);
|
renderer.setShowGrid(true);
|
||||||
renderer.setXTitle(variable.getName());
|
renderer.setXTitle(variable.getName());
|
||||||
renderer.setYTitle("f(" + variable.getName() + ")");
|
renderer.setYTitle("f(" + variable.getName() + ")");
|
||||||
renderer.setChartTitleTextSize(20);
|
renderer.setChartTitleTextSize(20);
|
||||||
|
|
||||||
renderer.setZoomEnabled(true);
|
renderer.setZoomEnabled(true);
|
||||||
renderer.setZoomButtonsVisible(true);
|
renderer.setZoomButtonsVisible(true);
|
||||||
|
|
||||||
renderer.addSeriesRenderer(createCommonRenderer());
|
renderer.addSeriesRenderer(createCommonRenderer());
|
||||||
if (imagExists) {
|
if (imagExists) {
|
||||||
renderer.addSeriesRenderer(createImagRenderer());
|
renderer.addSeriesRenderer(createImagRenderer());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CubicLineChart(data, renderer, 0.1f);
|
return new CubicLineChart(data, renderer, 0.1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static XYSeriesRenderer createImagRenderer() {
|
private static XYSeriesRenderer createImagRenderer() {
|
||||||
final XYSeriesRenderer imagRenderer = createCommonRenderer();
|
final XYSeriesRenderer imagRenderer = createCommonRenderer();
|
||||||
imagRenderer.setStroke(BasicStroke.DASHED);
|
imagRenderer.setStroke(BasicStroke.DASHED);
|
||||||
imagRenderer.setColor(Color.LTGRAY);
|
imagRenderer.setColor(Color.LTGRAY);
|
||||||
return imagRenderer;
|
return imagRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object onRetainNonConfigurationInstance() {
|
public Object onRetainNonConfigurationInstance() {
|
||||||
return new PlotBoundaries(chart.getRenderer());
|
return new PlotBoundaries(chart.getRenderer());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class PlotBoundaries implements Serializable {
|
private static final class PlotBoundaries implements Serializable {
|
||||||
|
|
||||||
private final double xMin;
|
private final double xMin;
|
||||||
private final double xMax;
|
private final double xMax;
|
||||||
private final double yMin;
|
private final double yMin;
|
||||||
private final double yMax;
|
private final double yMax;
|
||||||
|
|
||||||
public PlotBoundaries(@NotNull XYMultipleSeriesRenderer renderer) {
|
public PlotBoundaries(@NotNull XYMultipleSeriesRenderer renderer) {
|
||||||
this.xMin = renderer.getXAxisMin();
|
this.xMin = renderer.getXAxisMin();
|
||||||
this.yMin = renderer.getYAxisMin();
|
this.yMin = renderer.getYAxisMin();
|
||||||
this.xMax = renderer.getXAxisMax();
|
this.xMax = renderer.getXAxisMax();
|
||||||
this.yMax = renderer.getYAxisMax();
|
this.yMax = renderer.getYAxisMax();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "PlotBoundaries{" +
|
return "PlotBoundaries{" +
|
||||||
"yMax=" + yMax +
|
"yMax=" + yMax +
|
||||||
", yMin=" + yMin +
|
", yMin=" + yMin +
|
||||||
", xMax=" + xMax +
|
", xMax=" + xMax +
|
||||||
", xMin=" + xMin +
|
", xMin=" + xMin +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static XYSeriesRenderer createCommonRenderer() {
|
private static XYSeriesRenderer createCommonRenderer() {
|
||||||
final XYSeriesRenderer renderer = new XYSeriesRenderer();
|
final XYSeriesRenderer renderer = new XYSeriesRenderer();
|
||||||
renderer.setFillPoints(true);
|
renderer.setFillPoints(true);
|
||||||
renderer.setPointStyle(PointStyle.POINT);
|
renderer.setPointStyle(PointStyle.POINT);
|
||||||
renderer.setLineWidth(3);
|
renderer.setLineWidth(3);
|
||||||
renderer.setColor(Color.WHITE);
|
renderer.setColor(Color.WHITE);
|
||||||
renderer.setStroke(BasicStroke.SOLID);
|
renderer.setStroke(BasicStroke.SOLID);
|
||||||
return renderer;
|
return renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void zoomInClickHandler(@NotNull View v) {
|
public void zoomInClickHandler(@NotNull View v) {
|
||||||
this.graphicalView.zoomIn();
|
this.graphicalView.zoomIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void zoomOutClickHandler(@NotNull View v) {
|
public void zoomOutClickHandler(@NotNull View v) {
|
||||||
this.graphicalView.zoomOut();
|
this.graphicalView.zoomOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static class Input implements Serializable {
|
public static class Input implements Serializable {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private String expression;
|
private String expression;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private String variableName;
|
private String variableName;
|
||||||
|
|
||||||
public Input(@NotNull String expression, @NotNull String variableName) {
|
public Input(@NotNull String expression, @NotNull String variableName) {
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
this.variableName = variableName;
|
this.variableName = variableName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public String getExpression() {
|
public String getExpression() {
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public String getVariableName() {
|
public String getVariableName() {
|
||||||
return variableName;
|
return variableName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,99 +1,99 @@
|
|||||||
package org.solovyev.android.calculator.view;
|
package org.solovyev.android.calculator.view;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.Unit;
|
import org.solovyev.math.units.Unit;
|
||||||
import org.solovyev.android.UnitImpl;
|
import org.solovyev.math.units.UnitImpl;
|
||||||
import org.solovyev.android.calculator.AndroidNumeralBase;
|
import org.solovyev.android.calculator.AndroidNumeralBase;
|
||||||
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.model.CalculatorEngine;
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
import org.solovyev.android.calculator.model.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;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 4/22/12
|
* Date: 4/22/12
|
||||||
* Time: 12:20 AM
|
* Time: 12:20 AM
|
||||||
*/
|
*/
|
||||||
public class NumeralBaseConverterDialog {
|
public class NumeralBaseConverterDialog {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private String initialFromValue;
|
private String initialFromValue;
|
||||||
|
|
||||||
public NumeralBaseConverterDialog(String initialFromValue) {
|
public NumeralBaseConverterDialog(String initialFromValue) {
|
||||||
this.initialFromValue = initialFromValue;
|
this.initialFromValue = initialFromValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void show(@NotNull Context context) {
|
public void show(@NotNull Context context) {
|
||||||
final UnitConverterViewBuilder b = new UnitConverterViewBuilder();
|
final UnitConverterViewBuilder b = new UnitConverterViewBuilder();
|
||||||
b.setFromUnitTypes(Arrays.asList(AndroidNumeralBase.values()));
|
b.setFromUnitTypes(Arrays.asList(AndroidNumeralBase.values()));
|
||||||
b.setToUnitTypes(Arrays.asList(AndroidNumeralBase.values()));
|
b.setToUnitTypes(Arrays.asList(AndroidNumeralBase.values()));
|
||||||
|
|
||||||
if (!StringUtils.isEmpty(initialFromValue)) {
|
if (!StringUtils.isEmpty(initialFromValue)) {
|
||||||
String value = initialFromValue;
|
String value = initialFromValue;
|
||||||
try {
|
try {
|
||||||
value = ToJsclTextProcessor.getInstance().process(value).getExpression();
|
value = ToJsclTextProcessor.getInstance().process(value).getExpression();
|
||||||
b.setFromValue(UnitImpl.newInstance(value, AndroidNumeralBase.valueOf(CalculatorEngine.instance.getEngine().getNumeralBase())));
|
b.setFromValue(UnitImpl.newInstance(value, AndroidNumeralBase.valueOf(CalculatorEngine.instance.getEngine().getNumeralBase())));
|
||||||
} catch (CalculatorParseException e) {
|
} catch (CalculatorParseException e) {
|
||||||
b.setFromValue(UnitImpl.newInstance(value, AndroidNumeralBase.valueOf(CalculatorEngine.instance.getEngine().getNumeralBase())));
|
b.setFromValue(UnitImpl.newInstance(value, AndroidNumeralBase.valueOf(CalculatorEngine.instance.getEngine().getNumeralBase())));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
b.setFromValue(UnitImpl.newInstance("", AndroidNumeralBase.valueOf(CalculatorEngine.instance.getEngine().getNumeralBase())));
|
b.setFromValue(UnitImpl.newInstance("", AndroidNumeralBase.valueOf(CalculatorEngine.instance.getEngine().getNumeralBase())));
|
||||||
}
|
}
|
||||||
|
|
||||||
b.setConverter(AndroidNumeralBase.getConverter());
|
b.setConverter(AndroidNumeralBase.getConverter());
|
||||||
|
|
||||||
final MutableObject<AlertDialog> alertDialogHolder = new MutableObject<AlertDialog>();
|
final MutableObject<AlertDialog> alertDialogHolder = new MutableObject<AlertDialog>();
|
||||||
b.setOkButtonOnClickListener(new View.OnClickListener() {
|
b.setOkButtonOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
final AlertDialog alertDialog = alertDialogHolder.getObject();
|
final AlertDialog alertDialog = alertDialogHolder.getObject();
|
||||||
if (alertDialog != null) {
|
if (alertDialog != null) {
|
||||||
alertDialog.dismiss();
|
alertDialog.dismiss();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
b.setCustomButtonData(new UnitConverterViewBuilder.CustomButtonData(context.getString(R.string.c_use_short), new UnitConverterViewBuilder.CustomButtonOnClickListener() {
|
b.setCustomButtonData(new UnitConverterViewBuilder.CustomButtonData(context.getString(R.string.c_use_short), new UnitConverterViewBuilder.CustomButtonOnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(@NotNull Unit<String> fromUnits, @NotNull Unit<String> toUnits) {
|
public void onClick(@NotNull Unit<String> fromUnits, @NotNull Unit<String> toUnits) {
|
||||||
String toUnitsValue = toUnits.getValue();
|
String toUnitsValue = toUnits.getValue();
|
||||||
|
|
||||||
if (!toUnits.getUnitType().equals(AndroidNumeralBase.valueOf(CalculatorEngine.instance.getEngine().getNumeralBase()))) {
|
if (!toUnits.getUnitType().equals(AndroidNumeralBase.valueOf(CalculatorEngine.instance.getEngine().getNumeralBase()))) {
|
||||||
toUnitsValue = ((AndroidNumeralBase) toUnits.getUnitType()).getNumeralBase().getJsclPrefix() + toUnitsValue;
|
toUnitsValue = ((AndroidNumeralBase) toUnits.getUnitType()).getNumeralBase().getJsclPrefix() + toUnitsValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
CalculatorModel.instance.processDigitButtonAction(toUnitsValue, false);
|
CalculatorModel.instance.processDigitButtonAction(toUnitsValue, false);
|
||||||
final AlertDialog alertDialog = alertDialogHolder.getObject();
|
final AlertDialog alertDialog = alertDialogHolder.getObject();
|
||||||
if (alertDialog != null) {
|
if (alertDialog != null) {
|
||||||
alertDialog.dismiss();
|
alertDialog.dismiss();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
final AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
|
final AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
|
||||||
alertBuilder.setView(b.build(context));
|
alertBuilder.setView(b.build(context));
|
||||||
alertBuilder.setTitle(R.string.c_conversion_tool);
|
alertBuilder.setTitle(R.string.c_conversion_tool);
|
||||||
|
|
||||||
final AlertDialog alertDialog = alertBuilder.create();
|
final AlertDialog alertDialog = alertBuilder.create();
|
||||||
|
|
||||||
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
|
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
|
||||||
lp.copyFrom(alertDialog.getWindow().getAttributes());
|
lp.copyFrom(alertDialog.getWindow().getAttributes());
|
||||||
|
|
||||||
lp.width = WindowManager.LayoutParams.FILL_PARENT;
|
lp.width = WindowManager.LayoutParams.FILL_PARENT;
|
||||||
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||||
|
|
||||||
alertDialogHolder.setObject(alertDialog);
|
alertDialogHolder.setObject(alertDialog);
|
||||||
alertDialog.show();
|
alertDialog.show();
|
||||||
alertDialog.getWindow().setAttributes(lp);
|
alertDialog.getWindow().setAttributes(lp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,238 +1,243 @@
|
|||||||
/*
|
/*
|
||||||
* 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.view;
|
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.math.MathType;
|
import org.solovyev.android.calculator.AbstractNumberBuilder;
|
||||||
import org.solovyev.android.calculator.model.*;
|
import org.solovyev.android.calculator.CalculatorParseException;
|
||||||
import org.solovyev.common.MutableObject;
|
import org.solovyev.android.calculator.LiteNumberBuilder;
|
||||||
|
import org.solovyev.android.calculator.NumberBuilder;
|
||||||
import java.util.HashMap;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
import java.util.Map;
|
import org.solovyev.android.calculator.model.*;
|
||||||
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
/**
|
import org.solovyev.common.MutableObject;
|
||||||
* User: serso
|
|
||||||
* Date: 10/12/11
|
import java.util.HashMap;
|
||||||
* Time: 9:47 PM
|
import java.util.Map;
|
||||||
*/
|
|
||||||
public class TextHighlighter implements TextProcessor<TextHighlighter.Result, String> {
|
/**
|
||||||
|
* User: serso
|
||||||
private static final Map<String, String> nbFontAttributes = new HashMap<String, String>();
|
* Date: 10/12/11
|
||||||
|
* Time: 9:47 PM
|
||||||
static {
|
*/
|
||||||
nbFontAttributes.put("color", "#008000");
|
public class TextHighlighter implements TextProcessor<TextHighlighter.Result, String> {
|
||||||
}
|
|
||||||
|
private static final Map<String, String> nbFontAttributes = new HashMap<String, String>();
|
||||||
@NotNull
|
|
||||||
public final MathContext mathContext;
|
static {
|
||||||
|
nbFontAttributes.put("color", "#008000");
|
||||||
public static class Result implements CharSequence {
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final String string;
|
public final MathContext mathContext;
|
||||||
|
|
||||||
private final int offset;
|
public static class Result implements CharSequence {
|
||||||
|
|
||||||
public Result(@NotNull String string, int offset) {
|
@NotNull
|
||||||
this.string = string;
|
private final String string;
|
||||||
this.offset = offset;
|
|
||||||
}
|
private final int offset;
|
||||||
|
|
||||||
@Override
|
public Result(@NotNull String string, int offset) {
|
||||||
public int length() {
|
this.string = string;
|
||||||
return string.length();
|
this.offset = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char charAt(int i) {
|
public int length() {
|
||||||
return string.charAt(i);
|
return string.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharSequence subSequence(int i, int i1) {
|
public char charAt(int i) {
|
||||||
return string.subSequence(i, i1);
|
return string.charAt(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public CharSequence subSequence(int i, int i1) {
|
||||||
return string;
|
return string.subSequence(i, i1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOffset() {
|
@Override
|
||||||
return offset;
|
public String toString() {
|
||||||
}
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final int color;
|
public int getOffset() {
|
||||||
private final int colorRed;
|
return offset;
|
||||||
private final int colorGreen;
|
}
|
||||||
private final int colorBlue;
|
}
|
||||||
private final boolean formatNumber;
|
|
||||||
|
private final int color;
|
||||||
public TextHighlighter(int baseColor, boolean formatNumber, @NotNull MathContext mathContext) {
|
private final int colorRed;
|
||||||
this.color = baseColor;
|
private final int colorGreen;
|
||||||
this.formatNumber = formatNumber;
|
private final int colorBlue;
|
||||||
this.mathContext = mathContext;
|
private final boolean formatNumber;
|
||||||
//this.colorRed = Color.red(baseColor);
|
|
||||||
this.colorRed = (baseColor >> 16) & 0xFF;
|
public TextHighlighter(int baseColor, boolean formatNumber, @NotNull MathContext mathContext) {
|
||||||
//this.colorGreen = Color.green(baseColor);
|
this.color = baseColor;
|
||||||
this.colorGreen = (color >> 8) & 0xFF;
|
this.formatNumber = formatNumber;
|
||||||
//this.colorBlue = Color.blue(baseColor);
|
this.mathContext = mathContext;
|
||||||
this.colorBlue = color & 0xFF;
|
//this.colorRed = Color.red(baseColor);
|
||||||
}
|
this.colorRed = (baseColor >> 16) & 0xFF;
|
||||||
|
//this.colorGreen = Color.green(baseColor);
|
||||||
@NotNull
|
this.colorGreen = (color >> 8) & 0xFF;
|
||||||
@Override
|
//this.colorBlue = Color.blue(baseColor);
|
||||||
public Result process(@NotNull String text) throws CalculatorParseException {
|
this.colorBlue = color & 0xFF;
|
||||||
final String result;
|
}
|
||||||
|
|
||||||
int maxNumberOfOpenGroupSymbols = 0;
|
@NotNull
|
||||||
int numberOfOpenGroupSymbols = 0;
|
@Override
|
||||||
|
public Result process(@NotNull String text) throws CalculatorParseException {
|
||||||
final StringBuilder text1 = new StringBuilder();
|
final String result;
|
||||||
|
|
||||||
int resultOffset = 0;
|
int maxNumberOfOpenGroupSymbols = 0;
|
||||||
|
int numberOfOpenGroupSymbols = 0;
|
||||||
final AbstractNumberBuilder numberBuilder;
|
|
||||||
if (!formatNumber) {
|
final StringBuilder text1 = new StringBuilder();
|
||||||
numberBuilder = new LiteNumberBuilder(CalculatorEngine.instance.getEngine());
|
|
||||||
} else {
|
int resultOffset = 0;
|
||||||
numberBuilder = new NumberBuilder(CalculatorEngine.instance.getEngine());
|
|
||||||
}
|
final AbstractNumberBuilder numberBuilder;
|
||||||
for (int i = 0; i < text.length(); i++) {
|
if (!formatNumber) {
|
||||||
MathType.Result mathType = MathType.getType(text, i, numberBuilder.isHexMode());
|
numberBuilder = new LiteNumberBuilder(CalculatorEngine.instance.getEngine());
|
||||||
|
} else {
|
||||||
if (numberBuilder instanceof NumberBuilder) {
|
numberBuilder = new NumberBuilder(CalculatorEngine.instance.getEngine());
|
||||||
final MutableObject<Integer> numberOffset = new MutableObject<Integer>(0);
|
}
|
||||||
((NumberBuilder) numberBuilder).process(text1, mathType, numberOffset);
|
for (int i = 0; i < text.length(); i++) {
|
||||||
resultOffset += numberOffset.getObject();
|
MathType.Result mathType = MathType.getType(text, i, numberBuilder.isHexMode());
|
||||||
} else {
|
|
||||||
((LiteNumberBuilder) numberBuilder).process(mathType);
|
if (numberBuilder instanceof NumberBuilder) {
|
||||||
}
|
final MutableObject<Integer> numberOffset = new MutableObject<Integer>(0);
|
||||||
|
((NumberBuilder) numberBuilder).process(text1, mathType, numberOffset);
|
||||||
final String match = mathType.getMatch();
|
resultOffset += numberOffset.getObject();
|
||||||
switch (mathType.getMathType()) {
|
} else {
|
||||||
case open_group_symbol:
|
((LiteNumberBuilder) numberBuilder).process(mathType);
|
||||||
numberOfOpenGroupSymbols++;
|
}
|
||||||
maxNumberOfOpenGroupSymbols = Math.max(maxNumberOfOpenGroupSymbols, numberOfOpenGroupSymbols);
|
|
||||||
text1.append(text.charAt(i));
|
final String match = mathType.getMatch();
|
||||||
break;
|
switch (mathType.getMathType()) {
|
||||||
case close_group_symbol:
|
case open_group_symbol:
|
||||||
numberOfOpenGroupSymbols--;
|
numberOfOpenGroupSymbols++;
|
||||||
text1.append(text.charAt(i));
|
maxNumberOfOpenGroupSymbols = Math.max(maxNumberOfOpenGroupSymbols, numberOfOpenGroupSymbols);
|
||||||
break;
|
text1.append(text.charAt(i));
|
||||||
case operator:
|
break;
|
||||||
text1.append(match);
|
case close_group_symbol:
|
||||||
if (match.length() > 1) {
|
numberOfOpenGroupSymbols--;
|
||||||
i += match.length() - 1;
|
text1.append(text.charAt(i));
|
||||||
}
|
break;
|
||||||
break;
|
case operator:
|
||||||
case function:
|
text1.append(match);
|
||||||
i = processHighlightedText(text1, i, match, "i", null);
|
if (match.length() > 1) {
|
||||||
break;
|
i += match.length() - 1;
|
||||||
case constant:
|
}
|
||||||
i = processHighlightedText(text1, i, match, "b", null);
|
break;
|
||||||
break;
|
case function:
|
||||||
case numeral_base:
|
i = processHighlightedText(text1, i, match, "i", null);
|
||||||
i = processHighlightedText(text1, i, match, "b", null);
|
break;
|
||||||
break;
|
case constant:
|
||||||
default:
|
i = processHighlightedText(text1, i, match, "b", null);
|
||||||
if (mathType.getMathType() == MathType.text || match.length() <= 1) {
|
break;
|
||||||
text1.append(text.charAt(i));
|
case numeral_base:
|
||||||
} else {
|
i = processHighlightedText(text1, i, match, "b", null);
|
||||||
text1.append(match);
|
break;
|
||||||
i += match.length() - 1;
|
default:
|
||||||
}
|
if (mathType.getMathType() == MathType.text || match.length() <= 1) {
|
||||||
}
|
text1.append(text.charAt(i));
|
||||||
}
|
} else {
|
||||||
|
text1.append(match);
|
||||||
if (numberBuilder instanceof NumberBuilder) {
|
i += match.length() - 1;
|
||||||
final MutableObject<Integer> numberOffset = new MutableObject<Integer>(0);
|
}
|
||||||
((NumberBuilder) numberBuilder).processNumber(text1, numberOffset);
|
}
|
||||||
resultOffset += numberOffset.getObject();
|
}
|
||||||
}
|
|
||||||
|
if (numberBuilder instanceof NumberBuilder) {
|
||||||
if (maxNumberOfOpenGroupSymbols > 0) {
|
final MutableObject<Integer> numberOffset = new MutableObject<Integer>(0);
|
||||||
|
((NumberBuilder) numberBuilder).processNumber(text1, numberOffset);
|
||||||
final StringBuilder text2 = new StringBuilder();
|
resultOffset += numberOffset.getObject();
|
||||||
|
}
|
||||||
String s = text1.toString();
|
|
||||||
int i = processBracketGroup(text2, s, 0, 0, maxNumberOfOpenGroupSymbols);
|
if (maxNumberOfOpenGroupSymbols > 0) {
|
||||||
for (; i < s.length(); i++) {
|
|
||||||
text2.append(s.charAt(i));
|
final StringBuilder text2 = new StringBuilder();
|
||||||
}
|
|
||||||
|
String s = text1.toString();
|
||||||
//Log.d(CalculatorEditor.class.getName(), text2.toString());
|
int i = processBracketGroup(text2, s, 0, 0, maxNumberOfOpenGroupSymbols);
|
||||||
|
for (; i < s.length(); i++) {
|
||||||
result = text2.toString();
|
text2.append(s.charAt(i));
|
||||||
} else {
|
}
|
||||||
result = text1.toString();
|
|
||||||
}
|
//Log.d(CalculatorEditor.class.getName(), text2.toString());
|
||||||
|
|
||||||
return new Result(result, resultOffset);
|
result = text2.toString();
|
||||||
}
|
} else {
|
||||||
|
result = text1.toString();
|
||||||
private int processHighlightedText(@NotNull StringBuilder result, int i, @NotNull String match, @NotNull String tag, @Nullable Map<String, String> tagAttributes) {
|
}
|
||||||
result.append("<").append(tag);
|
|
||||||
|
return new Result(result, resultOffset);
|
||||||
if (tagAttributes != null) {
|
}
|
||||||
for (Map.Entry<String, String> entry : tagAttributes.entrySet()) {
|
|
||||||
// attr1="attr1_value" attr2="attr2_value"
|
private int processHighlightedText(@NotNull StringBuilder result, int i, @NotNull String match, @NotNull String tag, @Nullable Map<String, String> tagAttributes) {
|
||||||
result.append(" ").append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
|
result.append("<").append(tag);
|
||||||
}
|
|
||||||
}
|
if (tagAttributes != null) {
|
||||||
|
for (Map.Entry<String, String> entry : tagAttributes.entrySet()) {
|
||||||
result.append(">").append(match).append("</").append(tag).append(">");
|
// attr1="attr1_value" attr2="attr2_value"
|
||||||
if (match.length() > 1) {
|
result.append(" ").append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
|
||||||
return i + match.length() - 1;
|
}
|
||||||
} else {
|
}
|
||||||
return i;
|
|
||||||
}
|
result.append(">").append(match).append("</").append(tag).append(">");
|
||||||
}
|
if (match.length() > 1) {
|
||||||
|
return i + match.length() - 1;
|
||||||
private int processBracketGroup(@NotNull StringBuilder result, @NotNull String s, int i, int numberOfOpenings, int maxNumberOfGroups) {
|
} else {
|
||||||
|
return i;
|
||||||
result.append("<font color=\"").append(getColor(maxNumberOfGroups, numberOfOpenings)).append("\">");
|
}
|
||||||
|
}
|
||||||
for (; i < s.length(); i++) {
|
|
||||||
char ch = s.charAt(i);
|
private int processBracketGroup(@NotNull StringBuilder result, @NotNull String s, int i, int numberOfOpenings, int maxNumberOfGroups) {
|
||||||
|
|
||||||
if (MathType.open_group_symbol.getTokens().contains(String.valueOf(ch))) {
|
result.append("<font color=\"").append(getColor(maxNumberOfGroups, numberOfOpenings)).append("\">");
|
||||||
result.append(ch);
|
|
||||||
result.append("</font>");
|
for (; i < s.length(); i++) {
|
||||||
i = processBracketGroup(result, s, i + 1, numberOfOpenings + 1, maxNumberOfGroups);
|
char ch = s.charAt(i);
|
||||||
result.append("<font color=\"").append(getColor(maxNumberOfGroups, numberOfOpenings)).append("\">");
|
|
||||||
if (i < s.length() && MathType.close_group_symbol.getTokens().contains(String.valueOf(s.charAt(i)))) {
|
if (MathType.open_group_symbol.getTokens().contains(String.valueOf(ch))) {
|
||||||
result.append(s.charAt(i));
|
result.append(ch);
|
||||||
}
|
result.append("</font>");
|
||||||
} else if (MathType.close_group_symbol.getTokens().contains(String.valueOf(ch))) {
|
i = processBracketGroup(result, s, i + 1, numberOfOpenings + 1, maxNumberOfGroups);
|
||||||
break;
|
result.append("<font color=\"").append(getColor(maxNumberOfGroups, numberOfOpenings)).append("\">");
|
||||||
} else {
|
if (i < s.length() && MathType.close_group_symbol.getTokens().contains(String.valueOf(s.charAt(i)))) {
|
||||||
result.append(ch);
|
result.append(s.charAt(i));
|
||||||
}
|
}
|
||||||
}
|
} else if (MathType.close_group_symbol.getTokens().contains(String.valueOf(ch))) {
|
||||||
|
break;
|
||||||
result.append("</font>");
|
} else {
|
||||||
|
result.append(ch);
|
||||||
|
}
|
||||||
return i;
|
}
|
||||||
}
|
|
||||||
|
result.append("</font>");
|
||||||
private String getColor(int totalNumberOfOpenings, int numberOfOpenings) {
|
|
||||||
double c = 0.8;
|
|
||||||
|
return i;
|
||||||
int offset = ((int) (255 * c)) * numberOfOpenings / (totalNumberOfOpenings + 1);
|
}
|
||||||
|
|
||||||
// for tests:
|
private String getColor(int totalNumberOfOpenings, int numberOfOpenings) {
|
||||||
// innt result = Color.rgb(BASE_COLOUR_RED_COMPONENT - offset, BASE_COLOUR_GREEN_COMPONENT - offset, BASE_COLOUR_BLUE_COMPONENT - offset);
|
double c = 0.8;
|
||||||
int result = (0xFF << 24) | ((colorRed - offset) << 16) | ((colorGreen - offset) << 8) | (colorBlue - offset);
|
|
||||||
|
int offset = ((int) (255 * c)) * numberOfOpenings / (totalNumberOfOpenings + 1);
|
||||||
return "#" + Integer.toHexString(result).substring(2);
|
|
||||||
}
|
// for tests:
|
||||||
}
|
// innt result = Color.rgb(BASE_COLOUR_RED_COMPONENT - offset, BASE_COLOUR_GREEN_COMPONENT - offset, BASE_COLOUR_BLUE_COMPONENT - offset);
|
||||||
|
int result = (0xFF << 24) | ((colorRed - offset) << 16) | ((colorGreen - offset) << 8) | (colorBlue - offset);
|
||||||
|
|
||||||
|
return "#" + Integer.toHexString(result).substring(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -10,14 +10,14 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.*;
|
import android.widget.*;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.Unit;
|
import org.solovyev.android.calculator.CalculatorImpl;
|
||||||
import org.solovyev.android.UnitConverter;
|
import org.solovyev.math.units.Unit;
|
||||||
import org.solovyev.android.UnitImpl;
|
import org.solovyev.math.units.UnitConverter;
|
||||||
import org.solovyev.android.UnitType;
|
import org.solovyev.math.units.UnitImpl;
|
||||||
|
import org.solovyev.math.units.UnitType;
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
import org.solovyev.android.view.ViewBuilder;
|
import org.solovyev.android.view.ViewBuilder;
|
||||||
import org.solovyev.android.view.ViewFromLayoutBuilder;
|
import org.solovyev.android.view.ViewFromLayoutBuilder;
|
||||||
import org.solovyev.common.text.StringUtils;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -173,47 +173,12 @@ public class UnitConverterViewBuilder implements ViewBuilder<View> {
|
|||||||
|
|
||||||
final String from = fromEditText.getText().toString();
|
final String from = fromEditText.getText().toString();
|
||||||
try {
|
try {
|
||||||
toEditText.setText(doConversion(converter, from, getFromUnitType(main), getToUnitType(main)));
|
toEditText.setText(CalculatorImpl.doConversion(converter, from, getFromUnitType(main), getToUnitType(main)));
|
||||||
} catch (ConversionException e) {
|
} catch (CalculatorImpl.ConversionException e) {
|
||||||
toEditText.setText(context.getString(R.string.c_error));
|
toEditText.setText(context.getString(R.string.c_error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class ConversionException extends Exception {
|
|
||||||
private ConversionException() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private ConversionException(Throwable throwable) {
|
|
||||||
super(throwable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static String doConversion(@NotNull UnitConverter<String> converter,
|
|
||||||
@Nullable String from,
|
|
||||||
@NotNull UnitType<String> fromUnitType,
|
|
||||||
@NotNull UnitType<String> toUnitType) throws ConversionException{
|
|
||||||
final String result;
|
|
||||||
|
|
||||||
if (StringUtils.isEmpty(from)) {
|
|
||||||
result = "";
|
|
||||||
} else {
|
|
||||||
|
|
||||||
String to = null;
|
|
||||||
try {
|
|
||||||
if (converter.isSupported(fromUnitType, toUnitType)) {
|
|
||||||
to = converter.convert(UnitImpl.newInstance(from, fromUnitType), toUnitType).getValue();
|
|
||||||
}
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
throw new ConversionException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = to;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static Unit<String> getToUnit(@NotNull View main) {
|
private static Unit<String> getToUnit(@NotNull View main) {
|
||||||
final EditText toUnits = (EditText) main.findViewById(R.id.units_to);
|
final EditText toUnits = (EditText) main.findViewById(R.id.units_to);
|
||||||
|
@ -1,70 +1,72 @@
|
|||||||
package org.solovyev.android;
|
package org.solovyev.android;
|
||||||
|
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.solovyev.android.calculator.AndroidNumeralBase;
|
import org.solovyev.android.calculator.AndroidNumeralBase;
|
||||||
|
import org.solovyev.math.units.Unit;
|
||||||
import java.util.Date;
|
import org.solovyev.math.units.UnitConverter;
|
||||||
import java.util.Random;
|
|
||||||
|
import java.util.Date;
|
||||||
/**
|
import java.util.Random;
|
||||||
* User: serso
|
|
||||||
* Date: 4/21/12
|
/**
|
||||||
* Time: 8:24 PM
|
* User: serso
|
||||||
*/
|
* Date: 4/21/12
|
||||||
public class AndroidNumeralBaseTest {
|
* Time: 8:24 PM
|
||||||
|
*/
|
||||||
@NotNull
|
public class AndroidNumeralBaseTest {
|
||||||
private final UnitConverter c = AndroidNumeralBase.getConverter();
|
|
||||||
|
@NotNull
|
||||||
@Test
|
private final UnitConverter c = AndroidNumeralBase.getConverter();
|
||||||
public void testIsSupported() throws Exception {
|
|
||||||
Assert.assertTrue(c.isSupported(AndroidNumeralBase.bin, AndroidNumeralBase.dec));
|
@Test
|
||||||
}
|
public void testIsSupported() throws Exception {
|
||||||
|
Assert.assertTrue(c.isSupported(AndroidNumeralBase.bin, AndroidNumeralBase.dec));
|
||||||
@Test
|
}
|
||||||
public void testConvertFromDec() throws Exception {
|
|
||||||
|
@Test
|
||||||
Assert.assertEquals("101", c.convert(AndroidNumeralBase.dec.createUnit("5"), AndroidNumeralBase.bin).getValue());
|
public void testConvertFromDec() throws Exception {
|
||||||
Assert.assertEquals("1", c.convert(AndroidNumeralBase.dec.createUnit("1"), AndroidNumeralBase.bin).getValue());
|
|
||||||
Assert.assertEquals("0", c.convert(AndroidNumeralBase.dec.createUnit("0"), AndroidNumeralBase.bin).getValue());
|
Assert.assertEquals("101", c.convert(AndroidNumeralBase.dec.createUnit("5"), AndroidNumeralBase.bin).getValue());
|
||||||
Assert.assertEquals("1111100111", c.convert(AndroidNumeralBase.dec.createUnit("999"), AndroidNumeralBase.bin).getValue());
|
Assert.assertEquals("1", c.convert(AndroidNumeralBase.dec.createUnit("1"), AndroidNumeralBase.bin).getValue());
|
||||||
|
Assert.assertEquals("0", c.convert(AndroidNumeralBase.dec.createUnit("0"), AndroidNumeralBase.bin).getValue());
|
||||||
Assert.assertEquals("A23", c.convert(AndroidNumeralBase.dec.createUnit("2595"), AndroidNumeralBase.hex).getValue());
|
Assert.assertEquals("1111100111", c.convert(AndroidNumeralBase.dec.createUnit("999"), AndroidNumeralBase.bin).getValue());
|
||||||
Assert.assertEquals("AEE", c.convert(AndroidNumeralBase.dec.createUnit("2798"), AndroidNumeralBase.hex).getValue());
|
|
||||||
Assert.assertEquals("15", c.convert(AndroidNumeralBase.dec.createUnit("21"), AndroidNumeralBase.hex).getValue());
|
Assert.assertEquals("A23", c.convert(AndroidNumeralBase.dec.createUnit("2595"), AndroidNumeralBase.hex).getValue());
|
||||||
Assert.assertEquals("0", c.convert(AndroidNumeralBase.dec.createUnit("0"), AndroidNumeralBase.hex).getValue());
|
Assert.assertEquals("AEE", c.convert(AndroidNumeralBase.dec.createUnit("2798"), AndroidNumeralBase.hex).getValue());
|
||||||
Assert.assertEquals("3E7", c.convert(AndroidNumeralBase.dec.createUnit("999"), AndroidNumeralBase.hex).getValue());
|
Assert.assertEquals("15", c.convert(AndroidNumeralBase.dec.createUnit("21"), AndroidNumeralBase.hex).getValue());
|
||||||
|
Assert.assertEquals("0", c.convert(AndroidNumeralBase.dec.createUnit("0"), AndroidNumeralBase.hex).getValue());
|
||||||
Assert.assertEquals("76", c.convert(AndroidNumeralBase.dec.createUnit("62"), AndroidNumeralBase.oct).getValue());
|
Assert.assertEquals("3E7", c.convert(AndroidNumeralBase.dec.createUnit("999"), AndroidNumeralBase.hex).getValue());
|
||||||
Assert.assertEquals("12", c.convert(AndroidNumeralBase.dec.createUnit("10"), AndroidNumeralBase.oct).getValue());
|
|
||||||
Assert.assertEquals("15", c.convert(AndroidNumeralBase.dec.createUnit("13"), AndroidNumeralBase.oct).getValue());
|
Assert.assertEquals("76", c.convert(AndroidNumeralBase.dec.createUnit("62"), AndroidNumeralBase.oct).getValue());
|
||||||
Assert.assertEquals("0", c.convert(AndroidNumeralBase.dec.createUnit("0"), AndroidNumeralBase.oct).getValue());
|
Assert.assertEquals("12", c.convert(AndroidNumeralBase.dec.createUnit("10"), AndroidNumeralBase.oct).getValue());
|
||||||
Assert.assertEquals("10445", c.convert(AndroidNumeralBase.dec.createUnit("4389"), AndroidNumeralBase.oct).getValue());
|
Assert.assertEquals("15", c.convert(AndroidNumeralBase.dec.createUnit("13"), AndroidNumeralBase.oct).getValue());
|
||||||
}
|
Assert.assertEquals("0", c.convert(AndroidNumeralBase.dec.createUnit("0"), AndroidNumeralBase.oct).getValue());
|
||||||
|
Assert.assertEquals("10445", c.convert(AndroidNumeralBase.dec.createUnit("4389"), AndroidNumeralBase.oct).getValue());
|
||||||
@Test
|
}
|
||||||
public void testRandomConvert() throws Exception {
|
|
||||||
final Random random = new Random(new Date().getTime());
|
@Test
|
||||||
for (int i = 0; i < 100000; i++) {
|
public void testRandomConvert() throws Exception {
|
||||||
final String value = String.valueOf(random.nextInt());
|
final Random random = new Random(new Date().getTime());
|
||||||
Assert.assertEquals(value, convertChain(value, AndroidNumeralBase.dec, AndroidNumeralBase.oct, AndroidNumeralBase.oct, AndroidNumeralBase.bin, AndroidNumeralBase.dec));
|
for (int i = 0; i < 100000; i++) {
|
||||||
Assert.assertEquals(value, convertChain(value, AndroidNumeralBase.dec, AndroidNumeralBase.bin, AndroidNumeralBase.hex, AndroidNumeralBase.dec, AndroidNumeralBase.dec));
|
final String value = String.valueOf(random.nextInt());
|
||||||
Assert.assertEquals(value, convertChain(value, AndroidNumeralBase.dec, AndroidNumeralBase.dec, AndroidNumeralBase.hex, AndroidNumeralBase.oct, AndroidNumeralBase.dec));
|
Assert.assertEquals(value, convertChain(value, AndroidNumeralBase.dec, AndroidNumeralBase.oct, AndroidNumeralBase.oct, AndroidNumeralBase.bin, AndroidNumeralBase.dec));
|
||||||
Assert.assertEquals(value, convertChain(value, AndroidNumeralBase.dec, AndroidNumeralBase.hex, AndroidNumeralBase.bin, AndroidNumeralBase.oct, AndroidNumeralBase.dec));
|
Assert.assertEquals(value, convertChain(value, AndroidNumeralBase.dec, AndroidNumeralBase.bin, AndroidNumeralBase.hex, AndroidNumeralBase.dec, AndroidNumeralBase.dec));
|
||||||
|
Assert.assertEquals(value, convertChain(value, AndroidNumeralBase.dec, AndroidNumeralBase.dec, AndroidNumeralBase.hex, AndroidNumeralBase.oct, AndroidNumeralBase.dec));
|
||||||
}
|
Assert.assertEquals(value, convertChain(value, AndroidNumeralBase.dec, AndroidNumeralBase.hex, AndroidNumeralBase.bin, AndroidNumeralBase.oct, AndroidNumeralBase.dec));
|
||||||
}
|
|
||||||
|
}
|
||||||
@NotNull
|
}
|
||||||
private String convertChain(@NotNull String value, @NotNull AndroidNumeralBase baseAndroid, @NotNull AndroidNumeralBase... typeAndroids) {
|
|
||||||
Unit<String> unit = baseAndroid.createUnit(value);
|
@NotNull
|
||||||
|
private String convertChain(@NotNull String value, @NotNull AndroidNumeralBase baseAndroid, @NotNull AndroidNumeralBase... typeAndroids) {
|
||||||
for (AndroidNumeralBase typeAndroid : typeAndroids) {
|
Unit<String> unit = baseAndroid.createUnit(value);
|
||||||
unit = AndroidNumeralBase.getConverter().convert(unit, typeAndroid);
|
|
||||||
}
|
for (AndroidNumeralBase typeAndroid : typeAndroids) {
|
||||||
|
unit = AndroidNumeralBase.getConverter().convert(unit, typeAndroid);
|
||||||
return unit.getValue();
|
}
|
||||||
}
|
|
||||||
}
|
return unit.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,137 +1,137 @@
|
|||||||
/*
|
/*
|
||||||
* 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;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import jscl.JsclMathEngine;
|
import jscl.JsclMathEngine;
|
||||||
import jscl.MathEngine;
|
import jscl.MathEngine;
|
||||||
import jscl.NumeralBase;
|
import jscl.NumeralBase;
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.solovyev.android.calculator.model.CalculatorEngine;
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
import org.solovyev.android.calculator.model.TextProcessor;
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
import org.solovyev.android.calculator.view.TextHighlighter;
|
import org.solovyev.android.calculator.view.TextHighlighter;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 10/12/11
|
* Date: 10/12/11
|
||||||
* Time: 10:07 PM
|
* Time: 10:07 PM
|
||||||
*/
|
*/
|
||||||
public class TextHighlighterTest {
|
public class TextHighlighterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProcess() throws Exception {
|
public void testProcess() throws Exception {
|
||||||
TextProcessor<?, String> textHighlighter = new TextHighlighter(0, false, JsclMathEngine.instance);
|
TextProcessor<?, String> textHighlighter = new TextHighlighter(0, false, JsclMathEngine.instance);
|
||||||
|
|
||||||
final Random random = new Random(new Date().getTime());
|
final Random random = new Random(new Date().getTime());
|
||||||
for (int i = 0; i < 1000; i++) {
|
for (int i = 0; i < 1000; i++) {
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
for (int j = 0; j < 1000; j++) {
|
for (int j = 0; j < 1000; j++) {
|
||||||
sb.append(random.nextBoolean() ? "(" : ")");
|
sb.append(random.nextBoolean() ? "(" : ")");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
textHighlighter.process(sb.toString());
|
textHighlighter.process(sb.toString());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println(sb.toString());
|
System.out.println(sb.toString());
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.assertEquals("<font color=\"#000000\"></font>)(((())())", textHighlighter.process(")(((())())").toString());
|
Assert.assertEquals("<font color=\"#000000\"></font>)(((())())", textHighlighter.process(")(((())())").toString());
|
||||||
Assert.assertEquals(")", textHighlighter.process(")").toString());
|
Assert.assertEquals(")", textHighlighter.process(")").toString());
|
||||||
Assert.assertEquals(")()(", textHighlighter.process(")()(").toString());
|
Assert.assertEquals(")()(", textHighlighter.process(")()(").toString());
|
||||||
|
|
||||||
textHighlighter = new TextHighlighter(0, true, JsclMathEngine.instance);
|
textHighlighter = new TextHighlighter(0, true, JsclMathEngine.instance);
|
||||||
Assert.assertEquals("1 000 000", textHighlighter.process("1000000").toString());
|
Assert.assertEquals("1 000 000", textHighlighter.process("1000000").toString());
|
||||||
Assert.assertEquals("1 000 000", textHighlighter.process("1000000").toString());
|
Assert.assertEquals("1 000 000", textHighlighter.process("1000000").toString());
|
||||||
Assert.assertEquals("0.1E3", textHighlighter.process("0.1E3").toString());
|
Assert.assertEquals("0.1E3", textHighlighter.process("0.1E3").toString());
|
||||||
Assert.assertEquals("1E3", textHighlighter.process("1E3").toString());
|
Assert.assertEquals("1E3", textHighlighter.process("1E3").toString());
|
||||||
Assert.assertEquals("2<b>0x:</b>", textHighlighter.process("20x:").toString());
|
Assert.assertEquals("2<b>0x:</b>", textHighlighter.process("20x:").toString());
|
||||||
Assert.assertEquals("20g", textHighlighter.process("20g").toString());
|
Assert.assertEquals("20g", textHighlighter.process("20g").toString());
|
||||||
Assert.assertEquals("22g", textHighlighter.process("22g").toString());
|
Assert.assertEquals("22g", textHighlighter.process("22g").toString());
|
||||||
Assert.assertEquals("20ю", textHighlighter.process("20ю").toString());
|
Assert.assertEquals("20ю", textHighlighter.process("20ю").toString());
|
||||||
Assert.assertEquals("20ъ", textHighlighter.process("20ъ").toString());
|
Assert.assertEquals("20ъ", textHighlighter.process("20ъ").toString());
|
||||||
Assert.assertEquals("3!!", textHighlighter.process("3!!").toString());
|
Assert.assertEquals("3!!", textHighlighter.process("3!!").toString());
|
||||||
Assert.assertEquals("2", textHighlighter.process("2").toString());
|
Assert.assertEquals("2", textHighlighter.process("2").toString());
|
||||||
Assert.assertEquals("21", textHighlighter.process("21").toString());
|
Assert.assertEquals("21", textHighlighter.process("21").toString());
|
||||||
Assert.assertEquals("214", textHighlighter.process("214").toString());
|
Assert.assertEquals("214", textHighlighter.process("214").toString());
|
||||||
Assert.assertEquals("2 145", textHighlighter.process("2 145").toString());
|
Assert.assertEquals("2 145", textHighlighter.process("2 145").toString());
|
||||||
Assert.assertEquals("1 000 000E3", textHighlighter.process("1000000E3").toString());
|
Assert.assertEquals("1 000 000E3", textHighlighter.process("1000000E3").toString());
|
||||||
Assert.assertEquals("-1 000 000E3", textHighlighter.process("-1000000E3").toString());
|
Assert.assertEquals("-1 000 000E3", textHighlighter.process("-1000000E3").toString());
|
||||||
Assert.assertEquals("-1 000 000E-3", textHighlighter.process("-1000000E-3").toString());
|
Assert.assertEquals("-1 000 000E-3", textHighlighter.process("-1000000E-3").toString());
|
||||||
Assert.assertEquals("-1 000 000E-30000", textHighlighter.process("-1000000E-30000").toString());
|
Assert.assertEquals("-1 000 000E-30000", textHighlighter.process("-1000000E-30000").toString());
|
||||||
textHighlighter = new TextHighlighter(0, false, JsclMathEngine.instance);
|
textHighlighter = new TextHighlighter(0, false, JsclMathEngine.instance);
|
||||||
|
|
||||||
textHighlighter.process("cannot calculate 3^10^10 !!!\n" +
|
textHighlighter.process("cannot calculate 3^10^10 !!!\n" +
|
||||||
" unable to enter 0. FIXED\n" +
|
" unable to enter 0. FIXED\n" +
|
||||||
" empty display in Xperia Rayo\n" +
|
" empty display in Xperia Rayo\n" +
|
||||||
" check привиденная FIXED\n" +
|
" check привиденная FIXED\n" +
|
||||||
" set display result only if text in editor was not changed FIXED\n" +
|
" set display result only if text in editor was not changed FIXED\n" +
|
||||||
" shift M text to the left\n" +
|
" shift M text to the left\n" +
|
||||||
" do not show SYNTAX ERROR always (may be show send clock?q) FIXED\n" +
|
" do not show SYNTAX ERROR always (may be show send clock?q) FIXED\n" +
|
||||||
" ln(8)*log(8) => ln(8)*og(8) FIXED\n" +
|
" ln(8)*log(8) => ln(8)*og(8) FIXED\n" +
|
||||||
" copy/paste ln(8)*log(8)\n" +
|
" copy/paste ln(8)*log(8)\n" +
|
||||||
" 6!^2 ERROR");
|
" 6!^2 ERROR");
|
||||||
|
|
||||||
Assert.assertEquals("<font color=\"#000000\"><i>sin</i>(</font><font color=\"#ffff9a\">2</font><font color=\"#000000\">)</font>", textHighlighter.process("sin(2)").toString());
|
Assert.assertEquals("<font color=\"#000000\"><i>sin</i>(</font><font color=\"#ffff9a\">2</font><font color=\"#000000\">)</font>", textHighlighter.process("sin(2)").toString());
|
||||||
Assert.assertEquals("<font color=\"#000000\"><i>atanh</i>(</font><font color=\"#ffff9a\">2</font><font color=\"#000000\">)</font>", textHighlighter.process("atanh(2)").toString());
|
Assert.assertEquals("<font color=\"#000000\"><i>atanh</i>(</font><font color=\"#ffff9a\">2</font><font color=\"#000000\">)</font>", textHighlighter.process("atanh(2)").toString());
|
||||||
|
|
||||||
|
|
||||||
Assert.assertEquals("<b>0x:</b>E", textHighlighter.process("0x:E").toString());
|
Assert.assertEquals("<b>0x:</b>E", textHighlighter.process("0x:E").toString());
|
||||||
Assert.assertEquals("<b>0x:</b>6F", textHighlighter.process("0x:6F").toString());
|
Assert.assertEquals("<b>0x:</b>6F", textHighlighter.process("0x:6F").toString());
|
||||||
Assert.assertEquals("<b>0x:</b>6F.", textHighlighter.process("0x:6F.").toString());
|
Assert.assertEquals("<b>0x:</b>6F.", textHighlighter.process("0x:6F.").toString());
|
||||||
Assert.assertEquals("<b>0x:</b>6F.2", textHighlighter.process("0x:6F.2").toString());
|
Assert.assertEquals("<b>0x:</b>6F.2", textHighlighter.process("0x:6F.2").toString());
|
||||||
Assert.assertEquals("<b>0x:</b>6F.B", textHighlighter.process("0x:6F.B").toString());
|
Assert.assertEquals("<b>0x:</b>6F.B", textHighlighter.process("0x:6F.B").toString());
|
||||||
Assert.assertEquals("<b>0x:</b>006F.B", textHighlighter.process("0x:006F.B").toString());
|
Assert.assertEquals("<b>0x:</b>006F.B", textHighlighter.process("0x:006F.B").toString());
|
||||||
Assert.assertEquals("<b>0x:</b>0", textHighlighter.process("0x:0").toString());
|
Assert.assertEquals("<b>0x:</b>0", textHighlighter.process("0x:0").toString());
|
||||||
Assert.assertEquals("<b>0x:</b>FF33233FFE", textHighlighter.process("0x:FF33233FFE").toString());
|
Assert.assertEquals("<b>0x:</b>FF33233FFE", textHighlighter.process("0x:FF33233FFE").toString());
|
||||||
Assert.assertEquals("<b>0x:</b>FF33 233 FFE", textHighlighter.process("0x:FF33 233 FFE").toString());
|
Assert.assertEquals("<b>0x:</b>FF33 233 FFE", textHighlighter.process("0x:FF33 233 FFE").toString());
|
||||||
|
|
||||||
final MathEngine me = CalculatorEngine.instance.getEngine();
|
final MathEngine me = CalculatorEngine.instance.getEngine();
|
||||||
try {
|
try {
|
||||||
me.setNumeralBase(NumeralBase.hex);
|
me.setNumeralBase(NumeralBase.hex);
|
||||||
Assert.assertEquals("E", textHighlighter.process("E").toString());
|
Assert.assertEquals("E", textHighlighter.process("E").toString());
|
||||||
Assert.assertEquals(".E", textHighlighter.process(".E").toString());
|
Assert.assertEquals(".E", textHighlighter.process(".E").toString());
|
||||||
Assert.assertEquals("E+", textHighlighter.process("E+").toString());
|
Assert.assertEquals("E+", textHighlighter.process("E+").toString());
|
||||||
Assert.assertEquals("E.", textHighlighter.process("E.").toString());
|
Assert.assertEquals("E.", textHighlighter.process("E.").toString());
|
||||||
Assert.assertEquals(".E.", textHighlighter.process(".E.").toString());
|
Assert.assertEquals(".E.", textHighlighter.process(".E.").toString());
|
||||||
Assert.assertEquals("6F", textHighlighter.process("6F").toString());
|
Assert.assertEquals("6F", textHighlighter.process("6F").toString());
|
||||||
Assert.assertEquals("6F", textHighlighter.process("6F").toString());
|
Assert.assertEquals("6F", textHighlighter.process("6F").toString());
|
||||||
Assert.assertEquals("6F.", textHighlighter.process("6F.").toString());
|
Assert.assertEquals("6F.", textHighlighter.process("6F.").toString());
|
||||||
Assert.assertEquals("6F.2", textHighlighter.process("6F.2").toString());
|
Assert.assertEquals("6F.2", textHighlighter.process("6F.2").toString());
|
||||||
Assert.assertEquals("6F.B", textHighlighter.process("6F.B").toString());
|
Assert.assertEquals("6F.B", textHighlighter.process("6F.B").toString());
|
||||||
Assert.assertEquals("006F.B", textHighlighter.process("006F.B").toString());
|
Assert.assertEquals("006F.B", textHighlighter.process("006F.B").toString());
|
||||||
} finally {
|
} finally {
|
||||||
me.setNumeralBase(NumeralBase.dec);
|
me.setNumeralBase(NumeralBase.dec);
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.assertEquals("<b>0b:</b>110101", textHighlighter.process("0b:110101").toString());
|
Assert.assertEquals("<b>0b:</b>110101", textHighlighter.process("0b:110101").toString());
|
||||||
Assert.assertEquals("<b>0b:</b>110101.", textHighlighter.process("0b:110101.").toString());
|
Assert.assertEquals("<b>0b:</b>110101.", textHighlighter.process("0b:110101.").toString());
|
||||||
Assert.assertEquals("<b>0b:</b>110101.101", textHighlighter.process("0b:110101.101").toString());
|
Assert.assertEquals("<b>0b:</b>110101.101", textHighlighter.process("0b:110101.101").toString());
|
||||||
Assert.assertEquals("<b>0b:</b>11010100.1", textHighlighter.process("0b:11010100.1").toString());
|
Assert.assertEquals("<b>0b:</b>11010100.1", textHighlighter.process("0b:11010100.1").toString());
|
||||||
Assert.assertEquals("<b>0b:</b>110101.0", textHighlighter.process("0b:110101.0").toString());
|
Assert.assertEquals("<b>0b:</b>110101.0", textHighlighter.process("0b:110101.0").toString());
|
||||||
Assert.assertEquals("<b>0b:</b>0", textHighlighter.process("0b:0").toString());
|
Assert.assertEquals("<b>0b:</b>0", textHighlighter.process("0b:0").toString());
|
||||||
Assert.assertEquals("<b>0b:</b>1010100101111010101001", textHighlighter.process("0b:1010100101111010101001").toString());
|
Assert.assertEquals("<b>0b:</b>1010100101111010101001", textHighlighter.process("0b:1010100101111010101001").toString());
|
||||||
Assert.assertEquals("<b>0b:</b>101 010 01 0 111 1 0 10101001", textHighlighter.process("0b:101 010 01 0 111 1 0 10101001").toString());
|
Assert.assertEquals("<b>0b:</b>101 010 01 0 111 1 0 10101001", textHighlighter.process("0b:101 010 01 0 111 1 0 10101001").toString());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
me.setNumeralBase(NumeralBase.bin);
|
me.setNumeralBase(NumeralBase.bin);
|
||||||
Assert.assertEquals("110101", textHighlighter.process("110101").toString());
|
Assert.assertEquals("110101", textHighlighter.process("110101").toString());
|
||||||
Assert.assertEquals("110101.", textHighlighter.process("110101.").toString());
|
Assert.assertEquals("110101.", textHighlighter.process("110101.").toString());
|
||||||
Assert.assertEquals("110101.101", textHighlighter.process("110101.101").toString());
|
Assert.assertEquals("110101.101", textHighlighter.process("110101.101").toString());
|
||||||
Assert.assertEquals("11010100.1", textHighlighter.process("11010100.1").toString());
|
Assert.assertEquals("11010100.1", textHighlighter.process("11010100.1").toString());
|
||||||
Assert.assertEquals("110101.0", textHighlighter.process("110101.0").toString());
|
Assert.assertEquals("110101.0", textHighlighter.process("110101.0").toString());
|
||||||
Assert.assertEquals("0", textHighlighter.process("0").toString());
|
Assert.assertEquals("0", textHighlighter.process("0").toString());
|
||||||
Assert.assertEquals("1010100101111010101001", textHighlighter.process("1010100101111010101001").toString());
|
Assert.assertEquals("1010100101111010101001", textHighlighter.process("1010100101111010101001").toString());
|
||||||
Assert.assertEquals("101 010 01 0 111 1 0 10101001", textHighlighter.process("101 010 01 0 111 1 0 10101001").toString());
|
Assert.assertEquals("101 010 01 0 111 1 0 10101001", textHighlighter.process("101 010 01 0 111 1 0 10101001").toString());
|
||||||
} finally {
|
} finally {
|
||||||
me.setNumeralBase(NumeralBase.dec);
|
me.setNumeralBase(NumeralBase.dec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,8 @@ import junit.framework.Assert;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
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.ICalculatorDisplay;
|
import org.solovyev.android.calculator.CalculatorDisplay;
|
||||||
|
import org.solovyev.android.calculator.Editor;
|
||||||
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;
|
||||||
@ -124,7 +125,7 @@ public class HistoryUtilsTest {
|
|||||||
|
|
||||||
HistoryHelper<CalculatorHistoryState> history = new SimpleHistoryHelper<CalculatorHistoryState>();
|
HistoryHelper<CalculatorHistoryState> history = new SimpleHistoryHelper<CalculatorHistoryState>();
|
||||||
|
|
||||||
ICalculatorDisplay calculatorDisplay = new TestCalculatorDisplay();
|
CalculatorDisplay calculatorDisplay = new TestCalculatorDisplay();
|
||||||
calculatorDisplay.setErrorMessage("error_msg1");
|
calculatorDisplay.setErrorMessage("error_msg1");
|
||||||
calculatorDisplay.setText("Error");
|
calculatorDisplay.setText("Error");
|
||||||
calculatorDisplay.setSelection(1);
|
calculatorDisplay.setSelection(1);
|
||||||
@ -214,7 +215,7 @@ public class HistoryUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class TestCalculatorDisplay implements ICalculatorDisplay {
|
private static class TestCalculatorDisplay implements CalculatorDisplay {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final TestEditor testEditor = new TestEditor();
|
private final TestEditor testEditor = new TestEditor();
|
||||||
|
@ -15,6 +15,8 @@ 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.jscl.JsclOperation;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
|
||||||
import java.text.DecimalFormatSymbols;
|
import java.text.DecimalFormatSymbols;
|
||||||
@ -52,13 +54,13 @@ public class CalculatorEngineTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.assertEquals("0.017", cm.evaluate(JsclOperation.numeric, "1°").getResult());
|
Assert.assertEquals("0.017", cm.evaluate(JsclOperation.numeric, "1°").getStringResult());
|
||||||
Assert.assertEquals("0.349", cm.evaluate(JsclOperation.numeric, "20.0°").getResult());
|
Assert.assertEquals("0.349", cm.evaluate(JsclOperation.numeric, "20.0°").getStringResult());
|
||||||
Assert.assertEquals("0.5", cm.evaluate(JsclOperation.numeric, "sin(30°)").getResult());
|
Assert.assertEquals("0.5", cm.evaluate(JsclOperation.numeric, "sin(30°)").getStringResult());
|
||||||
Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "asin(sin(30°))").getResult());
|
Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "asin(sin(30°))").getStringResult());
|
||||||
Assert.assertEquals("∂(cos(t), t, t, 1°)", cm.evaluate(JsclOperation.numeric, "∂(cos(t),t,t,1°)").getResult());
|
Assert.assertEquals("∂(cos(t), t, t, 1°)", cm.evaluate(JsclOperation.numeric, "∂(cos(t),t,t,1°)").getStringResult());
|
||||||
|
|
||||||
Assert.assertEquals("∂(cos(t), t, t, 1°)", cm.evaluate(JsclOperation.simplify, "∂(cos(t),t,t,1°)").getResult());
|
Assert.assertEquals("∂(cos(t), t, t, 1°)", cm.evaluate(JsclOperation.simplify, "∂(cos(t),t,t,1°)").getStringResult());
|
||||||
} finally {
|
} finally {
|
||||||
cm.getEngine().setAngleUnits(defaultAngleUnit);
|
cm.getEngine().setAngleUnits(defaultAngleUnit);
|
||||||
}
|
}
|
||||||
@ -111,120 +113,120 @@ public class CalculatorEngineTest {
|
|||||||
public void testEvaluate() throws Exception {
|
public void testEvaluate() throws Exception {
|
||||||
final CalculatorEngine cm = CalculatorEngine.instance;
|
final CalculatorEngine cm = CalculatorEngine.instance;
|
||||||
|
|
||||||
Assert.assertEquals("cos(t)+10%", cm.evaluate(JsclOperation.simplify, "cos(t)+10%").getResult());
|
Assert.assertEquals("cos(t)+10%", cm.evaluate(JsclOperation.simplify, "cos(t)+10%").getStringResult());
|
||||||
|
|
||||||
final Generic expression = cm.getEngine().simplifyGeneric("cos(t)+10%");
|
final Generic expression = cm.getEngine().simplifyGeneric("cos(t)+10%");
|
||||||
expression.substitute(new Constant("t"), Expression.valueOf(100d));
|
expression.substitute(new Constant("t"), Expression.valueOf(100d));
|
||||||
|
|
||||||
Assert.assertEquals("it", cm.evaluate(JsclOperation.simplify, "it").getResult());
|
Assert.assertEquals("it", cm.evaluate(JsclOperation.simplify, "it").getStringResult());
|
||||||
Assert.assertEquals("10%", cm.evaluate(JsclOperation.simplify, "10%").getResult());
|
Assert.assertEquals("10%", cm.evaluate(JsclOperation.simplify, "10%").getStringResult());
|
||||||
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(0, 1)").getResult());
|
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(0, 1)").getStringResult());
|
||||||
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1)").getResult());
|
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1)").getStringResult());
|
||||||
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq( 1, 1)").getResult());
|
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq( 1, 1)").getStringResult());
|
||||||
Assert.assertEquals("1", cm.evaluate(JsclOperation.simplify, "eq( 1, 1)").getResult());
|
Assert.assertEquals("1", cm.evaluate(JsclOperation.simplify, "eq( 1, 1)").getStringResult());
|
||||||
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "lg(10)").getResult());
|
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "lg(10)").getStringResult());
|
||||||
Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "2+2").getResult());
|
Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "2+2").getStringResult());
|
||||||
final AngleUnit defaultAngleUnit = cm.getEngine().getAngleUnits();
|
final AngleUnit defaultAngleUnit = cm.getEngine().getAngleUnits();
|
||||||
try {
|
try {
|
||||||
cm.getEngine().setAngleUnits(AngleUnit.rad);
|
cm.getEngine().setAngleUnits(AngleUnit.rad);
|
||||||
Assert.assertEquals("-0.757", cm.evaluate(JsclOperation.numeric, "sin(4)").getResult());
|
Assert.assertEquals("-0.757", cm.evaluate(JsclOperation.numeric, "sin(4)").getStringResult());
|
||||||
Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "asin(0.5)").getResult());
|
Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "asin(0.5)").getStringResult());
|
||||||
Assert.assertEquals("-0.396", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)").getResult());
|
Assert.assertEquals("-0.396", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)").getStringResult());
|
||||||
Assert.assertEquals("-0.56", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)√(2)").getResult());
|
Assert.assertEquals("-0.56", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)√(2)").getStringResult());
|
||||||
Assert.assertEquals("-0.56", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)√(2)").getResult());
|
Assert.assertEquals("-0.56", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)√(2)").getStringResult());
|
||||||
} finally {
|
} finally {
|
||||||
cm.getEngine().setAngleUnits(defaultAngleUnit);
|
cm.getEngine().setAngleUnits(defaultAngleUnit);
|
||||||
}
|
}
|
||||||
Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "e^2").getResult());
|
Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "e^2").getStringResult());
|
||||||
Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "exp(1)^2").getResult());
|
Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "exp(1)^2").getStringResult());
|
||||||
Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "exp(2)").getResult());
|
Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "exp(2)").getStringResult());
|
||||||
Assert.assertEquals("2+i", cm.evaluate(JsclOperation.numeric, "2*1+√(-1)").getResult());
|
Assert.assertEquals("2+i", cm.evaluate(JsclOperation.numeric, "2*1+√(-1)").getStringResult());
|
||||||
try {
|
try {
|
||||||
cm.getEngine().setAngleUnits(AngleUnit.rad);
|
cm.getEngine().setAngleUnits(AngleUnit.rad);
|
||||||
Assert.assertEquals("0.921+Πi", cm.evaluate(JsclOperation.numeric, "ln(5cosh(38π√(2cos(2))))").getResult());
|
Assert.assertEquals("0.921+Πi", cm.evaluate(JsclOperation.numeric, "ln(5cosh(38π√(2cos(2))))").getStringResult());
|
||||||
Assert.assertEquals("-3.41+3.41i", cm.evaluate(JsclOperation.numeric, "(5tan(2i)+2i)/(1-i)").getResult());
|
Assert.assertEquals("-3.41+3.41i", cm.evaluate(JsclOperation.numeric, "(5tan(2i)+2i)/(1-i)").getStringResult());
|
||||||
} finally {
|
} finally {
|
||||||
cm.getEngine().setAngleUnits(defaultAngleUnit);
|
cm.getEngine().setAngleUnits(defaultAngleUnit);
|
||||||
}
|
}
|
||||||
Assert.assertEquals("7.389i", cm.evaluate(JsclOperation.numeric, "iexp(2)").getResult());
|
Assert.assertEquals("7.389i", cm.evaluate(JsclOperation.numeric, "iexp(2)").getStringResult());
|
||||||
Assert.assertEquals("2+7.389i", cm.evaluate(JsclOperation.numeric, "2+iexp(2)").getResult());
|
Assert.assertEquals("2+7.389i", cm.evaluate(JsclOperation.numeric, "2+iexp(2)").getStringResult());
|
||||||
Assert.assertEquals("2+7.389i", cm.evaluate(JsclOperation.numeric, "2+√(-1)exp(2)").getResult());
|
Assert.assertEquals("2+7.389i", cm.evaluate(JsclOperation.numeric, "2+√(-1)exp(2)").getStringResult());
|
||||||
Assert.assertEquals("2-2.5i", cm.evaluate(JsclOperation.numeric, "2-2.5i").getResult());
|
Assert.assertEquals("2-2.5i", cm.evaluate(JsclOperation.numeric, "2-2.5i").getStringResult());
|
||||||
Assert.assertEquals("-2-2.5i", cm.evaluate(JsclOperation.numeric, "-2-2.5i").getResult());
|
Assert.assertEquals("-2-2.5i", cm.evaluate(JsclOperation.numeric, "-2-2.5i").getStringResult());
|
||||||
Assert.assertEquals("-2+2.5i", cm.evaluate(JsclOperation.numeric, "-2+2.5i").getResult());
|
Assert.assertEquals("-2+2.5i", cm.evaluate(JsclOperation.numeric, "-2+2.5i").getStringResult());
|
||||||
Assert.assertEquals("-2+2.1i", cm.evaluate(JsclOperation.numeric, "-2+2.1i").getResult());
|
Assert.assertEquals("-2+2.1i", cm.evaluate(JsclOperation.numeric, "-2+2.1i").getStringResult());
|
||||||
Assert.assertEquals("-0.1-0.2i", cm.evaluate(JsclOperation.numeric, "(1-i)/(2+6i)").getResult());
|
Assert.assertEquals("-0.1-0.2i", cm.evaluate(JsclOperation.numeric, "(1-i)/(2+6i)").getStringResult());
|
||||||
|
|
||||||
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "4!").getResult());
|
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "4!").getStringResult());
|
||||||
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "(2+2)!").getResult());
|
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "(2+2)!").getStringResult());
|
||||||
junit.framework.Assert.assertEquals("120", cm.evaluate(JsclOperation.numeric, "(2+2+1)!").getResult());
|
junit.framework.Assert.assertEquals("120", cm.evaluate(JsclOperation.numeric, "(2+2+1)!").getStringResult());
|
||||||
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "(2.0+2.0)!").getResult());
|
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "(2.0+2.0)!").getStringResult());
|
||||||
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "4.0!").getResult());
|
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "4.0!").getStringResult());
|
||||||
junit.framework.Assert.assertEquals("720", cm.evaluate(JsclOperation.numeric, "(3!)!").getResult());
|
junit.framework.Assert.assertEquals("720", cm.evaluate(JsclOperation.numeric, "(3!)!").getStringResult());
|
||||||
junit.framework.Assert.assertEquals("36", Expression.valueOf("3!^2").numeric().toString());
|
junit.framework.Assert.assertEquals("36", Expression.valueOf("3!^2").numeric().toString());
|
||||||
junit.framework.Assert.assertEquals("3", Expression.valueOf("cubic(27)").numeric().toString());
|
junit.framework.Assert.assertEquals("3", Expression.valueOf("cubic(27)").numeric().toString());
|
||||||
try {
|
try {
|
||||||
junit.framework.Assert.assertEquals("√(-1)!", cm.evaluate(JsclOperation.numeric, "i!").getResult());
|
junit.framework.Assert.assertEquals("√(-1)!", cm.evaluate(JsclOperation.numeric, "i!").getStringResult());
|
||||||
fail();
|
fail();
|
||||||
} catch (CalculatorParseException e) {
|
} catch (CalculatorParseException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
junit.framework.Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "(π/π)!").getResult());
|
junit.framework.Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "(π/π)!").getStringResult());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
junit.framework.Assert.assertEquals("i", cm.evaluate(JsclOperation.numeric, "(-1)i!").getResult());
|
junit.framework.Assert.assertEquals("i", cm.evaluate(JsclOperation.numeric, "(-1)i!").getStringResult());
|
||||||
fail();
|
fail();
|
||||||
} catch (CalculatorParseException e) {
|
} catch (CalculatorParseException e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
junit.framework.Assert.assertEquals("24i", cm.evaluate(JsclOperation.numeric, "4!i").getResult());
|
junit.framework.Assert.assertEquals("24i", cm.evaluate(JsclOperation.numeric, "4!i").getStringResult());
|
||||||
|
|
||||||
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("si", 5d));
|
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("si", 5d));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cm.getEngine().setAngleUnits(AngleUnit.rad);
|
cm.getEngine().setAngleUnits(AngleUnit.rad);
|
||||||
Assert.assertEquals("0.451", cm.evaluate(JsclOperation.numeric, "acos(0.8999999999999811)").getResult());
|
Assert.assertEquals("0.451", cm.evaluate(JsclOperation.numeric, "acos(0.8999999999999811)").getStringResult());
|
||||||
Assert.assertEquals("-0.959", cm.evaluate(JsclOperation.numeric, "sin(5)").getResult());
|
Assert.assertEquals("-0.959", cm.evaluate(JsclOperation.numeric, "sin(5)").getStringResult());
|
||||||
Assert.assertEquals("-4.795", cm.evaluate(JsclOperation.numeric, "sin(5)si").getResult());
|
Assert.assertEquals("-4.795", cm.evaluate(JsclOperation.numeric, "sin(5)si").getStringResult());
|
||||||
Assert.assertEquals("-23.973", cm.evaluate(JsclOperation.numeric, "sisin(5)si").getResult());
|
Assert.assertEquals("-23.973", cm.evaluate(JsclOperation.numeric, "sisin(5)si").getStringResult());
|
||||||
Assert.assertEquals("-23.973", cm.evaluate(JsclOperation.numeric, "si*sin(5)si").getResult());
|
Assert.assertEquals("-23.973", cm.evaluate(JsclOperation.numeric, "si*sin(5)si").getStringResult());
|
||||||
Assert.assertEquals("-3.309", cm.evaluate(JsclOperation.numeric, "sisin(5si)si").getResult());
|
Assert.assertEquals("-3.309", cm.evaluate(JsclOperation.numeric, "sisin(5si)si").getStringResult());
|
||||||
} finally {
|
} finally {
|
||||||
cm.getEngine().setAngleUnits(defaultAngleUnit);
|
cm.getEngine().setAngleUnits(defaultAngleUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("s", 1d));
|
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("s", 1d));
|
||||||
Assert.assertEquals("5", cm.evaluate(JsclOperation.numeric, "si").getResult());
|
Assert.assertEquals("5", cm.evaluate(JsclOperation.numeric, "si").getStringResult());
|
||||||
|
|
||||||
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("k", 3.5d));
|
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("k", 3.5d));
|
||||||
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("k1", 4d));
|
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("k1", 4d));
|
||||||
Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "k11").getResult());
|
Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "k11").getStringResult());
|
||||||
|
|
||||||
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String) null));
|
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String) null));
|
||||||
Assert.assertEquals("11t", cm.evaluate(JsclOperation.numeric, "t11").getResult());
|
Assert.assertEquals("11t", cm.evaluate(JsclOperation.numeric, "t11").getStringResult());
|
||||||
Assert.assertEquals("11et", cm.evaluate(JsclOperation.numeric, "t11e").getResult());
|
Assert.assertEquals("11et", cm.evaluate(JsclOperation.numeric, "t11e").getStringResult());
|
||||||
Assert.assertEquals("∞", cm.evaluate(JsclOperation.numeric, "∞").getResult());
|
Assert.assertEquals("∞", cm.evaluate(JsclOperation.numeric, "∞").getStringResult());
|
||||||
Assert.assertEquals("∞", cm.evaluate(JsclOperation.numeric, "Infinity").getResult());
|
Assert.assertEquals("∞", cm.evaluate(JsclOperation.numeric, "Infinity").getStringResult());
|
||||||
Assert.assertEquals("11∞t", cm.evaluate(JsclOperation.numeric, "t11∞").getResult());
|
Assert.assertEquals("11∞t", cm.evaluate(JsclOperation.numeric, "t11∞").getStringResult());
|
||||||
Assert.assertEquals("-t+t^3", cm.evaluate(JsclOperation.numeric, "t(t-1)(t+1)").getResult());
|
Assert.assertEquals("-t+t^3", cm.evaluate(JsclOperation.numeric, "t(t-1)(t+1)").getStringResult());
|
||||||
|
|
||||||
Assert.assertEquals("100", cm.evaluate(JsclOperation.numeric, "0.1E3").getResult());
|
Assert.assertEquals("100", cm.evaluate(JsclOperation.numeric, "0.1E3").getStringResult());
|
||||||
Assert.assertEquals("3.957", cm.evaluate(JsclOperation.numeric, "ln(8)lg(8)+ln(8)").getResult());
|
Assert.assertEquals("3.957", cm.evaluate(JsclOperation.numeric, "ln(8)lg(8)+ln(8)").getStringResult());
|
||||||
|
|
||||||
Assert.assertEquals("0.933", cm.evaluate(JsclOperation.numeric, "0x:E/0x:F").getResult());
|
Assert.assertEquals("0.933", cm.evaluate(JsclOperation.numeric, "0x:E/0x:F").getStringResult());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cm.getEngine().setNumeralBase(NumeralBase.hex);
|
cm.getEngine().setNumeralBase(NumeralBase.hex);
|
||||||
Assert.assertEquals("E/F", cm.evaluate(JsclOperation.numeric, "0x:E/0x:F").getResult());
|
Assert.assertEquals("E/F", cm.evaluate(JsclOperation.numeric, "0x:E/0x:F").getStringResult());
|
||||||
Assert.assertEquals("E/F", cm.evaluate(JsclOperation.simplify, "0x:E/0x:F").getResult());
|
Assert.assertEquals("E/F", cm.evaluate(JsclOperation.simplify, "0x:E/0x:F").getStringResult());
|
||||||
Assert.assertEquals("E/F", cm.evaluate(JsclOperation.numeric, "E/F").getResult());
|
Assert.assertEquals("E/F", cm.evaluate(JsclOperation.numeric, "E/F").getStringResult());
|
||||||
Assert.assertEquals("E/F", cm.evaluate(JsclOperation.simplify, "E/F").getResult());
|
Assert.assertEquals("E/F", cm.evaluate(JsclOperation.simplify, "E/F").getStringResult());
|
||||||
} finally {
|
} finally {
|
||||||
cm.getEngine().setNumeralBase(NumeralBase.dec);
|
cm.getEngine().setNumeralBase(NumeralBase.dec);
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "((((((0))))))").getResult());
|
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "((((((0))))))").getStringResult());
|
||||||
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))").getResult());
|
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))").getStringResult());
|
||||||
|
|
||||||
|
|
||||||
/* Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "30°").getResult());
|
/* Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "30°").getResult());
|
||||||
@ -247,11 +249,11 @@ public class CalculatorEngineTest {
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String) null));
|
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String) null));
|
||||||
Assert.assertEquals("2t", cm.evaluate(JsclOperation.simplify, "∂(t^2,t)").getResult());
|
Assert.assertEquals("2t", cm.evaluate(JsclOperation.simplify, "∂(t^2,t)").getStringResult());
|
||||||
Assert.assertEquals("2t", cm.evaluate(JsclOperation.numeric, "∂(t^2,t)").getResult());
|
Assert.assertEquals("2t", cm.evaluate(JsclOperation.numeric, "∂(t^2,t)").getStringResult());
|
||||||
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", "2"));
|
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", "2"));
|
||||||
Assert.assertEquals("2t", cm.evaluate(JsclOperation.simplify, "∂(t^2,t)").getResult());
|
Assert.assertEquals("2t", cm.evaluate(JsclOperation.simplify, "∂(t^2,t)").getStringResult());
|
||||||
Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "∂(t^2,t)").getResult());
|
Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "∂(t^2,t)").getStringResult());
|
||||||
|
|
||||||
Assert.assertEquals("-x+x*ln(x)", cm.getEngine().simplify("∫(ln(x), x)"));
|
Assert.assertEquals("-x+x*ln(x)", cm.getEngine().simplify("∫(ln(x), x)"));
|
||||||
Assert.assertEquals("-(x-x*ln(x))/(ln(2)+ln(5))", cm.getEngine().simplify("∫(log(10, x), x)"));
|
Assert.assertEquals("-(x-x*ln(x))/(ln(2)+ln(5))", cm.getEngine().simplify("∫(log(10, x), x)"));
|
||||||
@ -265,7 +267,7 @@ public class CalculatorEngineTest {
|
|||||||
public void testFormatting() throws Exception {
|
public void testFormatting() throws Exception {
|
||||||
final CalculatorEngine ce = CalculatorEngine.instance;
|
final CalculatorEngine ce = CalculatorEngine.instance;
|
||||||
|
|
||||||
Assert.assertEquals("12 345", ce.evaluate(JsclOperation.simplify, "12345").getResult());
|
Assert.assertEquals("12 345", ce.evaluate(JsclOperation.simplify, "12345").getStringResult());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +275,7 @@ public class CalculatorEngineTest {
|
|||||||
public void testI() throws CalculatorParseException, CalculatorEvalException {
|
public void testI() throws CalculatorParseException, CalculatorEvalException {
|
||||||
final CalculatorEngine cm = CalculatorEngine.instance;
|
final CalculatorEngine cm = CalculatorEngine.instance;
|
||||||
|
|
||||||
Assert.assertEquals("-i", cm.evaluate(JsclOperation.numeric, "i^3").getResult());
|
Assert.assertEquals("-i", cm.evaluate(JsclOperation.numeric, "i^3").getStringResult());
|
||||||
for (int i = 0; i < 1000; i++) {
|
for (int i = 0; i < 1000; i++) {
|
||||||
double real = (Math.random()-0.5) * 1000;
|
double real = (Math.random()-0.5) * 1000;
|
||||||
double imag = (Math.random()-0.5) * 1000;
|
double imag = (Math.random()-0.5) * 1000;
|
||||||
@ -287,7 +289,7 @@ public class CalculatorEngineTest {
|
|||||||
sb.append(imag);
|
sb.append(imag);
|
||||||
sb.append("^").append(exp);
|
sb.append("^").append(exp);
|
||||||
try {
|
try {
|
||||||
cm.evaluate(JsclOperation.numeric, sb.toString()).getResult();
|
cm.evaluate(JsclOperation.numeric, sb.toString()).getStringResult();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
fail(sb.toString());
|
fail(sb.toString());
|
||||||
}
|
}
|
||||||
@ -302,7 +304,7 @@ public class CalculatorEngineTest {
|
|||||||
Assert.fail();
|
Assert.fail();
|
||||||
} catch (CalculatorParseException e) {
|
} catch (CalculatorParseException e) {
|
||||||
}
|
}
|
||||||
Assert.assertEquals("0.34+1.382i", cm.evaluate(JsclOperation.numeric, "ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(100)))))))))))))))").getResult());
|
Assert.assertEquals("0.34+1.382i", cm.evaluate(JsclOperation.numeric, "ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(100)))))))))))))))").getStringResult());
|
||||||
try {
|
try {
|
||||||
cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos())))))))))))))))))))))))))))))))))))");
|
cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos())))))))))))))))))))))))))))))))))))");
|
||||||
Assert.fail();
|
Assert.fail();
|
||||||
@ -312,13 +314,13 @@ public class CalculatorEngineTest {
|
|||||||
final AngleUnit defaultAngleUnit = cm.getEngine().getAngleUnits();
|
final AngleUnit defaultAngleUnit = cm.getEngine().getAngleUnits();
|
||||||
try {
|
try {
|
||||||
cm.getEngine().setAngleUnits(AngleUnit.rad);
|
cm.getEngine().setAngleUnits(AngleUnit.rad);
|
||||||
Assert.assertEquals("0.739", cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(1))))))))))))))))))))))))))))))))))))").getResult());
|
Assert.assertEquals("0.739", cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(1))))))))))))))))))))))))))))))))))))").getStringResult());
|
||||||
} finally {
|
} finally {
|
||||||
cm.getEngine().setAngleUnits(defaultAngleUnit);
|
cm.getEngine().setAngleUnits(defaultAngleUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("si", 5d));
|
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("si", 5d));
|
||||||
Assert.assertEquals("5", cm.evaluate(JsclOperation.numeric, "si").getResult());
|
Assert.assertEquals("5", cm.evaluate(JsclOperation.numeric, "si").getStringResult());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cm.evaluate(JsclOperation.numeric, "sin");
|
cm.evaluate(JsclOperation.numeric, "sin");
|
||||||
@ -337,11 +339,11 @@ public class CalculatorEngineTest {
|
|||||||
decimalGroupSymbols.setGroupingSeparator('\'');
|
decimalGroupSymbols.setGroupingSeparator('\'');
|
||||||
cm.setDecimalGroupSymbols(decimalGroupSymbols);
|
cm.setDecimalGroupSymbols(decimalGroupSymbols);
|
||||||
cm.setPrecision(2);
|
cm.setPrecision(2);
|
||||||
Assert.assertEquals("12'345'678.9", cm.evaluate(JsclOperation.numeric, "1.23456789E7").getResult());
|
Assert.assertEquals("12'345'678.9", cm.evaluate(JsclOperation.numeric, "1.23456789E7").getStringResult());
|
||||||
cm.setPrecision(10);
|
cm.setPrecision(10);
|
||||||
Assert.assertEquals("12'345'678.9", cm.evaluate(JsclOperation.numeric, "1.23456789E7").getResult());
|
Assert.assertEquals("12'345'678.9", cm.evaluate(JsclOperation.numeric, "1.23456789E7").getStringResult());
|
||||||
Assert.assertEquals("123'456'789", cm.evaluate(JsclOperation.numeric, "1.234567890E8").getResult());
|
Assert.assertEquals("123'456'789", cm.evaluate(JsclOperation.numeric, "1.234567890E8").getStringResult());
|
||||||
Assert.assertEquals("1'234'567'890.1", cm.evaluate(JsclOperation.numeric, "1.2345678901E9").getResult());
|
Assert.assertEquals("1'234'567'890.1", cm.evaluate(JsclOperation.numeric, "1.2345678901E9").getStringResult());
|
||||||
} finally {
|
} finally {
|
||||||
cm.setPrecision(3);
|
cm.setPrecision(3);
|
||||||
DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols(Locale.getDefault());
|
DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols(Locale.getDefault());
|
||||||
@ -355,36 +357,36 @@ public class CalculatorEngineTest {
|
|||||||
public void testComparisonFunction() throws Exception {
|
public void testComparisonFunction() throws Exception {
|
||||||
final CalculatorEngine cm = CalculatorEngine.instance;
|
final CalculatorEngine cm = CalculatorEngine.instance;
|
||||||
|
|
||||||
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(0, 1)").getResult());
|
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(0, 1)").getStringResult());
|
||||||
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1)").getResult());
|
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1)").getStringResult());
|
||||||
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1.0)").getResult());
|
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1.0)").getStringResult());
|
||||||
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(1, 1.000000000000001)").getResult());
|
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(1, 1.000000000000001)").getStringResult());
|
||||||
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(1, 0)").getResult());
|
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(1, 0)").getStringResult());
|
||||||
|
|
||||||
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "lt(0, 1)").getResult());
|
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "lt(0, 1)").getStringResult());
|
||||||
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "lt(1, 1)").getResult());
|
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "lt(1, 1)").getStringResult());
|
||||||
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "lt(1, 0)").getResult());
|
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "lt(1, 0)").getStringResult());
|
||||||
|
|
||||||
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "gt(0, 1)").getResult());
|
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "gt(0, 1)").getStringResult());
|
||||||
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "gt(1, 1)").getResult());
|
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "gt(1, 1)").getStringResult());
|
||||||
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "gt(1, 0)").getResult());
|
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "gt(1, 0)").getStringResult());
|
||||||
|
|
||||||
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ne(0, 1)").getResult());
|
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ne(0, 1)").getStringResult());
|
||||||
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ne(1, 1)").getResult());
|
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ne(1, 1)").getStringResult());
|
||||||
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ne(1, 0)").getResult());
|
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ne(1, 0)").getStringResult());
|
||||||
|
|
||||||
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "le(0, 1)").getResult());
|
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "le(0, 1)").getStringResult());
|
||||||
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "le(1, 1)").getResult());
|
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "le(1, 1)").getStringResult());
|
||||||
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "le(1, 0)").getResult());
|
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "le(1, 0)").getStringResult());
|
||||||
|
|
||||||
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ge(0, 1)").getResult());
|
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ge(0, 1)").getStringResult());
|
||||||
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ge(1, 1)").getResult());
|
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ge(1, 1)").getStringResult());
|
||||||
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ge(1, 0)").getResult());
|
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ge(1, 0)").getStringResult());
|
||||||
|
|
||||||
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ap(0, 1)").getResult());
|
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ap(0, 1)").getStringResult());
|
||||||
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ap(1, 1)").getResult());
|
Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ap(1, 1)").getStringResult());
|
||||||
//Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ap(1, 1.000000000000001)").getResult());
|
//Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ap(1, 1.000000000000001)").getResult());
|
||||||
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ap(1, 0)").getResult());
|
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ap(1, 0)").getStringResult());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,17 +395,17 @@ public class CalculatorEngineTest {
|
|||||||
public void testNumeralSystems() throws Exception {
|
public void testNumeralSystems() throws Exception {
|
||||||
final CalculatorEngine cm = CalculatorEngine.instance;
|
final CalculatorEngine cm = CalculatorEngine.instance;
|
||||||
|
|
||||||
Assert.assertEquals("11 259 375", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF").getResult());
|
Assert.assertEquals("11 259 375", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF").getStringResult());
|
||||||
Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF*e").getResult());
|
Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF*e").getStringResult());
|
||||||
Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "e*0x:ABCDEF").getResult());
|
Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "e*0x:ABCDEF").getStringResult());
|
||||||
Assert.assertEquals("e", cm.evaluate(JsclOperation.numeric, "e*0x:ABCDEF/0x:ABCDEF").getResult());
|
Assert.assertEquals("e", cm.evaluate(JsclOperation.numeric, "e*0x:ABCDEF/0x:ABCDEF").getStringResult());
|
||||||
Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF*e*0x:ABCDEF/0x:ABCDEF").getResult());
|
Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF*e*0x:ABCDEF/0x:ABCDEF").getStringResult());
|
||||||
Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "c+0x:ABCDEF*e*0x:ABCDEF/0x:ABCDEF-c+0x:C-0x:C").getResult());
|
Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "c+0x:ABCDEF*e*0x:ABCDEF/0x:ABCDEF-c+0x:C-0x:C").getStringResult());
|
||||||
Assert.assertEquals("1 446 257 064 651.832", cm.evaluate(JsclOperation.numeric, "28*28 * sin(28) - 0b:1101 + √(28) + exp ( 28) ").getResult());
|
Assert.assertEquals("1 446 257 064 651.832", cm.evaluate(JsclOperation.numeric, "28*28 * sin(28) - 0b:1101 + √(28) + exp ( 28) ").getStringResult());
|
||||||
Assert.assertEquals("13", cm.evaluate(JsclOperation.numeric, "0b:1101").getResult());
|
Assert.assertEquals("13", cm.evaluate(JsclOperation.numeric, "0b:1101").getStringResult());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cm.evaluate(JsclOperation.numeric, "0b:π").getResult();
|
cm.evaluate(JsclOperation.numeric, "0b:π").getStringResult();
|
||||||
Assert.fail();
|
Assert.fail();
|
||||||
} catch (CalculatorParseException e) {
|
} catch (CalculatorParseException e) {
|
||||||
// ok
|
// ok
|
||||||
@ -412,12 +414,12 @@ public class CalculatorEngineTest {
|
|||||||
final NumeralBase defaultNumeralBase = cm.getEngine().getNumeralBase();
|
final NumeralBase defaultNumeralBase = cm.getEngine().getNumeralBase();
|
||||||
try{
|
try{
|
||||||
cm.getEngine().setNumeralBase(NumeralBase.bin);
|
cm.getEngine().setNumeralBase(NumeralBase.bin);
|
||||||
Assert.assertEquals("101", cm.evaluate(JsclOperation.numeric, "10+11").getResult());
|
Assert.assertEquals("101", cm.evaluate(JsclOperation.numeric, "10+11").getStringResult());
|
||||||
Assert.assertEquals("10/11", cm.evaluate(JsclOperation.numeric, "10/11").getResult());
|
Assert.assertEquals("10/11", cm.evaluate(JsclOperation.numeric, "10/11").getStringResult());
|
||||||
|
|
||||||
cm.getEngine().setNumeralBase(NumeralBase.hex);
|
cm.getEngine().setNumeralBase(NumeralBase.hex);
|
||||||
Assert.assertEquals("63 7B", cm.evaluate(JsclOperation.numeric, "56CE+CAD").getResult());
|
Assert.assertEquals("63 7B", cm.evaluate(JsclOperation.numeric, "56CE+CAD").getStringResult());
|
||||||
Assert.assertEquals("E", cm.evaluate(JsclOperation.numeric, "E").getResult());
|
Assert.assertEquals("E", cm.evaluate(JsclOperation.numeric, "E").getStringResult());
|
||||||
} finally {
|
} finally {
|
||||||
cm.setNumeralBase(defaultNumeralBase);
|
cm.setNumeralBase(defaultNumeralBase);
|
||||||
}
|
}
|
||||||
@ -432,12 +434,12 @@ public class CalculatorEngineTest {
|
|||||||
|
|
||||||
// logarithm
|
// logarithm
|
||||||
Assert.assertEquals("ln(x)/ln(base)", ((CustomFunction) cm.getFunctionsRegistry().get("log")).getContent());
|
Assert.assertEquals("ln(x)/ln(base)", ((CustomFunction) cm.getFunctionsRegistry().get("log")).getContent());
|
||||||
Assert.assertEquals("∞", cm.evaluate(JsclOperation.numeric, "log(1, 10)").getResult());
|
Assert.assertEquals("∞", cm.evaluate(JsclOperation.numeric, "log(1, 10)").getStringResult());
|
||||||
Assert.assertEquals("3.322", cm.evaluate(JsclOperation.numeric, "log(2, 10)").getResult());
|
Assert.assertEquals("3.322", cm.evaluate(JsclOperation.numeric, "log(2, 10)").getStringResult());
|
||||||
Assert.assertEquals("1.431", cm.evaluate(JsclOperation.numeric, "log(5, 10)").getResult());
|
Assert.assertEquals("1.431", cm.evaluate(JsclOperation.numeric, "log(5, 10)").getStringResult());
|
||||||
Assert.assertEquals("0.96", cm.evaluate(JsclOperation.numeric, "log(11, 10)").getResult());
|
Assert.assertEquals("0.96", cm.evaluate(JsclOperation.numeric, "log(11, 10)").getStringResult());
|
||||||
Assert.assertEquals("1/(bln(a))", cm.evaluate(JsclOperation.simplify, "∂(log(a, b), b)").getResult());
|
Assert.assertEquals("1/(bln(a))", cm.evaluate(JsclOperation.simplify, "∂(log(a, b), b)").getStringResult());
|
||||||
Assert.assertEquals("-ln(b)/(aln(a)^2)", cm.evaluate(JsclOperation.simplify, "∂(log(a, b), a)").getResult());
|
Assert.assertEquals("-ln(b)/(aln(a)^2)", cm.evaluate(JsclOperation.simplify, "∂(log(a, b), a)").getStringResult());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,69 +1,70 @@
|
|||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator.model;
|
||||||
|
|
||||||
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.text.FromJsclSimplifyTextProcessor;
|
||||||
import java.text.DecimalFormatSymbols;
|
|
||||||
|
import java.text.DecimalFormatSymbols;
|
||||||
/**
|
|
||||||
* User: serso
|
/**
|
||||||
* Date: 10/20/11
|
* User: serso
|
||||||
* Time: 3:43 PM
|
* Date: 10/20/11
|
||||||
*/
|
* Time: 3:43 PM
|
||||||
public class FromJsclSimplifyTextProcessorTest {
|
*/
|
||||||
|
public class FromJsclSimplifyTextProcessorTest {
|
||||||
@BeforeClass
|
|
||||||
public static void setUp() throws Exception {
|
@BeforeClass
|
||||||
CalculatorEngine.instance.init(null, null);
|
public static void setUp() throws Exception {
|
||||||
}
|
CalculatorEngine.instance.init(null, null);
|
||||||
|
}
|
||||||
@Test
|
|
||||||
public void testProcess() throws Exception {
|
@Test
|
||||||
FromJsclSimplifyTextProcessor tp = new FromJsclSimplifyTextProcessor();
|
public void testProcess() throws Exception {
|
||||||
//Assert.assertEquals("(e)", tp.process("(2.718281828459045)"));
|
FromJsclSimplifyTextProcessor tp = new FromJsclSimplifyTextProcessor();
|
||||||
//Assert.assertEquals("ee", tp.process("2.718281828459045*2.718281828459045"));
|
//Assert.assertEquals("(e)", tp.process("(2.718281828459045)"));
|
||||||
//Assert.assertEquals("((e)(e))", tp.process("((2.718281828459045)*(2.718281828459045))"));
|
//Assert.assertEquals("ee", tp.process("2.718281828459045*2.718281828459045"));
|
||||||
DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols();
|
//Assert.assertEquals("((e)(e))", tp.process("((2.718281828459045)*(2.718281828459045))"));
|
||||||
decimalGroupSymbols.setGroupingSeparator(' ');
|
DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols();
|
||||||
CalculatorEngine.instance.setDecimalGroupSymbols(decimalGroupSymbols);
|
decimalGroupSymbols.setGroupingSeparator(' ');
|
||||||
//Assert.assertEquals("123 456 789e", tp.process("123456789*2.718281828459045"));
|
CalculatorEngine.instance.setDecimalGroupSymbols(decimalGroupSymbols);
|
||||||
//Assert.assertEquals("123 456 789e", tp.process("123 456 789 * 2.718281828459045"));
|
//Assert.assertEquals("123 456 789e", tp.process("123456789*2.718281828459045"));
|
||||||
//Assert.assertEquals("t11e", tp.process("t11*2.718281828459045"));
|
//Assert.assertEquals("123 456 789e", tp.process("123 456 789 * 2.718281828459045"));
|
||||||
//Assert.assertEquals("e", tp.process("2.718281828459045"));
|
//Assert.assertEquals("t11e", tp.process("t11*2.718281828459045"));
|
||||||
//Assert.assertEquals("tee", tp.process("t2.718281828459045*2.718281828459045"));
|
//Assert.assertEquals("e", tp.process("2.718281828459045"));
|
||||||
|
//Assert.assertEquals("tee", tp.process("t2.718281828459045*2.718281828459045"));
|
||||||
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t2.718281828459045", "2"));
|
|
||||||
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String)null));
|
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t2.718281828459045", "2"));
|
||||||
//Assert.assertEquals("t2.718281828459045e", tp.process("t2.718281828459045*2.718281828459045"));
|
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String)null));
|
||||||
//Assert.assertEquals("ee", tp.process("2.718281828459045*2.718281828459045"));
|
//Assert.assertEquals("t2.718281828459045e", tp.process("t2.718281828459045*2.718281828459045"));
|
||||||
Assert.assertEquals("t×", tp.process("t*"));
|
//Assert.assertEquals("ee", tp.process("2.718281828459045*2.718281828459045"));
|
||||||
Assert.assertEquals("×t", tp.process("*t"));
|
Assert.assertEquals("t×", tp.process("t*"));
|
||||||
Assert.assertEquals("t2", tp.process("t*2"));
|
Assert.assertEquals("×t", tp.process("*t"));
|
||||||
Assert.assertEquals("2t", tp.process("2*t"));
|
Assert.assertEquals("t2", tp.process("t*2"));
|
||||||
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String) null));
|
Assert.assertEquals("2t", tp.process("2*t"));
|
||||||
Assert.assertEquals("t×", tp.process("t*"));
|
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String) null));
|
||||||
Assert.assertEquals("×t", tp.process("*t"));
|
Assert.assertEquals("t×", tp.process("t*"));
|
||||||
|
Assert.assertEquals("×t", tp.process("*t"));
|
||||||
Assert.assertEquals("t2", tp.process("t*2"));
|
|
||||||
Assert.assertEquals("2t", tp.process("2*t"));
|
Assert.assertEquals("t2", tp.process("t*2"));
|
||||||
|
Assert.assertEquals("2t", tp.process("2*t"));
|
||||||
Assert.assertEquals("t^2×2", tp.process("t^2*2"));
|
|
||||||
Assert.assertEquals("2t^2", tp.process("2*t^2"));
|
Assert.assertEquals("t^2×2", tp.process("t^2*2"));
|
||||||
|
Assert.assertEquals("2t^2", tp.process("2*t^2"));
|
||||||
Assert.assertEquals("t^[2×2t]", tp.process("t^[2*2*t]"));
|
|
||||||
Assert.assertEquals("2t^2[2t]", tp.process("2*t^2[2*t]"));
|
Assert.assertEquals("t^[2×2t]", tp.process("t^[2*2*t]"));
|
||||||
|
Assert.assertEquals("2t^2[2t]", tp.process("2*t^2[2*t]"));
|
||||||
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("k", (String) null));
|
|
||||||
Assert.assertEquals("(t+2k)[k+2t]", tp.process("(t+2*k)*[k+2*t]"));
|
CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("k", (String) null));
|
||||||
Assert.assertEquals("(te+2k)e[k+2te]", tp.process("(t*e+2*k)*e*[k+2*t*e]"));
|
Assert.assertEquals("(t+2k)[k+2t]", tp.process("(t+2*k)*[k+2*t]"));
|
||||||
|
Assert.assertEquals("(te+2k)e[k+2te]", tp.process("(t*e+2*k)*e*[k+2*t*e]"));
|
||||||
|
|
||||||
Assert.assertEquals("tlog(3)", tp.process("t*log(3)"));
|
|
||||||
Assert.assertEquals("t√(3)", tp.process("t*√(3)"));
|
Assert.assertEquals("tlog(3)", tp.process("t*log(3)"));
|
||||||
Assert.assertEquals("20x", tp.process("20*x"));
|
Assert.assertEquals("t√(3)", tp.process("t*√(3)"));
|
||||||
Assert.assertEquals("20x", tp.process("20x"));
|
Assert.assertEquals("20x", tp.process("20*x"));
|
||||||
Assert.assertEquals("2×0x3", tp.process("2*0x3"));
|
Assert.assertEquals("20x", tp.process("20x"));
|
||||||
Assert.assertEquals("2×0x:3", tp.process("2*0x:3"));
|
Assert.assertEquals("2×0x3", tp.process("2*0x3"));
|
||||||
}
|
Assert.assertEquals("2×0x:3", tp.process("2*0x:3"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -10,6 +10,8 @@ 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.jscl.JsclOperation;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
import org.solovyev.common.Converter;
|
import org.solovyev.common.Converter;
|
||||||
|
|
||||||
@ -98,11 +100,11 @@ public class NumeralBaseTest {
|
|||||||
final String bin = "0b:" + line[2].toUpperCase();
|
final String bin = "0b:" + line[2].toUpperCase();
|
||||||
|
|
||||||
final String decExpression = converter.convert(dec);
|
final String decExpression = converter.convert(dec);
|
||||||
final String decResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, decExpression).getResult();
|
final String decResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, decExpression).getStringResult();
|
||||||
final String hexExpression = converter.convert(hex);
|
final String hexExpression = converter.convert(hex);
|
||||||
final String hexResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, hexExpression).getResult();
|
final String hexResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, hexExpression).getStringResult();
|
||||||
final String binExpression = converter.convert(bin);
|
final String binExpression = converter.convert(bin);
|
||||||
final String binResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, binExpression).getResult();
|
final String binResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, binExpression).getStringResult();
|
||||||
|
|
||||||
Assert.assertEquals("dec-hex: " + decExpression + " : " + hexExpression, decResult, hexResult);
|
Assert.assertEquals("dec-hex: " + decExpression + " : " + hexExpression, decResult, hexResult);
|
||||||
Assert.assertEquals("dec-bin: " + decExpression + " : " + binExpression, decResult, binResult);
|
Assert.assertEquals("dec-bin: " + decExpression + " : " + binExpression, decResult, binResult);
|
||||||
|
@ -1,161 +1,165 @@
|
|||||||
/*
|
/*
|
||||||
* 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.model;
|
||||||
|
|
||||||
import jscl.JsclMathEngine;
|
import jscl.JsclMathEngine;
|
||||||
import jscl.NumeralBase;
|
import jscl.NumeralBase;
|
||||||
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.CalculatorParseException;
|
||||||
/**
|
import org.solovyev.android.calculator.PreparedExpression;
|
||||||
* User: serso
|
import org.solovyev.android.calculator.ToJsclTextProcessor;
|
||||||
* Date: 9/26/11
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
* Time: 12:13 PM
|
|
||||||
*/
|
/**
|
||||||
public class ToJsclTextProcessorTest {
|
* User: serso
|
||||||
|
* Date: 9/26/11
|
||||||
@BeforeClass
|
* Time: 12:13 PM
|
||||||
public static void setUp() throws Exception {
|
*/
|
||||||
CalculatorEngine.instance.init(null, null);
|
public class ToJsclTextProcessorTest {
|
||||||
}
|
|
||||||
|
@BeforeClass
|
||||||
@Test
|
public static void setUp() throws Exception {
|
||||||
public void testSpecialCases() throws CalculatorParseException {
|
CalculatorEngine.instance.init(null, null);
|
||||||
final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
|
}
|
||||||
Assert.assertEquals( "3^E10", preprocessor.process("3^E10").toString());
|
|
||||||
}
|
@Test
|
||||||
|
public void testSpecialCases() throws CalculatorParseException {
|
||||||
@Test
|
final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
|
||||||
public void testProcess() throws Exception {
|
Assert.assertEquals( "3^E10", preprocessor.process("3^E10").toString());
|
||||||
final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
|
}
|
||||||
|
|
||||||
Assert.assertEquals( "", preprocessor.process("").toString());
|
@Test
|
||||||
Assert.assertEquals( "()", preprocessor.process("[]").toString());
|
public void testProcess() throws Exception {
|
||||||
Assert.assertEquals( "()*()", preprocessor.process("[][]").toString());
|
final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
|
||||||
Assert.assertEquals( "()*(1)", preprocessor.process("[][1]").toString());
|
|
||||||
Assert.assertEquals( "(0)*(1)", preprocessor.process("[0][1]").toString());
|
Assert.assertEquals( "", preprocessor.process("").toString());
|
||||||
Assert.assertEquals( "(0)*(1E)", preprocessor.process("[0][1E]").toString());
|
Assert.assertEquals( "()", preprocessor.process("[]").toString());
|
||||||
Assert.assertEquals( "(0)*(1E1)", preprocessor.process("[0][1E1]").toString());
|
Assert.assertEquals( "()*()", preprocessor.process("[][]").toString());
|
||||||
Assert.assertEquals( "(0)*(1E-1)", preprocessor.process("[0][1E-1]").toString());
|
Assert.assertEquals( "()*(1)", preprocessor.process("[][1]").toString());
|
||||||
Assert.assertEquals( "(0)*(1.E-1)", preprocessor.process("[0][1.E-1]").toString());
|
Assert.assertEquals( "(0)*(1)", preprocessor.process("[0][1]").toString());
|
||||||
Assert.assertEquals( "(0)*(2*E-1)", preprocessor.process("[0][2*E-1]").toString());
|
Assert.assertEquals( "(0)*(1E)", preprocessor.process("[0][1E]").toString());
|
||||||
Assert.assertEquals( "(0)*ln(1)*(2*E-1)", preprocessor.process("[0]ln(1)[2*E-1]").toString());
|
Assert.assertEquals( "(0)*(1E1)", preprocessor.process("[0][1E1]").toString());
|
||||||
Assert.assertEquals( "sin(4)*asin(0.5)*√(2)", preprocessor.process("sin(4)asin(0.5)√(2)").toString());
|
Assert.assertEquals( "(0)*(1E-1)", preprocessor.process("[0][1E-1]").toString());
|
||||||
Assert.assertEquals( "sin(4)*cos(5)", preprocessor.process("sin(4)cos(5)").toString());
|
Assert.assertEquals( "(0)*(1.E-1)", preprocessor.process("[0][1.E-1]").toString());
|
||||||
Assert.assertEquals( "π*sin(4)*π*cos(√(5))", preprocessor.process("πsin(4)πcos(√(5))").toString());
|
Assert.assertEquals( "(0)*(2*E-1)", preprocessor.process("[0][2*E-1]").toString());
|
||||||
Assert.assertEquals( "π*sin(4)+π*cos(√(5))", preprocessor.process("πsin(4)+πcos(√(5))").toString());
|
Assert.assertEquals( "(0)*ln(1)*(2*E-1)", preprocessor.process("[0]ln(1)[2*E-1]").toString());
|
||||||
Assert.assertEquals( "π*sin(4)+π*cos(√(5+(√(-1))))", preprocessor.process("πsin(4)+πcos(√(5+i))").toString());
|
Assert.assertEquals( "sin(4)*asin(0.5)*√(2)", preprocessor.process("sin(4)asin(0.5)√(2)").toString());
|
||||||
Assert.assertEquals( "π*sin(4.01)+π*cos(√(5+(√(-1))))", preprocessor.process("πsin(4.01)+πcos(√(5+i))").toString());
|
Assert.assertEquals( "sin(4)*cos(5)", preprocessor.process("sin(4)cos(5)").toString());
|
||||||
Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))").toString());
|
Assert.assertEquals( "π*sin(4)*π*cos(√(5))", preprocessor.process("πsin(4)πcos(√(5))").toString());
|
||||||
Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))E2", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))E2").toString());
|
Assert.assertEquals( "π*sin(4)+π*cos(√(5))", preprocessor.process("πsin(4)+πcos(√(5))").toString());
|
||||||
Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))E-2", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))E-2").toString());
|
Assert.assertEquals( "π*sin(4)+π*cos(√(5+(√(-1))))", preprocessor.process("πsin(4)+πcos(√(5+i))").toString());
|
||||||
Assert.assertEquals( "E2", preprocessor.process("E2").toString());
|
Assert.assertEquals( "π*sin(4.01)+π*cos(√(5+(√(-1))))", preprocessor.process("πsin(4.01)+πcos(√(5+i))").toString());
|
||||||
Assert.assertEquals( "E-2", preprocessor.process("E-2").toString());
|
Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))").toString());
|
||||||
Assert.assertEquals( "E-1/2", preprocessor.process("E-1/2").toString());
|
Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))E2", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))E2").toString());
|
||||||
Assert.assertEquals( "E-1.2", preprocessor.process("E-1.2").toString());
|
Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))E-2", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))E-2").toString());
|
||||||
Assert.assertEquals( "E+1.2", preprocessor.process("E+1.2").toString());
|
Assert.assertEquals( "E2", preprocessor.process("E2").toString());
|
||||||
Assert.assertEquals( "E(-1.2)", preprocessor.process("E(-1.2)").toString());
|
Assert.assertEquals( "E-2", preprocessor.process("E-2").toString());
|
||||||
Assert.assertEquals( "EE", preprocessor.process("EE").toString());
|
Assert.assertEquals( "E-1/2", preprocessor.process("E-1/2").toString());
|
||||||
|
Assert.assertEquals( "E-1.2", preprocessor.process("E-1.2").toString());
|
||||||
try {
|
Assert.assertEquals( "E+1.2", preprocessor.process("E+1.2").toString());
|
||||||
CalculatorEngine.instance.getEngine().setNumeralBase(NumeralBase.hex);
|
Assert.assertEquals( "E(-1.2)", preprocessor.process("E(-1.2)").toString());
|
||||||
Assert.assertEquals( "22F*exp(F)", preprocessor.process("22Fexp(F)").toString());
|
Assert.assertEquals( "EE", preprocessor.process("EE").toString());
|
||||||
} finally {
|
|
||||||
CalculatorEngine.instance.getEngine().setNumeralBase(NumeralBase.dec);
|
try {
|
||||||
}
|
CalculatorEngine.instance.getEngine().setNumeralBase(NumeralBase.hex);
|
||||||
Assert.assertEquals( "0x:ABCDEF", preprocessor.process("0x:ABCDEF").toString());
|
Assert.assertEquals( "22F*exp(F)", preprocessor.process("22Fexp(F)").toString());
|
||||||
Assert.assertEquals( "0x:ABCDEF", preprocessor.process("0x:A BC DEF").toString());
|
} finally {
|
||||||
Assert.assertEquals( "0x:ABCDEF", preprocessor.process("0x:A BC DEF").toString());
|
CalculatorEngine.instance.getEngine().setNumeralBase(NumeralBase.dec);
|
||||||
Assert.assertEquals( "0x:ABCDEF*0*x", preprocessor.process("0x:A BC DEF*0x").toString());
|
}
|
||||||
Assert.assertEquals( "0x:ABCDEF001*0*x", preprocessor.process("0x:A BC DEF001*0x").toString());
|
Assert.assertEquals( "0x:ABCDEF", preprocessor.process("0x:ABCDEF").toString());
|
||||||
Assert.assertEquals( "0x:ABCDEF001*0*c", preprocessor.process("0x:A BC DEF001*0c").toString());
|
Assert.assertEquals( "0x:ABCDEF", preprocessor.process("0x:A BC DEF").toString());
|
||||||
Assert.assertEquals( "0x:ABCDEF001*c", preprocessor.process("0x:A BC DEF001*c").toString());
|
Assert.assertEquals( "0x:ABCDEF", preprocessor.process("0x:A BC DEF").toString());
|
||||||
Assert.assertEquals( "0b:1101", preprocessor.process("0b:1101").toString());
|
Assert.assertEquals( "0x:ABCDEF*0*x", preprocessor.process("0x:A BC DEF*0x").toString());
|
||||||
Assert.assertEquals( "0x:1C", preprocessor.process("0x:1C").toString());
|
Assert.assertEquals( "0x:ABCDEF001*0*x", preprocessor.process("0x:A BC DEF001*0x").toString());
|
||||||
Assert.assertEquals( "0x:1C", preprocessor.process(" 0x:1C").toString());
|
Assert.assertEquals( "0x:ABCDEF001*0*c", preprocessor.process("0x:A BC DEF001*0c").toString());
|
||||||
Assert.assertEquals( "0x:1C*0x:1C*sin(0x:1C)-0b:1101+√(0x:1C)+exp(0x:1C)", preprocessor.process("0x:1C*0x:1C * sin(0x:1C) - 0b:1101 + √(0x:1C) + exp ( 0x:1C)").toString());
|
Assert.assertEquals( "0x:ABCDEF001*c", preprocessor.process("0x:A BC DEF001*c").toString());
|
||||||
Assert.assertEquals( "0x:1C*0x:1C*sin(0x:1C)-0b:1101+√(0x:1C)+exp(0x:1C)", preprocessor.process("0x:1C*0x:1C * sin(0x:1C) - 0b:1101 + √(0x:1C) + exp ( 0x:1C)").toString());
|
Assert.assertEquals( "0b:1101", preprocessor.process("0b:1101").toString());
|
||||||
|
Assert.assertEquals( "0x:1C", preprocessor.process("0x:1C").toString());
|
||||||
try {
|
Assert.assertEquals( "0x:1C", preprocessor.process(" 0x:1C").toString());
|
||||||
preprocessor.process("ln()");
|
Assert.assertEquals( "0x:1C*0x:1C*sin(0x:1C)-0b:1101+√(0x:1C)+exp(0x:1C)", preprocessor.process("0x:1C*0x:1C * sin(0x:1C) - 0b:1101 + √(0x:1C) + exp ( 0x:1C)").toString());
|
||||||
Assert.fail();
|
Assert.assertEquals( "0x:1C*0x:1C*sin(0x:1C)-0b:1101+√(0x:1C)+exp(0x:1C)", preprocessor.process("0x:1C*0x:1C * sin(0x:1C) - 0b:1101 + √(0x:1C) + exp ( 0x:1C)").toString());
|
||||||
} catch (CalculatorParseException e) {
|
|
||||||
}
|
try {
|
||||||
try {
|
preprocessor.process("ln()");
|
||||||
preprocessor.process("ln()ln()");
|
Assert.fail();
|
||||||
Assert.fail();
|
} catch (CalculatorParseException e) {
|
||||||
} catch (CalculatorParseException e) {
|
}
|
||||||
}
|
try {
|
||||||
|
preprocessor.process("ln()ln()");
|
||||||
try {
|
Assert.fail();
|
||||||
preprocessor.process("eln()eln()ln()ln()ln()e");
|
} catch (CalculatorParseException e) {
|
||||||
Assert.fail();
|
}
|
||||||
} catch (CalculatorParseException e) {
|
|
||||||
}
|
try {
|
||||||
|
preprocessor.process("eln()eln()ln()ln()ln()e");
|
||||||
try {
|
Assert.fail();
|
||||||
preprocessor.process("ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln()))))))))))))))");
|
} catch (CalculatorParseException e) {
|
||||||
Assert.fail();
|
}
|
||||||
} catch (CalculatorParseException e) {
|
|
||||||
}
|
try {
|
||||||
|
preprocessor.process("ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln()))))))))))))))");
|
||||||
try {
|
Assert.fail();
|
||||||
preprocessor.process("cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos(cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos())))))))))))))))))))))))))))))))))))))");
|
} catch (CalculatorParseException e) {
|
||||||
Assert.fail();
|
}
|
||||||
} catch (CalculatorParseException e) {
|
|
||||||
}
|
try {
|
||||||
}
|
preprocessor.process("cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos(cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos())))))))))))))))))))))))))))))))))))))");
|
||||||
|
Assert.fail();
|
||||||
@Test
|
} catch (CalculatorParseException e) {
|
||||||
public void testDegrees() throws Exception {
|
}
|
||||||
final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
|
}
|
||||||
|
|
||||||
Assert.assertEquals( "", preprocessor.process("").toString());
|
@Test
|
||||||
/* try {
|
public void testDegrees() throws Exception {
|
||||||
Assert.assertEquals( "π/180", preprocessor.process("°").toString());
|
final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
|
||||||
} catch (ParseException e) {
|
|
||||||
if ( !e.getMessage().startsWith("Could not find start of prefix") ){
|
Assert.assertEquals( "", preprocessor.process("").toString());
|
||||||
junit.framework.Assert.fail();
|
/* try {
|
||||||
}
|
Assert.assertEquals( "π/180", preprocessor.process("°").toString());
|
||||||
}
|
} catch (ParseException e) {
|
||||||
Assert.assertEquals( "1*π/180", preprocessor.process("1°").toString());
|
if ( !e.getMessage().startsWith("Could not find start of prefix") ){
|
||||||
Assert.assertEquals( "20.0*π/180", preprocessor.process("20.0°").toString());
|
junit.framework.Assert.fail();
|
||||||
Assert.assertEquals( "sin(30*π/180)", preprocessor.process("sin(30°)").toString());
|
}
|
||||||
Assert.assertEquals( "asin(sin(π/6))*π/180", preprocessor.process("asin(sin(π/6))°").toString());
|
}
|
||||||
Assert.assertEquals( "1*π/180*sin(1)", preprocessor.process("1°sin(1)").toString());
|
Assert.assertEquals( "1*π/180", preprocessor.process("1°").toString());
|
||||||
try {
|
Assert.assertEquals( "20.0*π/180", preprocessor.process("20.0°").toString());
|
||||||
Assert.assertEquals( "1*π/180^sin(1)", preprocessor.process("1°^sin(1)").toString());
|
Assert.assertEquals( "sin(30*π/180)", preprocessor.process("sin(30°)").toString());
|
||||||
junit.framework.Assert.fail();
|
Assert.assertEquals( "asin(sin(π/6))*π/180", preprocessor.process("asin(sin(π/6))°").toString());
|
||||||
} catch (ParseException e) {
|
Assert.assertEquals( "1*π/180*sin(1)", preprocessor.process("1°sin(1)").toString());
|
||||||
if ( !e.getMessage().equals("Power operation after postfix function is currently unsupported!") ) {
|
try {
|
||||||
junit.framework.Assert.fail();
|
Assert.assertEquals( "1*π/180^sin(1)", preprocessor.process("1°^sin(1)").toString());
|
||||||
}
|
junit.framework.Assert.fail();
|
||||||
}*/
|
} catch (ParseException e) {
|
||||||
|
if ( !e.getMessage().equals("Power operation after postfix function is currently unsupported!") ) {
|
||||||
}
|
junit.framework.Assert.fail();
|
||||||
|
}
|
||||||
@Test
|
}*/
|
||||||
public void testPostfixFunction() throws Exception {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNumeralBases() throws Exception {
|
public void testPostfixFunction() throws Exception {
|
||||||
final TextProcessor<PreparedExpression, String> processor = ToJsclTextProcessor.getInstance();
|
}
|
||||||
|
|
||||||
final NumeralBase defaultNumeralBase = JsclMathEngine.instance.getNumeralBase();
|
@Test
|
||||||
try{
|
public void testNumeralBases() throws Exception {
|
||||||
JsclMathEngine.instance.setNumeralBase(NumeralBase.bin);
|
final TextProcessor<PreparedExpression, String> processor = ToJsclTextProcessor.getInstance();
|
||||||
Assert.assertEquals("101", JsclMathEngine.instance.evaluate("10+11"));
|
|
||||||
|
final NumeralBase defaultNumeralBase = JsclMathEngine.instance.getNumeralBase();
|
||||||
JsclMathEngine.instance.setNumeralBase(NumeralBase.hex);
|
try{
|
||||||
Assert.assertEquals("56CE+CAD", processor.process("56CE+CAD").getExpression());
|
JsclMathEngine.instance.setNumeralBase(NumeralBase.bin);
|
||||||
} finally {
|
Assert.assertEquals("101", JsclMathEngine.instance.evaluate("10+11"));
|
||||||
JsclMathEngine.instance.setNumeralBase(defaultNumeralBase);
|
|
||||||
}
|
JsclMathEngine.instance.setNumeralBase(NumeralBase.hex);
|
||||||
}
|
Assert.assertEquals("56CE+CAD", processor.process("56CE+CAD").getExpression());
|
||||||
}
|
} finally {
|
||||||
|
JsclMathEngine.instance.setNumeralBase(defaultNumeralBase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
37
pom.xml
37
pom.xml
@ -15,6 +15,7 @@
|
|||||||
<module>calculatorpp</module>
|
<module>calculatorpp</module>
|
||||||
<module>calculatorpp-service</module>
|
<module>calculatorpp-service</module>
|
||||||
<module>calculatorpp-test</module>
|
<module>calculatorpp-test</module>
|
||||||
|
<module>calculatorpp-core</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@ -71,6 +72,18 @@
|
|||||||
<version>1.0.0</version>
|
<version>1.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.solovyev</groupId>
|
||||||
|
<artifactId>jscl</artifactId>
|
||||||
|
<version>0.0.2</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>xercesImpl</artifactId>
|
||||||
|
<groupId>xerces</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.solovyev.android</groupId>
|
<groupId>org.solovyev.android</groupId>
|
||||||
<artifactId>android-common-other</artifactId>
|
<artifactId>android-common-other</artifactId>
|
||||||
@ -81,7 +94,13 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.8.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.intellij</groupId>
|
||||||
|
<artifactId>annotations</artifactId>
|
||||||
|
<version>7.0.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -103,6 +122,22 @@
|
|||||||
<version>11.0.2</version>
|
<version>11.0.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.simpleframework</groupId>
|
||||||
|
<artifactId>simple-xml</artifactId>
|
||||||
|
<version>2.6.1</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>stax-api</artifactId>
|
||||||
|
<groupId>stax</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>xpp3</artifactId>
|
||||||
|
<groupId>xpp3</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user